clipsruby 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/clipsruby/agenda.c +1373 -0
- data/ext/clipsruby/agenda.h +169 -0
- data/ext/clipsruby/analysis.c +1142 -0
- data/ext/clipsruby/analysis.h +61 -0
- data/ext/clipsruby/argacces.c +526 -0
- data/ext/clipsruby/argacces.h +77 -0
- data/ext/clipsruby/bload.c +884 -0
- data/ext/clipsruby/bload.h +94 -0
- data/ext/clipsruby/bmathfun.c +557 -0
- data/ext/clipsruby/bmathfun.h +66 -0
- data/ext/clipsruby/bsave.c +634 -0
- data/ext/clipsruby/bsave.h +130 -0
- data/ext/clipsruby/classcom.c +976 -0
- data/ext/clipsruby/classcom.h +115 -0
- data/ext/clipsruby/classexm.c +1376 -0
- data/ext/clipsruby/classexm.h +97 -0
- data/ext/clipsruby/classfun.c +1392 -0
- data/ext/clipsruby/classfun.h +164 -0
- data/ext/clipsruby/classinf.c +1245 -0
- data/ext/clipsruby/classinf.h +94 -0
- data/ext/clipsruby/classini.c +843 -0
- data/ext/clipsruby/classini.h +75 -0
- data/ext/clipsruby/classpsr.c +957 -0
- data/ext/clipsruby/classpsr.h +73 -0
- data/ext/clipsruby/clips.h +133 -0
- data/ext/clipsruby/clipsruby.c +619 -0
- data/ext/clipsruby/clsltpsr.c +931 -0
- data/ext/clipsruby/clsltpsr.h +72 -0
- data/ext/clipsruby/commline.c +1217 -0
- data/ext/clipsruby/commline.h +131 -0
- data/ext/clipsruby/conscomp.c +1593 -0
- data/ext/clipsruby/conscomp.h +150 -0
- data/ext/clipsruby/constant.h +264 -0
- data/ext/clipsruby/constrct.c +1090 -0
- data/ext/clipsruby/constrct.h +216 -0
- data/ext/clipsruby/constrnt.c +554 -0
- data/ext/clipsruby/constrnt.h +132 -0
- data/ext/clipsruby/crstrtgy.c +1088 -0
- data/ext/clipsruby/crstrtgy.h +85 -0
- data/ext/clipsruby/cstrcbin.c +185 -0
- data/ext/clipsruby/cstrcbin.h +61 -0
- data/ext/clipsruby/cstrccmp.h +43 -0
- data/ext/clipsruby/cstrccom.c +1791 -0
- data/ext/clipsruby/cstrccom.h +115 -0
- data/ext/clipsruby/cstrcpsr.c +835 -0
- data/ext/clipsruby/cstrcpsr.h +97 -0
- data/ext/clipsruby/cstrnbin.c +282 -0
- data/ext/clipsruby/cstrnbin.h +55 -0
- data/ext/clipsruby/cstrnchk.c +826 -0
- data/ext/clipsruby/cstrnchk.h +91 -0
- data/ext/clipsruby/cstrncmp.c +238 -0
- data/ext/clipsruby/cstrncmp.h +57 -0
- data/ext/clipsruby/cstrnops.c +1176 -0
- data/ext/clipsruby/cstrnops.h +47 -0
- data/ext/clipsruby/cstrnpsr.c +1394 -0
- data/ext/clipsruby/cstrnpsr.h +88 -0
- data/ext/clipsruby/cstrnutl.c +564 -0
- data/ext/clipsruby/cstrnutl.h +54 -0
- data/ext/clipsruby/default.c +454 -0
- data/ext/clipsruby/default.h +57 -0
- data/ext/clipsruby/defins.c +971 -0
- data/ext/clipsruby/defins.h +127 -0
- data/ext/clipsruby/developr.c +677 -0
- data/ext/clipsruby/developr.h +69 -0
- data/ext/clipsruby/dffctbin.c +477 -0
- data/ext/clipsruby/dffctbin.h +76 -0
- data/ext/clipsruby/dffctbsc.c +308 -0
- data/ext/clipsruby/dffctbsc.h +72 -0
- data/ext/clipsruby/dffctcmp.c +297 -0
- data/ext/clipsruby/dffctcmp.h +44 -0
- data/ext/clipsruby/dffctdef.c +364 -0
- data/ext/clipsruby/dffctdef.h +104 -0
- data/ext/clipsruby/dffctpsr.c +179 -0
- data/ext/clipsruby/dffctpsr.h +49 -0
- data/ext/clipsruby/dffnxbin.c +520 -0
- data/ext/clipsruby/dffnxbin.h +67 -0
- data/ext/clipsruby/dffnxcmp.c +378 -0
- data/ext/clipsruby/dffnxcmp.h +54 -0
- data/ext/clipsruby/dffnxexe.c +241 -0
- data/ext/clipsruby/dffnxexe.h +58 -0
- data/ext/clipsruby/dffnxfun.c +1192 -0
- data/ext/clipsruby/dffnxfun.h +155 -0
- data/ext/clipsruby/dffnxpsr.c +514 -0
- data/ext/clipsruby/dffnxpsr.h +57 -0
- data/ext/clipsruby/dfinsbin.c +509 -0
- data/ext/clipsruby/dfinsbin.h +66 -0
- data/ext/clipsruby/dfinscmp.c +345 -0
- data/ext/clipsruby/dfinscmp.h +48 -0
- data/ext/clipsruby/drive.c +1191 -0
- data/ext/clipsruby/drive.h +65 -0
- data/ext/clipsruby/emathfun.c +1213 -0
- data/ext/clipsruby/emathfun.h +99 -0
- data/ext/clipsruby/engine.c +1568 -0
- data/ext/clipsruby/engine.h +203 -0
- data/ext/clipsruby/entities.h +276 -0
- data/ext/clipsruby/envrnbld.c +514 -0
- data/ext/clipsruby/envrnbld.h +40 -0
- data/ext/clipsruby/envrnmnt.c +257 -0
- data/ext/clipsruby/envrnmnt.h +112 -0
- data/ext/clipsruby/evaluatn.c +1736 -0
- data/ext/clipsruby/evaluatn.h +211 -0
- data/ext/clipsruby/expressn.c +494 -0
- data/ext/clipsruby/expressn.h +154 -0
- data/ext/clipsruby/exprnbin.c +538 -0
- data/ext/clipsruby/exprnbin.h +60 -0
- data/ext/clipsruby/exprnops.c +564 -0
- data/ext/clipsruby/exprnops.h +67 -0
- data/ext/clipsruby/exprnpsr.c +1112 -0
- data/ext/clipsruby/exprnpsr.h +98 -0
- data/ext/clipsruby/extconf.rb +2 -0
- data/ext/clipsruby/extnfunc.c +1015 -0
- data/ext/clipsruby/extnfunc.h +157 -0
- data/ext/clipsruby/factbin.c +447 -0
- data/ext/clipsruby/factbin.h +56 -0
- data/ext/clipsruby/factbld.c +1035 -0
- data/ext/clipsruby/factbld.h +63 -0
- data/ext/clipsruby/factcmp.c +386 -0
- data/ext/clipsruby/factcmp.h +46 -0
- data/ext/clipsruby/factcom.c +759 -0
- data/ext/clipsruby/factcom.h +80 -0
- data/ext/clipsruby/factfile.c +1761 -0
- data/ext/clipsruby/factfile.h +54 -0
- data/ext/clipsruby/factfun.c +682 -0
- data/ext/clipsruby/factfun.h +77 -0
- data/ext/clipsruby/factgen.c +1305 -0
- data/ext/clipsruby/factgen.h +229 -0
- data/ext/clipsruby/facthsh.c +438 -0
- data/ext/clipsruby/facthsh.h +81 -0
- data/ext/clipsruby/factlhs.c +250 -0
- data/ext/clipsruby/factlhs.h +54 -0
- data/ext/clipsruby/factmch.c +905 -0
- data/ext/clipsruby/factmch.h +68 -0
- data/ext/clipsruby/factmngr.c +3373 -0
- data/ext/clipsruby/factmngr.h +325 -0
- data/ext/clipsruby/factprt.c +498 -0
- data/ext/clipsruby/factprt.h +60 -0
- data/ext/clipsruby/factqpsr.c +796 -0
- data/ext/clipsruby/factqpsr.h +61 -0
- data/ext/clipsruby/factqury.c +1267 -0
- data/ext/clipsruby/factqury.h +112 -0
- data/ext/clipsruby/factrete.c +978 -0
- data/ext/clipsruby/factrete.h +70 -0
- data/ext/clipsruby/factrhs.c +667 -0
- data/ext/clipsruby/factrhs.h +55 -0
- data/ext/clipsruby/filecom.c +353 -0
- data/ext/clipsruby/filecom.h +137 -0
- data/ext/clipsruby/filertr.c +481 -0
- data/ext/clipsruby/filertr.h +94 -0
- data/ext/clipsruby/fileutil.c +1020 -0
- data/ext/clipsruby/fileutil.h +50 -0
- data/ext/clipsruby/generate.c +1079 -0
- data/ext/clipsruby/generate.h +57 -0
- data/ext/clipsruby/genrcbin.c +902 -0
- data/ext/clipsruby/genrcbin.h +69 -0
- data/ext/clipsruby/genrccmp.c +640 -0
- data/ext/clipsruby/genrccmp.h +59 -0
- data/ext/clipsruby/genrccom.c +2017 -0
- data/ext/clipsruby/genrccom.h +119 -0
- data/ext/clipsruby/genrcexe.c +737 -0
- data/ext/clipsruby/genrcexe.h +73 -0
- data/ext/clipsruby/genrcfun.c +890 -0
- data/ext/clipsruby/genrcfun.h +185 -0
- data/ext/clipsruby/genrcpsr.c +1618 -0
- data/ext/clipsruby/genrcpsr.h +80 -0
- data/ext/clipsruby/globlbin.c +458 -0
- data/ext/clipsruby/globlbin.h +71 -0
- data/ext/clipsruby/globlbsc.c +361 -0
- data/ext/clipsruby/globlbsc.h +83 -0
- data/ext/clipsruby/globlcmp.c +330 -0
- data/ext/clipsruby/globlcmp.h +52 -0
- data/ext/clipsruby/globlcom.c +289 -0
- data/ext/clipsruby/globlcom.h +63 -0
- data/ext/clipsruby/globldef.c +1087 -0
- data/ext/clipsruby/globldef.h +151 -0
- data/ext/clipsruby/globlpsr.c +530 -0
- data/ext/clipsruby/globlpsr.h +59 -0
- data/ext/clipsruby/immthpsr.c +431 -0
- data/ext/clipsruby/immthpsr.h +55 -0
- data/ext/clipsruby/incrrset.c +530 -0
- data/ext/clipsruby/incrrset.h +73 -0
- data/ext/clipsruby/inherpsr.c +850 -0
- data/ext/clipsruby/inherpsr.h +52 -0
- data/ext/clipsruby/inscom.c +2076 -0
- data/ext/clipsruby/inscom.h +182 -0
- data/ext/clipsruby/insfile.c +1764 -0
- data/ext/clipsruby/insfile.h +96 -0
- data/ext/clipsruby/insfun.c +1451 -0
- data/ext/clipsruby/insfun.h +134 -0
- data/ext/clipsruby/insmngr.c +2550 -0
- data/ext/clipsruby/insmngr.h +125 -0
- data/ext/clipsruby/insmoddp.c +1041 -0
- data/ext/clipsruby/insmoddp.h +91 -0
- data/ext/clipsruby/insmult.c +804 -0
- data/ext/clipsruby/insmult.h +62 -0
- data/ext/clipsruby/inspsr.c +602 -0
- data/ext/clipsruby/inspsr.h +60 -0
- data/ext/clipsruby/insquery.c +1278 -0
- data/ext/clipsruby/insquery.h +115 -0
- data/ext/clipsruby/insqypsr.c +729 -0
- data/ext/clipsruby/insqypsr.h +63 -0
- data/ext/clipsruby/iofun.c +2045 -0
- data/ext/clipsruby/iofun.h +116 -0
- data/ext/clipsruby/lgcldpnd.c +644 -0
- data/ext/clipsruby/lgcldpnd.h +75 -0
- data/ext/clipsruby/main.c +112 -0
- data/ext/clipsruby/match.h +142 -0
- data/ext/clipsruby/memalloc.c +481 -0
- data/ext/clipsruby/memalloc.h +197 -0
- data/ext/clipsruby/miscfun.c +1801 -0
- data/ext/clipsruby/miscfun.h +132 -0
- data/ext/clipsruby/modulbin.c +607 -0
- data/ext/clipsruby/modulbin.h +84 -0
- data/ext/clipsruby/modulbsc.c +347 -0
- data/ext/clipsruby/modulbsc.h +67 -0
- data/ext/clipsruby/modulcmp.c +499 -0
- data/ext/clipsruby/modulcmp.h +54 -0
- data/ext/clipsruby/moduldef.c +817 -0
- data/ext/clipsruby/moduldef.h +271 -0
- data/ext/clipsruby/modulpsr.c +1150 -0
- data/ext/clipsruby/modulpsr.h +69 -0
- data/ext/clipsruby/modulutl.c +1036 -0
- data/ext/clipsruby/modulutl.h +84 -0
- data/ext/clipsruby/msgcom.c +1221 -0
- data/ext/clipsruby/msgcom.h +125 -0
- data/ext/clipsruby/msgfun.c +1076 -0
- data/ext/clipsruby/msgfun.h +118 -0
- data/ext/clipsruby/msgpass.c +1441 -0
- data/ext/clipsruby/msgpass.h +103 -0
- data/ext/clipsruby/msgpsr.c +698 -0
- data/ext/clipsruby/msgpsr.h +73 -0
- data/ext/clipsruby/multifld.c +1404 -0
- data/ext/clipsruby/multifld.h +130 -0
- data/ext/clipsruby/multifun.c +2182 -0
- data/ext/clipsruby/multifun.h +102 -0
- data/ext/clipsruby/network.h +142 -0
- data/ext/clipsruby/objbin.c +1522 -0
- data/ext/clipsruby/objbin.h +79 -0
- data/ext/clipsruby/objcmp.c +1507 -0
- data/ext/clipsruby/objcmp.h +71 -0
- data/ext/clipsruby/object.h +260 -0
- data/ext/clipsruby/objrtbin.c +701 -0
- data/ext/clipsruby/objrtbin.h +79 -0
- data/ext/clipsruby/objrtbld.c +2393 -0
- data/ext/clipsruby/objrtbld.h +66 -0
- data/ext/clipsruby/objrtcmp.c +734 -0
- data/ext/clipsruby/objrtcmp.h +66 -0
- data/ext/clipsruby/objrtfnx.c +1330 -0
- data/ext/clipsruby/objrtfnx.h +222 -0
- data/ext/clipsruby/objrtgen.c +736 -0
- data/ext/clipsruby/objrtgen.h +63 -0
- data/ext/clipsruby/objrtmch.c +1524 -0
- data/ext/clipsruby/objrtmch.h +160 -0
- data/ext/clipsruby/parsefun.c +415 -0
- data/ext/clipsruby/parsefun.h +67 -0
- data/ext/clipsruby/pattern.c +1265 -0
- data/ext/clipsruby/pattern.h +163 -0
- data/ext/clipsruby/pprint.c +328 -0
- data/ext/clipsruby/pprint.h +79 -0
- data/ext/clipsruby/prccode.c +1478 -0
- data/ext/clipsruby/prccode.h +145 -0
- data/ext/clipsruby/prcdrfun.c +640 -0
- data/ext/clipsruby/prcdrfun.h +95 -0
- data/ext/clipsruby/prcdrpsr.c +1068 -0
- data/ext/clipsruby/prcdrpsr.h +79 -0
- data/ext/clipsruby/prdctfun.c +869 -0
- data/ext/clipsruby/prdctfun.h +77 -0
- data/ext/clipsruby/prntutil.c +878 -0
- data/ext/clipsruby/prntutil.h +125 -0
- data/ext/clipsruby/proflfun.c +827 -0
- data/ext/clipsruby/proflfun.h +118 -0
- data/ext/clipsruby/reorder.c +2082 -0
- data/ext/clipsruby/reorder.h +172 -0
- data/ext/clipsruby/reteutil.c +1732 -0
- data/ext/clipsruby/reteutil.h +111 -0
- data/ext/clipsruby/retract.c +710 -0
- data/ext/clipsruby/retract.h +74 -0
- data/ext/clipsruby/router.c +737 -0
- data/ext/clipsruby/router.h +147 -0
- data/ext/clipsruby/rulebin.c +1136 -0
- data/ext/clipsruby/rulebin.h +153 -0
- data/ext/clipsruby/rulebld.c +1328 -0
- data/ext/clipsruby/rulebld.h +62 -0
- data/ext/clipsruby/rulebsc.c +517 -0
- data/ext/clipsruby/rulebsc.h +91 -0
- data/ext/clipsruby/rulecmp.c +733 -0
- data/ext/clipsruby/rulecmp.h +63 -0
- data/ext/clipsruby/rulecom.c +1583 -0
- data/ext/clipsruby/rulecom.h +116 -0
- data/ext/clipsruby/rulecstr.c +892 -0
- data/ext/clipsruby/rulecstr.h +53 -0
- data/ext/clipsruby/ruledef.c +559 -0
- data/ext/clipsruby/ruledef.h +179 -0
- data/ext/clipsruby/ruledlt.c +599 -0
- data/ext/clipsruby/ruledlt.h +58 -0
- data/ext/clipsruby/rulelhs.c +1216 -0
- data/ext/clipsruby/rulelhs.h +52 -0
- data/ext/clipsruby/rulepsr.c +1073 -0
- data/ext/clipsruby/rulepsr.h +61 -0
- data/ext/clipsruby/scanner.c +856 -0
- data/ext/clipsruby/scanner.h +112 -0
- data/ext/clipsruby/setup.h +488 -0
- data/ext/clipsruby/sortfun.c +433 -0
- data/ext/clipsruby/sortfun.h +55 -0
- data/ext/clipsruby/strngfun.c +1173 -0
- data/ext/clipsruby/strngfun.h +96 -0
- data/ext/clipsruby/strngrtr.c +523 -0
- data/ext/clipsruby/strngrtr.h +97 -0
- data/ext/clipsruby/symblbin.c +648 -0
- data/ext/clipsruby/symblbin.h +64 -0
- data/ext/clipsruby/symblcmp.c +893 -0
- data/ext/clipsruby/symblcmp.h +61 -0
- data/ext/clipsruby/symbol.c +1961 -0
- data/ext/clipsruby/symbol.h +243 -0
- data/ext/clipsruby/sysdep.c +894 -0
- data/ext/clipsruby/sysdep.h +164 -0
- data/ext/clipsruby/textpro.c +1388 -0
- data/ext/clipsruby/textpro.h +77 -0
- data/ext/clipsruby/tmpltbin.c +609 -0
- data/ext/clipsruby/tmpltbin.h +108 -0
- data/ext/clipsruby/tmpltbsc.c +327 -0
- data/ext/clipsruby/tmpltbsc.h +87 -0
- data/ext/clipsruby/tmpltcmp.c +450 -0
- data/ext/clipsruby/tmpltcmp.h +57 -0
- data/ext/clipsruby/tmpltdef.c +584 -0
- data/ext/clipsruby/tmpltdef.h +155 -0
- data/ext/clipsruby/tmpltfun.c +2477 -0
- data/ext/clipsruby/tmpltfun.h +122 -0
- data/ext/clipsruby/tmpltlhs.c +379 -0
- data/ext/clipsruby/tmpltlhs.h +50 -0
- data/ext/clipsruby/tmpltpsr.c +819 -0
- data/ext/clipsruby/tmpltpsr.h +59 -0
- data/ext/clipsruby/tmpltrhs.c +595 -0
- data/ext/clipsruby/tmpltrhs.h +55 -0
- data/ext/clipsruby/tmpltutl.c +637 -0
- data/ext/clipsruby/tmpltutl.h +82 -0
- data/ext/clipsruby/userdata.c +156 -0
- data/ext/clipsruby/userdata.h +72 -0
- data/ext/clipsruby/userfunctions.c +70 -0
- data/ext/clipsruby/usrsetup.h +7 -0
- data/ext/clipsruby/utility.c +1594 -0
- data/ext/clipsruby/utility.h +250 -0
- data/ext/clipsruby/watch.c +865 -0
- data/ext/clipsruby/watch.h +124 -0
- data/lib/clipsruby.rb +1 -0
- metadata +388 -0
@@ -0,0 +1,1761 @@
|
|
1
|
+
/*******************************************************/
|
2
|
+
/* "C" Language Integrated Production System */
|
3
|
+
/* */
|
4
|
+
/* CLIPS Version 6.41 08/16/22 */
|
5
|
+
/* */
|
6
|
+
/* FACT LOAD/SAVE (ASCII/BINARY) MODULE */
|
7
|
+
/*******************************************************/
|
8
|
+
|
9
|
+
/*************************************************************/
|
10
|
+
/* Purpose: File load/save routines for facts */
|
11
|
+
/* */
|
12
|
+
/* Principal Programmer(s): */
|
13
|
+
/* Brian L. Dantes */
|
14
|
+
/* Gary D. Riley */
|
15
|
+
/* */
|
16
|
+
/* Contributing Programmer(s): */
|
17
|
+
/* */
|
18
|
+
/* Revision History: */
|
19
|
+
/* */
|
20
|
+
/* 6.32: Fixed load-facts garbage collection issue. */
|
21
|
+
/* */
|
22
|
+
/* 6.40: New file for save-facts and load-facts. */
|
23
|
+
/* */
|
24
|
+
/* Added bsave-facts and bload-facts. */
|
25
|
+
/* */
|
26
|
+
/* The save-facts and load-facts functions now */
|
27
|
+
/* return the number of facts saved/loaded. */
|
28
|
+
/* */
|
29
|
+
/*************************************************************/
|
30
|
+
|
31
|
+
/* =========================================
|
32
|
+
*****************************************
|
33
|
+
EXTERNAL DEFINITIONS
|
34
|
+
=========================================
|
35
|
+
***************************************** */
|
36
|
+
|
37
|
+
#include <stdlib.h>
|
38
|
+
#include <string.h>
|
39
|
+
|
40
|
+
#include "setup.h"
|
41
|
+
|
42
|
+
#if DEFTEMPLATE_CONSTRUCT
|
43
|
+
|
44
|
+
#include "argacces.h"
|
45
|
+
#if BLOAD || BLOAD_AND_BSAVE
|
46
|
+
#include "bload.h"
|
47
|
+
#endif
|
48
|
+
#include "cstrcpsr.h"
|
49
|
+
#include "factmngr.h"
|
50
|
+
#include "factrhs.h"
|
51
|
+
#include "insmngr.h"
|
52
|
+
#include "memalloc.h"
|
53
|
+
#include "modulpsr.h"
|
54
|
+
#include "modulutl.h"
|
55
|
+
#include "prntutil.h"
|
56
|
+
#include "router.h"
|
57
|
+
#include "scanner.h"
|
58
|
+
#include "strngrtr.h"
|
59
|
+
#include "symblbin.h"
|
60
|
+
#include "sysdep.h"
|
61
|
+
#include "tmpltdef.h"
|
62
|
+
#include "tmpltutl.h"
|
63
|
+
|
64
|
+
#include "factfile.h"
|
65
|
+
|
66
|
+
struct bsaveSlotValue
|
67
|
+
{
|
68
|
+
unsigned long slotName;
|
69
|
+
unsigned long valueCount;
|
70
|
+
};
|
71
|
+
|
72
|
+
struct bsaveSlotValueAtom
|
73
|
+
{
|
74
|
+
unsigned short type;
|
75
|
+
unsigned long value;
|
76
|
+
};
|
77
|
+
|
78
|
+
#define BINARY_FACTS_PREFIX_ID "\5\6\7BSFCLIPS"
|
79
|
+
#define BINARY_FACTS_VERSION_ID "V6.40"
|
80
|
+
|
81
|
+
#define MAX_BLOCK_SIZE 10240
|
82
|
+
|
83
|
+
/***************************************/
|
84
|
+
/* LOCAL INTERNAL FUNCTION DEFINITIONS */
|
85
|
+
/***************************************/
|
86
|
+
|
87
|
+
static struct expr *StandardLoadFact(Environment *,const char *,struct token *);
|
88
|
+
static Deftemplate **GetSaveFactsDeftemplateNames(Environment *,const char *,struct expr *,SaveScope,
|
89
|
+
unsigned int *,bool *);
|
90
|
+
|
91
|
+
static bool VerifyBinaryHeader(Environment *,const char *);
|
92
|
+
|
93
|
+
static long MarkFacts(Environment *,SaveScope,Deftemplate **,unsigned int,size_t *);
|
94
|
+
static void MarkSingleFact(Environment *,Fact *,size_t *);
|
95
|
+
static void MarkNeededAtom(Environment *,CLIPSValue *,size_t *);
|
96
|
+
static void WriteBinaryHeader(Environment *,FILE *);
|
97
|
+
static long SaveBinaryFacts(Environment *,FILE *,SaveScope,Deftemplate **,unsigned int count,size_t *);
|
98
|
+
static void SaveSingleFactBinary(Environment *theEnv,FILE *,Fact *);
|
99
|
+
static void SaveAtomBinary(Environment *,CLIPSValue *,FILE *);
|
100
|
+
static bool LoadSingleBinaryFact(Environment *);
|
101
|
+
static Deftemplate *BloadFactsCreateImpliedDeftemplate(Environment *,CLIPSLexeme *);
|
102
|
+
static void BinaryLoadFactError(Environment *,Deftemplate *);
|
103
|
+
static void CreateSlotValue(Environment *,UDFValue *,struct bsaveSlotValueAtom *,unsigned long,bool);
|
104
|
+
static void *GetBinaryAtomValue(Environment *,struct bsaveSlotValueAtom *);
|
105
|
+
|
106
|
+
/********************************************************/
|
107
|
+
/* FactFileCommandDefinitions: Initializes save-facts, */
|
108
|
+
/* load-facts, bsave-facts, and bload-facts commands. */
|
109
|
+
/********************************************************/
|
110
|
+
void FactFileCommandDefinitions(
|
111
|
+
Environment *theEnv)
|
112
|
+
{
|
113
|
+
#if (! RUN_TIME)
|
114
|
+
AddUDF(theEnv,"save-facts","l",1,UNBOUNDED,"y;sy",SaveFactsCommand,"SaveFactsCommand",NULL);
|
115
|
+
AddUDF(theEnv,"load-facts","l",1,1,"sy",LoadFactsCommand,"LoadFactsCommand",NULL);
|
116
|
+
|
117
|
+
AddUDF(theEnv,"bsave-facts","l",1,UNBOUNDED,"y;sy",BinarySaveFactsCommand,"BinarySaveFactsCommand",NULL);
|
118
|
+
AddUDF(theEnv,"bload-facts","l",1,1,"sy",BinaryLoadFactsCommand,"BinaryLoadFactsCommand",NULL);
|
119
|
+
#endif
|
120
|
+
}
|
121
|
+
|
122
|
+
/******************************************/
|
123
|
+
/* SaveFactsCommand: H/L access routine */
|
124
|
+
/* for the save-facts command. */
|
125
|
+
/******************************************/
|
126
|
+
void SaveFactsCommand(
|
127
|
+
Environment *theEnv,
|
128
|
+
UDFContext *context,
|
129
|
+
UDFValue *returnValue)
|
130
|
+
{
|
131
|
+
const char *fileName;
|
132
|
+
unsigned int numArgs;
|
133
|
+
SaveScope saveCode = LOCAL_SAVE;
|
134
|
+
const char *argument;
|
135
|
+
UDFValue theValue;
|
136
|
+
struct expr *theList = NULL;
|
137
|
+
long factCount = 0;
|
138
|
+
|
139
|
+
/*============================================*/
|
140
|
+
/* Check for the correct number of arguments. */
|
141
|
+
/*============================================*/
|
142
|
+
|
143
|
+
numArgs = UDFArgumentCount(context);
|
144
|
+
|
145
|
+
/*=================================================*/
|
146
|
+
/* Get the file name to which facts will be saved. */
|
147
|
+
/*=================================================*/
|
148
|
+
|
149
|
+
if ((fileName = GetFileName(context)) == NULL)
|
150
|
+
{
|
151
|
+
returnValue->integerValue = CreateInteger(theEnv,-1);
|
152
|
+
return;
|
153
|
+
}
|
154
|
+
|
155
|
+
/*=============================================================*/
|
156
|
+
/* If specified, the second argument to save-facts indicates */
|
157
|
+
/* whether just facts local to the current module or all facts */
|
158
|
+
/* visible to the current module will be saved. */
|
159
|
+
/*=============================================================*/
|
160
|
+
|
161
|
+
if (numArgs > 1)
|
162
|
+
{
|
163
|
+
if (! UDFNextArgument(context,SYMBOL_BIT,&theValue))
|
164
|
+
{
|
165
|
+
returnValue->integerValue = CreateInteger(theEnv,-1);
|
166
|
+
return;
|
167
|
+
}
|
168
|
+
|
169
|
+
argument = theValue.lexemeValue->contents;
|
170
|
+
|
171
|
+
if (strcmp(argument,"local") == 0)
|
172
|
+
{ saveCode = LOCAL_SAVE; }
|
173
|
+
else if (strcmp(argument,"visible") == 0)
|
174
|
+
{ saveCode = VISIBLE_SAVE; }
|
175
|
+
else
|
176
|
+
{
|
177
|
+
ExpectedTypeError1(theEnv,"save-facts",2,"symbol with value local or visible");
|
178
|
+
returnValue->integerValue = CreateInteger(theEnv,-1);
|
179
|
+
return;
|
180
|
+
}
|
181
|
+
}
|
182
|
+
|
183
|
+
/*======================================================*/
|
184
|
+
/* Subsequent arguments indicate that only those facts */
|
185
|
+
/* associated with the specified deftemplates should be */
|
186
|
+
/* saved to the file. */
|
187
|
+
/*======================================================*/
|
188
|
+
|
189
|
+
if (numArgs > 2) theList = GetFirstArgument()->nextArg->nextArg;
|
190
|
+
|
191
|
+
/*====================================*/
|
192
|
+
/* Call the SaveFacts driver routine. */
|
193
|
+
/*====================================*/
|
194
|
+
|
195
|
+
factCount = SaveFactsDriver(theEnv,fileName,saveCode,theList);
|
196
|
+
returnValue->integerValue = CreateInteger(theEnv,factCount);
|
197
|
+
}
|
198
|
+
|
199
|
+
/***********************************************************/
|
200
|
+
/* SaveFacts: C access routine for the save-facts command. */
|
201
|
+
/***********************************************************/
|
202
|
+
long SaveFacts(
|
203
|
+
Environment *theEnv,
|
204
|
+
const char *fileName,
|
205
|
+
SaveScope saveCode)
|
206
|
+
{
|
207
|
+
return SaveFactsDriver(theEnv,fileName,saveCode,NULL);
|
208
|
+
}
|
209
|
+
|
210
|
+
/*****************************************************************/
|
211
|
+
/* SaveFactsDriver: C access routine for the save-facts command. */
|
212
|
+
/*****************************************************************/
|
213
|
+
long SaveFactsDriver(
|
214
|
+
Environment *theEnv,
|
215
|
+
const char *fileName,
|
216
|
+
SaveScope saveCode,
|
217
|
+
struct expr *theList)
|
218
|
+
{
|
219
|
+
bool tempValue1, tempValue2, tempValue3;
|
220
|
+
Fact *theFact;
|
221
|
+
FILE *filePtr;
|
222
|
+
Defmodule *theModule;
|
223
|
+
Deftemplate **deftemplateArray;
|
224
|
+
unsigned int count, i;
|
225
|
+
bool printFact, error;
|
226
|
+
long factCount = 0;
|
227
|
+
|
228
|
+
/*======================================================*/
|
229
|
+
/* Open the file. Use either "fast save" or I/O Router. */
|
230
|
+
/*======================================================*/
|
231
|
+
|
232
|
+
if ((filePtr = GenOpen(theEnv,fileName,"w")) == NULL)
|
233
|
+
{
|
234
|
+
OpenErrorMessage(theEnv,"save-facts",fileName);
|
235
|
+
return -1;
|
236
|
+
}
|
237
|
+
|
238
|
+
SetFastSave(theEnv,filePtr);
|
239
|
+
|
240
|
+
/*===========================================*/
|
241
|
+
/* Set the print flags so that addresses and */
|
242
|
+
/* strings are printed properly to the file. */
|
243
|
+
/*===========================================*/
|
244
|
+
|
245
|
+
tempValue1 = PrintUtilityData(theEnv)->PreserveEscapedCharacters;
|
246
|
+
PrintUtilityData(theEnv)->PreserveEscapedCharacters = true;
|
247
|
+
tempValue2 = PrintUtilityData(theEnv)->AddressesToStrings;
|
248
|
+
PrintUtilityData(theEnv)->AddressesToStrings = true;
|
249
|
+
tempValue3 = PrintUtilityData(theEnv)->InstanceAddressesToNames;
|
250
|
+
PrintUtilityData(theEnv)->InstanceAddressesToNames = true;
|
251
|
+
|
252
|
+
/*===================================================*/
|
253
|
+
/* Determine the list of specific facts to be saved. */
|
254
|
+
/*===================================================*/
|
255
|
+
|
256
|
+
deftemplateArray = GetSaveFactsDeftemplateNames(theEnv,"save-facts",theList,saveCode,&count,&error);
|
257
|
+
|
258
|
+
if (error)
|
259
|
+
{
|
260
|
+
PrintUtilityData(theEnv)->PreserveEscapedCharacters = tempValue1;
|
261
|
+
PrintUtilityData(theEnv)->AddressesToStrings = tempValue2;
|
262
|
+
PrintUtilityData(theEnv)->InstanceAddressesToNames = tempValue3;
|
263
|
+
GenClose(theEnv,filePtr);
|
264
|
+
SetFastSave(theEnv,NULL);
|
265
|
+
return -1;
|
266
|
+
}
|
267
|
+
|
268
|
+
/*=================*/
|
269
|
+
/* Save the facts. */
|
270
|
+
/*=================*/
|
271
|
+
|
272
|
+
theModule = GetCurrentModule(theEnv);
|
273
|
+
|
274
|
+
for (theFact = GetNextFactInScope(theEnv,NULL);
|
275
|
+
theFact != NULL;
|
276
|
+
theFact = GetNextFactInScope(theEnv,theFact))
|
277
|
+
{
|
278
|
+
/*===========================================================*/
|
279
|
+
/* If we're doing a local save and the facts's corresponding */
|
280
|
+
/* deftemplate isn't in the current module, then don't save */
|
281
|
+
/* the fact. */
|
282
|
+
/*===========================================================*/
|
283
|
+
|
284
|
+
if ((saveCode == LOCAL_SAVE) &&
|
285
|
+
(theFact->whichDeftemplate->header.whichModule->theModule != theModule))
|
286
|
+
{ printFact = false; }
|
287
|
+
|
288
|
+
/*=====================================================*/
|
289
|
+
/* Otherwise, if the list of facts to be printed isn't */
|
290
|
+
/* restricted, then set the print flag to true. */
|
291
|
+
/*=====================================================*/
|
292
|
+
|
293
|
+
else if (theList == NULL)
|
294
|
+
{ printFact = true; }
|
295
|
+
|
296
|
+
/*=======================================================*/
|
297
|
+
/* Otherwise see if the fact's corresponding deftemplate */
|
298
|
+
/* is in the list of deftemplates whose facts are to be */
|
299
|
+
/* saved. If it's in the list, then set the print flag */
|
300
|
+
/* to true, otherwise set it to false. */
|
301
|
+
/*=======================================================*/
|
302
|
+
|
303
|
+
else
|
304
|
+
{
|
305
|
+
printFact = false;
|
306
|
+
for (i = 0; i < count; i++)
|
307
|
+
{
|
308
|
+
if (deftemplateArray[i] == theFact->whichDeftemplate)
|
309
|
+
{
|
310
|
+
printFact = true;
|
311
|
+
break;
|
312
|
+
}
|
313
|
+
}
|
314
|
+
}
|
315
|
+
|
316
|
+
/*===================================*/
|
317
|
+
/* If the print flag is set to true, */
|
318
|
+
/* then save the fact to the file. */
|
319
|
+
/*===================================*/
|
320
|
+
|
321
|
+
if (printFact)
|
322
|
+
{
|
323
|
+
factCount++;
|
324
|
+
PrintFact(theEnv,(char *) filePtr,theFact,false,false,NULL);
|
325
|
+
WriteString(theEnv,(char *) filePtr,"\n");
|
326
|
+
}
|
327
|
+
}
|
328
|
+
|
329
|
+
/*==========================*/
|
330
|
+
/* Restore the print flags. */
|
331
|
+
/*==========================*/
|
332
|
+
|
333
|
+
PrintUtilityData(theEnv)->PreserveEscapedCharacters = tempValue1;
|
334
|
+
PrintUtilityData(theEnv)->AddressesToStrings = tempValue2;
|
335
|
+
PrintUtilityData(theEnv)->InstanceAddressesToNames = tempValue3;
|
336
|
+
|
337
|
+
/*=================*/
|
338
|
+
/* Close the file. */
|
339
|
+
/*=================*/
|
340
|
+
|
341
|
+
GenClose(theEnv,filePtr);
|
342
|
+
SetFastSave(theEnv,NULL);
|
343
|
+
|
344
|
+
/*==================================*/
|
345
|
+
/* Free the deftemplate name array. */
|
346
|
+
/*==================================*/
|
347
|
+
|
348
|
+
if (theList != NULL)
|
349
|
+
{ rm(theEnv,deftemplateArray,sizeof(Deftemplate *) * count); }
|
350
|
+
|
351
|
+
/*=========================================*/
|
352
|
+
/* Return the fact count to indicate no */
|
353
|
+
/* errors occurred while saving the facts. */
|
354
|
+
/*=========================================*/
|
355
|
+
|
356
|
+
return factCount;
|
357
|
+
}
|
358
|
+
|
359
|
+
/*******************************************************************/
|
360
|
+
/* GetSaveFactsDeftemplateNames: Retrieves the list of deftemplate */
|
361
|
+
/* names for saving specific facts with the save-facts command. */
|
362
|
+
/*******************************************************************/
|
363
|
+
static Deftemplate **GetSaveFactsDeftemplateNames(
|
364
|
+
Environment *theEnv,
|
365
|
+
const char *functionName,
|
366
|
+
struct expr *theList,
|
367
|
+
SaveScope saveCode,
|
368
|
+
unsigned int *count,
|
369
|
+
bool *error)
|
370
|
+
{
|
371
|
+
struct expr *tempList;
|
372
|
+
Deftemplate **deftemplateArray;
|
373
|
+
UDFValue tempArg;
|
374
|
+
unsigned int i, tempCount;
|
375
|
+
Deftemplate *theDeftemplate = NULL;
|
376
|
+
|
377
|
+
/*=============================*/
|
378
|
+
/* Initialize the error state. */
|
379
|
+
/*=============================*/
|
380
|
+
|
381
|
+
*error = false;
|
382
|
+
|
383
|
+
/*=====================================================*/
|
384
|
+
/* If no deftemplate names were specified as arguments */
|
385
|
+
/* then the deftemplate name list is empty. */
|
386
|
+
/*=====================================================*/
|
387
|
+
|
388
|
+
if (theList == NULL)
|
389
|
+
{
|
390
|
+
*count = 0;
|
391
|
+
return NULL;
|
392
|
+
}
|
393
|
+
|
394
|
+
/*======================================*/
|
395
|
+
/* Determine the number of deftemplate */
|
396
|
+
/* names to be stored in the name list. */
|
397
|
+
/*======================================*/
|
398
|
+
|
399
|
+
for (tempList = theList, *count = 0;
|
400
|
+
tempList != NULL;
|
401
|
+
tempList = tempList->nextArg, (*count)++)
|
402
|
+
{ /* Do Nothing */ }
|
403
|
+
|
404
|
+
/*=========================================*/
|
405
|
+
/* Allocate the storage for the name list. */
|
406
|
+
/*=========================================*/
|
407
|
+
|
408
|
+
deftemplateArray = (Deftemplate **) gm2(theEnv,sizeof(Deftemplate *) * *count);
|
409
|
+
|
410
|
+
/*=====================================*/
|
411
|
+
/* Loop through each of the arguments. */
|
412
|
+
/*=====================================*/
|
413
|
+
|
414
|
+
for (tempList = theList, i = 0;
|
415
|
+
i < *count;
|
416
|
+
tempList = tempList->nextArg, i++)
|
417
|
+
{
|
418
|
+
/*========================*/
|
419
|
+
/* Evaluate the argument. */
|
420
|
+
/*========================*/
|
421
|
+
|
422
|
+
EvaluateExpression(theEnv,tempList,&tempArg);
|
423
|
+
|
424
|
+
if (EvaluationData(theEnv)->EvaluationError)
|
425
|
+
{
|
426
|
+
*error = true;
|
427
|
+
rm(theEnv,deftemplateArray,sizeof(Deftemplate *) * *count);
|
428
|
+
return NULL;
|
429
|
+
}
|
430
|
+
|
431
|
+
/*======================================*/
|
432
|
+
/* A deftemplate name must be a symbol. */
|
433
|
+
/*======================================*/
|
434
|
+
|
435
|
+
if (tempArg.header->type != SYMBOL_TYPE)
|
436
|
+
{
|
437
|
+
*error = true;
|
438
|
+
ExpectedTypeError1(theEnv,functionName,3+i,"symbol");
|
439
|
+
rm(theEnv,deftemplateArray,sizeof(Deftemplate *) * *count);
|
440
|
+
return NULL;
|
441
|
+
}
|
442
|
+
|
443
|
+
/*===================================================*/
|
444
|
+
/* Find the deftemplate. For a local save, look only */
|
445
|
+
/* in the current module. For a visible save, look */
|
446
|
+
/* in all visible modules. */
|
447
|
+
/*===================================================*/
|
448
|
+
|
449
|
+
if (saveCode == LOCAL_SAVE)
|
450
|
+
{
|
451
|
+
theDeftemplate = FindDeftemplateInModule(theEnv,tempArg.lexemeValue->contents);
|
452
|
+
if (theDeftemplate == NULL)
|
453
|
+
{
|
454
|
+
*error = true;
|
455
|
+
ExpectedTypeError1(theEnv,functionName,3+i,"'local deftemplate name'");
|
456
|
+
rm(theEnv,deftemplateArray,sizeof(Deftemplate *) * *count);
|
457
|
+
return NULL;
|
458
|
+
}
|
459
|
+
}
|
460
|
+
else if (saveCode == VISIBLE_SAVE)
|
461
|
+
{
|
462
|
+
theDeftemplate = (Deftemplate *)
|
463
|
+
FindImportedConstruct(theEnv,"deftemplate",NULL,
|
464
|
+
tempArg.lexemeValue->contents,
|
465
|
+
&tempCount,true,NULL);
|
466
|
+
if (theDeftemplate == NULL)
|
467
|
+
{
|
468
|
+
*error = true;
|
469
|
+
ExpectedTypeError1(theEnv,functionName,3+i,"'visible deftemplate name'");
|
470
|
+
rm(theEnv,deftemplateArray,sizeof(Deftemplate *) * *count);
|
471
|
+
return NULL;
|
472
|
+
}
|
473
|
+
}
|
474
|
+
|
475
|
+
/*==================================*/
|
476
|
+
/* Add a pointer to the deftemplate */
|
477
|
+
/* to the array being created. */
|
478
|
+
/*==================================*/
|
479
|
+
|
480
|
+
deftemplateArray[i] = theDeftemplate;
|
481
|
+
}
|
482
|
+
|
483
|
+
/*===================================*/
|
484
|
+
/* Return the array of deftemplates. */
|
485
|
+
/*===================================*/
|
486
|
+
|
487
|
+
return deftemplateArray;
|
488
|
+
}
|
489
|
+
|
490
|
+
/******************************************/
|
491
|
+
/* LoadFactsCommand: H/L access routine */
|
492
|
+
/* for the load-facts command. */
|
493
|
+
/******************************************/
|
494
|
+
void LoadFactsCommand(
|
495
|
+
Environment *theEnv,
|
496
|
+
UDFContext *context,
|
497
|
+
UDFValue *returnValue)
|
498
|
+
{
|
499
|
+
const char *fileName;
|
500
|
+
long factCount;
|
501
|
+
|
502
|
+
/*====================================================*/
|
503
|
+
/* Get the file name from which facts will be loaded. */
|
504
|
+
/*====================================================*/
|
505
|
+
|
506
|
+
if ((fileName = GetFileName(context)) == NULL)
|
507
|
+
{
|
508
|
+
returnValue->integerValue = CreateInteger(theEnv,-1);
|
509
|
+
return;
|
510
|
+
}
|
511
|
+
|
512
|
+
/*====================================*/
|
513
|
+
/* Call the LoadFacts driver routine. */
|
514
|
+
/*====================================*/
|
515
|
+
|
516
|
+
factCount = LoadFacts(theEnv,fileName);
|
517
|
+
returnValue->integerValue = CreateInteger(theEnv,factCount);
|
518
|
+
}
|
519
|
+
|
520
|
+
/***********************************************************/
|
521
|
+
/* LoadFacts: C access routine for the load-facts command. */
|
522
|
+
/***********************************************************/
|
523
|
+
long LoadFacts(
|
524
|
+
Environment *theEnv,
|
525
|
+
const char *fileName)
|
526
|
+
{
|
527
|
+
FILE *filePtr;
|
528
|
+
struct token theToken;
|
529
|
+
struct expr *testPtr;
|
530
|
+
UDFValue rv;
|
531
|
+
int danglingConstructs;
|
532
|
+
GCBlock gcb;
|
533
|
+
long factCount = 0;
|
534
|
+
|
535
|
+
/*=====================================*/
|
536
|
+
/* If embedded, clear the error flags. */
|
537
|
+
/*=====================================*/
|
538
|
+
|
539
|
+
if (EvaluationData(theEnv)->CurrentExpression == NULL)
|
540
|
+
{ ResetErrorFlags(theEnv); }
|
541
|
+
|
542
|
+
/*======================================================*/
|
543
|
+
/* Open the file. Use either "fast save" or I/O Router. */
|
544
|
+
/*======================================================*/
|
545
|
+
|
546
|
+
if ((filePtr = GenOpen(theEnv,fileName,"r")) == NULL)
|
547
|
+
{
|
548
|
+
OpenErrorMessage(theEnv,"load-facts",fileName);
|
549
|
+
return -1;
|
550
|
+
}
|
551
|
+
|
552
|
+
SetFastLoad(theEnv,filePtr);
|
553
|
+
|
554
|
+
/*========================================*/
|
555
|
+
/* Set up the frame for tracking garbage. */
|
556
|
+
/*========================================*/
|
557
|
+
|
558
|
+
GCBlockStart(theEnv,&gcb);
|
559
|
+
|
560
|
+
/*=================*/
|
561
|
+
/* Load the facts. */
|
562
|
+
/*=================*/
|
563
|
+
|
564
|
+
danglingConstructs = ConstructData(theEnv)->DanglingConstructs;
|
565
|
+
|
566
|
+
theToken.tknType = LEFT_PARENTHESIS_TOKEN;
|
567
|
+
while (theToken.tknType != STOP_TOKEN)
|
568
|
+
{
|
569
|
+
testPtr = StandardLoadFact(theEnv,(char *) filePtr,&theToken);
|
570
|
+
if (testPtr == NULL) theToken.tknType = STOP_TOKEN;
|
571
|
+
else
|
572
|
+
{
|
573
|
+
factCount++;
|
574
|
+
ExpressionInstall(theEnv,testPtr);
|
575
|
+
EvaluateExpression(theEnv,testPtr,&rv);
|
576
|
+
ExpressionDeinstall(theEnv,testPtr);
|
577
|
+
}
|
578
|
+
ReturnExpression(theEnv,testPtr);
|
579
|
+
}
|
580
|
+
|
581
|
+
/*================================*/
|
582
|
+
/* Restore the old garbage frame. */
|
583
|
+
/*================================*/
|
584
|
+
|
585
|
+
GCBlockEnd(theEnv,&gcb);
|
586
|
+
|
587
|
+
/*===============================================*/
|
588
|
+
/* If embedded, clean the topmost garbage frame. */
|
589
|
+
/*===============================================*/
|
590
|
+
|
591
|
+
if (EvaluationData(theEnv)->CurrentExpression == NULL)
|
592
|
+
{
|
593
|
+
CleanCurrentGarbageFrame(theEnv,NULL);
|
594
|
+
ConstructData(theEnv)->DanglingConstructs = danglingConstructs;
|
595
|
+
}
|
596
|
+
|
597
|
+
/*======================*/
|
598
|
+
/* Call periodic tasks. */
|
599
|
+
/*======================*/
|
600
|
+
|
601
|
+
CallPeriodicTasks(theEnv);
|
602
|
+
|
603
|
+
/*=================*/
|
604
|
+
/* Close the file. */
|
605
|
+
/*=================*/
|
606
|
+
|
607
|
+
SetFastLoad(theEnv,NULL);
|
608
|
+
GenClose(theEnv,filePtr);
|
609
|
+
|
610
|
+
/*================================================*/
|
611
|
+
/* Return true if no error occurred while loading */
|
612
|
+
/* the facts, otherwise return false. */
|
613
|
+
/*================================================*/
|
614
|
+
|
615
|
+
if (EvaluationData(theEnv)->EvaluationError) return -1;
|
616
|
+
return factCount;
|
617
|
+
}
|
618
|
+
|
619
|
+
/******************************************/
|
620
|
+
/* LoadFactsFromString: C access routine. */
|
621
|
+
/******************************************/
|
622
|
+
long LoadFactsFromString(
|
623
|
+
Environment *theEnv,
|
624
|
+
const char *theString,
|
625
|
+
size_t theMax)
|
626
|
+
{
|
627
|
+
const char *theStrRouter = "*** load-facts-from-string ***";
|
628
|
+
struct token theToken;
|
629
|
+
struct expr *testPtr;
|
630
|
+
UDFValue rv;
|
631
|
+
long factCount = 0;
|
632
|
+
|
633
|
+
/*=====================================*/
|
634
|
+
/* If embedded, clear the error flags. */
|
635
|
+
/*=====================================*/
|
636
|
+
|
637
|
+
if (EvaluationData(theEnv)->CurrentExpression == NULL)
|
638
|
+
{ ResetErrorFlags(theEnv); }
|
639
|
+
|
640
|
+
/*==========================*/
|
641
|
+
/* Initialize string router */
|
642
|
+
/*==========================*/
|
643
|
+
|
644
|
+
if ((theMax == SIZE_MAX) ? (! OpenStringSource(theEnv,theStrRouter,theString,0)) :
|
645
|
+
(! OpenTextSource(theEnv,theStrRouter,theString,0,theMax)))
|
646
|
+
{ return -1; }
|
647
|
+
|
648
|
+
/*=================*/
|
649
|
+
/* Load the facts. */
|
650
|
+
/*=================*/
|
651
|
+
|
652
|
+
theToken.tknType = LEFT_PARENTHESIS_TOKEN;
|
653
|
+
while (theToken.tknType != STOP_TOKEN)
|
654
|
+
{
|
655
|
+
testPtr = StandardLoadFact(theEnv,theStrRouter,&theToken);
|
656
|
+
if (testPtr == NULL) theToken.tknType = STOP_TOKEN;
|
657
|
+
else
|
658
|
+
{
|
659
|
+
factCount++;
|
660
|
+
EvaluateExpression(theEnv,testPtr,&rv);
|
661
|
+
}
|
662
|
+
ReturnExpression(theEnv,testPtr);
|
663
|
+
}
|
664
|
+
|
665
|
+
/*=================*/
|
666
|
+
/* Close router. */
|
667
|
+
/*=================*/
|
668
|
+
|
669
|
+
CloseStringSource(theEnv,theStrRouter);
|
670
|
+
|
671
|
+
/*==================================================*/
|
672
|
+
/* Return the fact count if no error occurred while */
|
673
|
+
/* loading the facts, otherwise return -1. */
|
674
|
+
/*==================================================*/
|
675
|
+
|
676
|
+
if (EvaluationData(theEnv)->EvaluationError) return -1;
|
677
|
+
return factCount;
|
678
|
+
}
|
679
|
+
|
680
|
+
/**************************************************************************/
|
681
|
+
/* StandardLoadFact: Loads a single fact from the specified logical name. */
|
682
|
+
/**************************************************************************/
|
683
|
+
static struct expr *StandardLoadFact(
|
684
|
+
Environment *theEnv,
|
685
|
+
const char *logicalName,
|
686
|
+
struct token *theToken)
|
687
|
+
{
|
688
|
+
bool error = false;
|
689
|
+
struct expr *temp;
|
690
|
+
|
691
|
+
GetToken(theEnv,logicalName,theToken);
|
692
|
+
if (theToken->tknType != LEFT_PARENTHESIS_TOKEN) return NULL;
|
693
|
+
|
694
|
+
temp = GenConstant(theEnv,FCALL,FindFunction(theEnv,"assert"));
|
695
|
+
temp->argList = GetRHSPattern(theEnv,logicalName,theToken,&error,
|
696
|
+
true,false,true,RIGHT_PARENTHESIS_TOKEN);
|
697
|
+
|
698
|
+
if (error == true)
|
699
|
+
{
|
700
|
+
WriteString(theEnv,STDERR,"Function load-facts encountered an error\n");
|
701
|
+
SetEvaluationError(theEnv,true);
|
702
|
+
ReturnExpression(theEnv,temp);
|
703
|
+
return NULL;
|
704
|
+
}
|
705
|
+
|
706
|
+
if (ExpressionContainsVariables(temp,true))
|
707
|
+
{
|
708
|
+
ReturnExpression(theEnv,temp);
|
709
|
+
return NULL;
|
710
|
+
}
|
711
|
+
|
712
|
+
return(temp);
|
713
|
+
}
|
714
|
+
|
715
|
+
/**********************************************/
|
716
|
+
/* BinaryLoadFactsCommand: H/L access routine */
|
717
|
+
/* for the bload-facts command. */
|
718
|
+
/**********************************************/
|
719
|
+
void BinaryLoadFactsCommand(
|
720
|
+
Environment *theEnv,
|
721
|
+
UDFContext *context,
|
722
|
+
UDFValue *returnValue)
|
723
|
+
{
|
724
|
+
const char *fileName;
|
725
|
+
long factCount;
|
726
|
+
|
727
|
+
/*====================================================*/
|
728
|
+
/* Get the file name from which facts will be loaded. */
|
729
|
+
/*====================================================*/
|
730
|
+
|
731
|
+
if ((fileName = GetFileName(context)) == NULL)
|
732
|
+
{
|
733
|
+
returnValue->integerValue = CreateInteger(theEnv,-1);
|
734
|
+
return;
|
735
|
+
}
|
736
|
+
|
737
|
+
/*==========================================*/
|
738
|
+
/* Call the BinaryLoadFacts driver routine. */
|
739
|
+
/*==========================================*/
|
740
|
+
|
741
|
+
factCount = BinaryLoadFacts(theEnv,fileName);
|
742
|
+
returnValue->integerValue = CreateInteger(theEnv,factCount);
|
743
|
+
}
|
744
|
+
|
745
|
+
/******************************************************************/
|
746
|
+
/* BinaryLoadFacts: C access routine for the bload-facts command. */
|
747
|
+
/******************************************************************/
|
748
|
+
long BinaryLoadFacts(
|
749
|
+
Environment *theEnv,
|
750
|
+
const char *fileName)
|
751
|
+
{
|
752
|
+
GCBlock gcb;
|
753
|
+
long i;
|
754
|
+
long factCount;
|
755
|
+
|
756
|
+
/*=====================================*/
|
757
|
+
/* If embedded, clear the error flags. */
|
758
|
+
/*=====================================*/
|
759
|
+
|
760
|
+
if (EvaluationData(theEnv)->CurrentExpression == NULL)
|
761
|
+
{ ResetErrorFlags(theEnv); }
|
762
|
+
|
763
|
+
/*======================================================*/
|
764
|
+
/* Open the file. Use either "fast save" or I/O Router. */
|
765
|
+
/*======================================================*/
|
766
|
+
|
767
|
+
if (GenOpenReadBinary(theEnv,"bload-facts",fileName) == false)
|
768
|
+
{
|
769
|
+
OpenErrorMessage(theEnv,"bload-facts",fileName);
|
770
|
+
return -1;
|
771
|
+
}
|
772
|
+
|
773
|
+
/*======================================*/
|
774
|
+
/* Check the binary header to determine */
|
775
|
+
/* if this is a binary fact file. */
|
776
|
+
/*======================================*/
|
777
|
+
|
778
|
+
if (VerifyBinaryHeader(theEnv,fileName) == false)
|
779
|
+
{
|
780
|
+
GenCloseBinary(theEnv);
|
781
|
+
return -1;
|
782
|
+
}
|
783
|
+
|
784
|
+
/*========================================*/
|
785
|
+
/* Set up the frame for tracking garbage. */
|
786
|
+
/*========================================*/
|
787
|
+
|
788
|
+
GCBlockStart(theEnv,&gcb);
|
789
|
+
|
790
|
+
/*=================*/
|
791
|
+
/* Load the facts. */
|
792
|
+
/*=================*/
|
793
|
+
|
794
|
+
ReadNeededAtomicValues(theEnv);
|
795
|
+
|
796
|
+
UtilityData(theEnv)->BinaryFileOffset = 0L;
|
797
|
+
|
798
|
+
GenReadBinary(theEnv,&UtilityData(theEnv)->BinaryFileSize,sizeof(size_t));
|
799
|
+
GenReadBinary(theEnv,&factCount,sizeof(long));
|
800
|
+
|
801
|
+
for (i = 0; i < factCount; i++)
|
802
|
+
{
|
803
|
+
if (LoadSingleBinaryFact(theEnv) == false)
|
804
|
+
{
|
805
|
+
SetEvaluationError(theEnv,true);
|
806
|
+
break;
|
807
|
+
}
|
808
|
+
}
|
809
|
+
|
810
|
+
FreeReadBuffer(theEnv);
|
811
|
+
|
812
|
+
FreeAtomicValueStorage(theEnv);
|
813
|
+
|
814
|
+
/*=================*/
|
815
|
+
/* Close the file. */
|
816
|
+
/*=================*/
|
817
|
+
|
818
|
+
GenCloseBinary(theEnv);
|
819
|
+
|
820
|
+
/*================================*/
|
821
|
+
/* Restore the old garbage frame. */
|
822
|
+
/*================================*/
|
823
|
+
|
824
|
+
GCBlockEnd(theEnv,&gcb);
|
825
|
+
|
826
|
+
/*===============================================*/
|
827
|
+
/* If embedded, clean the topmost garbage frame. */
|
828
|
+
/*===============================================*/
|
829
|
+
|
830
|
+
if (EvaluationData(theEnv)->CurrentExpression == NULL)
|
831
|
+
{ CleanCurrentGarbageFrame(theEnv,NULL); }
|
832
|
+
|
833
|
+
/*======================*/
|
834
|
+
/* Call periodic tasks. */
|
835
|
+
/*======================*/
|
836
|
+
|
837
|
+
CallPeriodicTasks(theEnv);
|
838
|
+
|
839
|
+
/*===============================================*/
|
840
|
+
/* Return the fact count if no error occurred */
|
841
|
+
/* while loading the facts, otherwise return -1. */
|
842
|
+
/*===============================================*/
|
843
|
+
|
844
|
+
if (EvaluationData(theEnv)->EvaluationError) return -1;
|
845
|
+
|
846
|
+
return factCount;
|
847
|
+
}
|
848
|
+
|
849
|
+
/***********************/
|
850
|
+
/* VerifyBinaryHeader: */
|
851
|
+
/***********************/
|
852
|
+
static bool VerifyBinaryHeader(
|
853
|
+
Environment *theEnv,
|
854
|
+
const char *theFile)
|
855
|
+
{
|
856
|
+
char buf[20];
|
857
|
+
|
858
|
+
GenReadBinary(theEnv,buf,(strlen(BINARY_FACTS_PREFIX_ID) + 1));
|
859
|
+
if (strcmp(buf,BINARY_FACTS_PREFIX_ID) != 0)
|
860
|
+
{
|
861
|
+
PrintErrorID(theEnv,"FACTFILE",1,false);
|
862
|
+
WriteString(theEnv,STDERR,"File '");
|
863
|
+
WriteString(theEnv,STDERR,theFile);
|
864
|
+
WriteString(theEnv,STDERR,"' is not a binary facts file.\n");
|
865
|
+
return false;
|
866
|
+
}
|
867
|
+
|
868
|
+
GenReadBinary(theEnv,buf,(strlen(BINARY_FACTS_VERSION_ID) + 1));
|
869
|
+
if (strcmp(buf,BINARY_FACTS_VERSION_ID) != 0)
|
870
|
+
{
|
871
|
+
PrintErrorID(theEnv,"FACTFILE",2,false);
|
872
|
+
WriteString(theEnv,STDERR,"File '");
|
873
|
+
WriteString(theEnv,STDERR,theFile);
|
874
|
+
WriteString(theEnv,STDERR,"' is not a compatible binary facts file.\n");
|
875
|
+
return false;
|
876
|
+
}
|
877
|
+
|
878
|
+
return true;
|
879
|
+
}
|
880
|
+
|
881
|
+
/************************/
|
882
|
+
/* LoadSingleBinaryFact */
|
883
|
+
/************************/
|
884
|
+
static bool LoadSingleBinaryFact(
|
885
|
+
Environment *theEnv)
|
886
|
+
{
|
887
|
+
CLIPSLexeme *deftemplateName;
|
888
|
+
unsigned short slotCount;
|
889
|
+
Deftemplate *theDeftemplate;
|
890
|
+
Fact *newFact;
|
891
|
+
struct bsaveSlotValue *bsArray;
|
892
|
+
struct bsaveSlotValueAtom *bsaArray = NULL;
|
893
|
+
unsigned long nameIndex;
|
894
|
+
unsigned long totalValueCount;
|
895
|
+
long i, j;
|
896
|
+
unsigned int count;
|
897
|
+
TemplateSlot *sp;
|
898
|
+
UDFValue slotValue;
|
899
|
+
bool implied, isMultislot;
|
900
|
+
bool success = true;
|
901
|
+
|
902
|
+
/*===========================*/
|
903
|
+
/* Get the deftemplate name. */
|
904
|
+
/*===========================*/
|
905
|
+
|
906
|
+
BufferedRead(theEnv,&nameIndex,sizeof(unsigned long));
|
907
|
+
deftemplateName = SymbolPointer(nameIndex);
|
908
|
+
|
909
|
+
/*===========================*/
|
910
|
+
/* Get the deftemplate type. */
|
911
|
+
/*===========================*/
|
912
|
+
|
913
|
+
BufferedRead(theEnv,&implied,sizeof(bool));
|
914
|
+
|
915
|
+
/*=====================*/
|
916
|
+
/* Get the slot count. */
|
917
|
+
/*=====================*/
|
918
|
+
|
919
|
+
BufferedRead(theEnv,&slotCount,sizeof(unsigned short));
|
920
|
+
|
921
|
+
/*==================================*/
|
922
|
+
/* Make sure the deftemplate exists */
|
923
|
+
/* and check the slot count. */
|
924
|
+
/*==================================*/
|
925
|
+
|
926
|
+
theDeftemplate = (Deftemplate *)
|
927
|
+
FindImportedConstruct(theEnv,"deftemplate",NULL,deftemplateName->contents,
|
928
|
+
&count,true,NULL);
|
929
|
+
|
930
|
+
if (theDeftemplate == NULL)
|
931
|
+
{
|
932
|
+
if (implied)
|
933
|
+
{
|
934
|
+
theDeftemplate = BloadFactsCreateImpliedDeftemplate(theEnv,deftemplateName);
|
935
|
+
if (theDeftemplate == NULL)
|
936
|
+
{ return false; }
|
937
|
+
}
|
938
|
+
else
|
939
|
+
{
|
940
|
+
CantFindItemInFunctionErrorMessage(theEnv,"deftemplate",deftemplateName->contents,"bload-facts",true);
|
941
|
+
return false;
|
942
|
+
}
|
943
|
+
}
|
944
|
+
|
945
|
+
if ((implied && (slotCount != 1)) ||
|
946
|
+
((! implied) && (theDeftemplate->numberOfSlots != slotCount)))
|
947
|
+
{
|
948
|
+
BinaryLoadFactError(theEnv,theDeftemplate);
|
949
|
+
return false;
|
950
|
+
}
|
951
|
+
|
952
|
+
/*==================================*/
|
953
|
+
/* Create the new unitialized fact. */
|
954
|
+
/*==================================*/
|
955
|
+
|
956
|
+
newFact = CreateFactBySize(theEnv,slotCount);
|
957
|
+
newFact->whichDeftemplate = theDeftemplate;
|
958
|
+
|
959
|
+
if (slotCount == 0)
|
960
|
+
{
|
961
|
+
Assert(newFact);
|
962
|
+
return true;
|
963
|
+
}
|
964
|
+
|
965
|
+
sp = theDeftemplate->slotList;
|
966
|
+
|
967
|
+
/*====================================*/
|
968
|
+
/* Read all slot information and slot */
|
969
|
+
/* value atoms into big arrays. */
|
970
|
+
/*====================================*/
|
971
|
+
|
972
|
+
bsArray = (struct bsaveSlotValue *) gm2(theEnv,(sizeof(struct bsaveSlotValue) * slotCount));
|
973
|
+
BufferedRead(theEnv,bsArray,(sizeof(struct bsaveSlotValue) * slotCount));
|
974
|
+
|
975
|
+
BufferedRead(theEnv,&totalValueCount,sizeof(unsigned long));
|
976
|
+
|
977
|
+
if (totalValueCount != 0L)
|
978
|
+
{
|
979
|
+
bsaArray = (struct bsaveSlotValueAtom *)
|
980
|
+
gm2(theEnv,(totalValueCount * sizeof(struct bsaveSlotValueAtom)));
|
981
|
+
BufferedRead(theEnv,bsaArray,(totalValueCount * sizeof(struct bsaveSlotValueAtom)));
|
982
|
+
}
|
983
|
+
|
984
|
+
/*==================================*/
|
985
|
+
/* Insert the values for the slots. */
|
986
|
+
/*==================================*/
|
987
|
+
|
988
|
+
for (i = 0 , j = 0L ; i < slotCount ; i++)
|
989
|
+
{
|
990
|
+
/*=======================================================*/
|
991
|
+
/* Here is another check for the validity of the binary */
|
992
|
+
/* file: the order of the slots in the file should match */
|
993
|
+
/* the order in the deftemplate definition. */
|
994
|
+
/*=======================================================*/
|
995
|
+
|
996
|
+
if (implied)
|
997
|
+
{
|
998
|
+
if (bsArray[i].slotName != ULONG_MAX)
|
999
|
+
{
|
1000
|
+
BinaryLoadFactError(theEnv,theDeftemplate);
|
1001
|
+
ReturnFact(theEnv,newFact);
|
1002
|
+
success = false;
|
1003
|
+
break;
|
1004
|
+
}
|
1005
|
+
}
|
1006
|
+
else
|
1007
|
+
{
|
1008
|
+
if (sp->slotName != SymbolPointer(bsArray[i].slotName))
|
1009
|
+
{
|
1010
|
+
BinaryLoadFactError(theEnv,theDeftemplate);
|
1011
|
+
ReturnFact(theEnv,newFact);
|
1012
|
+
success = false;
|
1013
|
+
break;
|
1014
|
+
}
|
1015
|
+
}
|
1016
|
+
|
1017
|
+
isMultislot = implied || (sp->multislot == true);
|
1018
|
+
|
1019
|
+
CreateSlotValue(theEnv,&slotValue,(struct bsaveSlotValueAtom *) &bsaArray[j],
|
1020
|
+
bsArray[i].valueCount,isMultislot);
|
1021
|
+
|
1022
|
+
newFact->theProposition.contents[i].value = slotValue.value;
|
1023
|
+
|
1024
|
+
j += (unsigned long) bsArray[i].valueCount;
|
1025
|
+
|
1026
|
+
if (! implied)
|
1027
|
+
{ sp = sp->next; }
|
1028
|
+
}
|
1029
|
+
|
1030
|
+
rm(theEnv,bsArray,(sizeof(struct bsaveSlotValue) * slotCount));
|
1031
|
+
|
1032
|
+
if (totalValueCount != 0L)
|
1033
|
+
{ rm(theEnv,bsaArray,(totalValueCount * sizeof(struct bsaveSlotValueAtom))); }
|
1034
|
+
|
1035
|
+
if (success)
|
1036
|
+
{ Assert(newFact); }
|
1037
|
+
|
1038
|
+
return success;
|
1039
|
+
}
|
1040
|
+
|
1041
|
+
/**************************************/
|
1042
|
+
/* BloadFactsCreateImpliedDeftemplate */
|
1043
|
+
/**************************************/
|
1044
|
+
static Deftemplate *BloadFactsCreateImpliedDeftemplate(
|
1045
|
+
Environment *theEnv,
|
1046
|
+
CLIPSLexeme *deftemplateName)
|
1047
|
+
{
|
1048
|
+
#if (! BLOAD_ONLY) && (! RUN_TIME)
|
1049
|
+
|
1050
|
+
#if BLOAD || BLOAD_AND_BSAVE
|
1051
|
+
if (Bloaded(theEnv))
|
1052
|
+
{
|
1053
|
+
CantFindItemInFunctionErrorMessage(theEnv,"deftemplate",deftemplateName->contents,"bload-facts",true);
|
1054
|
+
return NULL;
|
1055
|
+
}
|
1056
|
+
#endif
|
1057
|
+
#if DEFMODULE_CONSTRUCT
|
1058
|
+
if (FindImportExportConflict(theEnv,"deftemplate",GetCurrentModule(theEnv),deftemplateName->contents))
|
1059
|
+
{
|
1060
|
+
ImportExportConflictMessage(theEnv,"implied deftemplate",deftemplateName->contents,NULL,NULL);
|
1061
|
+
return NULL;
|
1062
|
+
}
|
1063
|
+
#endif
|
1064
|
+
return CreateImpliedDeftemplate(theEnv,deftemplateName,true);
|
1065
|
+
|
1066
|
+
#else
|
1067
|
+
CantFindItemInFunctionErrorMessage(theEnv,"deftemplate",deftemplateName->contents,"bload-facts",true);
|
1068
|
+
return NULL;
|
1069
|
+
#endif
|
1070
|
+
}
|
1071
|
+
|
1072
|
+
/***************************************************
|
1073
|
+
NAME : CreateSlotValue
|
1074
|
+
DESCRIPTION : Creates a data object value from
|
1075
|
+
the binary slot value atom data
|
1076
|
+
INPUTS : 1) A data object buffer
|
1077
|
+
2) The slot value atoms array
|
1078
|
+
3) The number of values to put
|
1079
|
+
in the data object
|
1080
|
+
RETURNS : Nothing useful
|
1081
|
+
SIDE EFFECTS : Data object initialized
|
1082
|
+
(if more than one value, a
|
1083
|
+
multifield is created)
|
1084
|
+
NOTES : None
|
1085
|
+
***************************************************/
|
1086
|
+
static void CreateSlotValue(
|
1087
|
+
Environment *theEnv,
|
1088
|
+
UDFValue *returnValue,
|
1089
|
+
struct bsaveSlotValueAtom *bsaValues,
|
1090
|
+
unsigned long valueCount,
|
1091
|
+
bool isMultislot)
|
1092
|
+
{
|
1093
|
+
unsigned i;
|
1094
|
+
|
1095
|
+
if (isMultislot)
|
1096
|
+
{
|
1097
|
+
returnValue->value = CreateUnmanagedMultifield(theEnv,valueCount);
|
1098
|
+
returnValue->begin = 0;
|
1099
|
+
returnValue->range = valueCount;
|
1100
|
+
for (i = 0 ; i < valueCount ; i++)
|
1101
|
+
{ returnValue->multifieldValue->contents[i].value = GetBinaryAtomValue(theEnv,&bsaValues[i]); }
|
1102
|
+
}
|
1103
|
+
else
|
1104
|
+
{ returnValue->value = GetBinaryAtomValue(theEnv,&bsaValues[0]); }
|
1105
|
+
}
|
1106
|
+
|
1107
|
+
/**********************/
|
1108
|
+
/* GetBinaryAtomValue */
|
1109
|
+
/**********************/
|
1110
|
+
static void *GetBinaryAtomValue(
|
1111
|
+
Environment *theEnv,
|
1112
|
+
struct bsaveSlotValueAtom *ba)
|
1113
|
+
{
|
1114
|
+
switch (ba->type)
|
1115
|
+
{
|
1116
|
+
case SYMBOL_TYPE:
|
1117
|
+
case STRING_TYPE:
|
1118
|
+
case INSTANCE_NAME_TYPE:
|
1119
|
+
return((void *) SymbolPointer(ba->value));
|
1120
|
+
|
1121
|
+
case FLOAT_TYPE:
|
1122
|
+
return((void *) FloatPointer(ba->value));
|
1123
|
+
|
1124
|
+
case INTEGER_TYPE:
|
1125
|
+
return((void *) IntegerPointer(ba->value));
|
1126
|
+
|
1127
|
+
case FACT_ADDRESS_TYPE:
|
1128
|
+
#if DEFTEMPLATE_CONSTRUCT && DEFRULE_CONSTRUCT
|
1129
|
+
return((void *) &FactData(theEnv)->DummyFact);
|
1130
|
+
#else
|
1131
|
+
return NULL;
|
1132
|
+
#endif
|
1133
|
+
|
1134
|
+
case EXTERNAL_ADDRESS_TYPE:
|
1135
|
+
return CreateExternalAddress(theEnv,NULL,0);
|
1136
|
+
|
1137
|
+
default:
|
1138
|
+
{
|
1139
|
+
SystemError(theEnv,"INSFILE",1);
|
1140
|
+
ExitRouter(theEnv,EXIT_FAILURE);
|
1141
|
+
}
|
1142
|
+
}
|
1143
|
+
return NULL;
|
1144
|
+
}
|
1145
|
+
|
1146
|
+
/***********************/
|
1147
|
+
/* BinaryLoadFactError */
|
1148
|
+
/***********************/
|
1149
|
+
static void BinaryLoadFactError(
|
1150
|
+
Environment *theEnv,
|
1151
|
+
Deftemplate *theDeftemplate)
|
1152
|
+
{
|
1153
|
+
PrintErrorID(theEnv,"FACTFILE",3,false);
|
1154
|
+
WriteString(theEnv,STDERR,"Function 'bload-facts' is unable to load fact of deftemplate '");
|
1155
|
+
WriteString(theEnv,STDERR,theDeftemplate->header.name->contents);
|
1156
|
+
WriteString(theEnv,STDERR,"'\n");
|
1157
|
+
}
|
1158
|
+
|
1159
|
+
/**********************************************/
|
1160
|
+
/* BinarySaveFactsCommand: H/L access routine */
|
1161
|
+
/* for the bsave-facts command. */
|
1162
|
+
/**********************************************/
|
1163
|
+
void BinarySaveFactsCommand(
|
1164
|
+
Environment *theEnv,
|
1165
|
+
UDFContext *context,
|
1166
|
+
UDFValue *returnValue)
|
1167
|
+
{
|
1168
|
+
const char *fileName;
|
1169
|
+
unsigned int numArgs;
|
1170
|
+
SaveScope saveCode = LOCAL_SAVE;
|
1171
|
+
const char *argument;
|
1172
|
+
UDFValue theValue;
|
1173
|
+
struct expr *theList = NULL;
|
1174
|
+
long factCount;
|
1175
|
+
|
1176
|
+
/*============================================*/
|
1177
|
+
/* Check for the correct number of arguments. */
|
1178
|
+
/*============================================*/
|
1179
|
+
|
1180
|
+
numArgs = UDFArgumentCount(context);
|
1181
|
+
|
1182
|
+
/*=================================================*/
|
1183
|
+
/* Get the file name to which facts will be saved. */
|
1184
|
+
/*=================================================*/
|
1185
|
+
|
1186
|
+
if ((fileName = GetFileName(context)) == NULL)
|
1187
|
+
{
|
1188
|
+
returnValue->integerValue = CreateInteger(theEnv,-1);
|
1189
|
+
return;
|
1190
|
+
}
|
1191
|
+
|
1192
|
+
/*=============================================================*/
|
1193
|
+
/* If specified, the second argument to save-facts indicates */
|
1194
|
+
/* whether just facts local to the current module or all facts */
|
1195
|
+
/* visible to the current module will be saved. */
|
1196
|
+
/*=============================================================*/
|
1197
|
+
|
1198
|
+
if (numArgs > 1)
|
1199
|
+
{
|
1200
|
+
if (! UDFNextArgument(context,SYMBOL_BIT,&theValue))
|
1201
|
+
{
|
1202
|
+
returnValue->integerValue = CreateInteger(theEnv,-1);
|
1203
|
+
return;
|
1204
|
+
}
|
1205
|
+
|
1206
|
+
argument = theValue.lexemeValue->contents;
|
1207
|
+
|
1208
|
+
if (strcmp(argument,"local") == 0)
|
1209
|
+
{ saveCode = LOCAL_SAVE; }
|
1210
|
+
else if (strcmp(argument,"visible") == 0)
|
1211
|
+
{ saveCode = VISIBLE_SAVE; }
|
1212
|
+
else
|
1213
|
+
{
|
1214
|
+
ExpectedTypeError1(theEnv,"bsave-facts",2,"symbol with value local or visible");
|
1215
|
+
returnValue->integerValue = CreateInteger(theEnv,-1);
|
1216
|
+
return;
|
1217
|
+
}
|
1218
|
+
}
|
1219
|
+
|
1220
|
+
/*======================================================*/
|
1221
|
+
/* Subsequent arguments indicate that only those facts */
|
1222
|
+
/* associated with the specified deftemplates should be */
|
1223
|
+
/* saved to the file. */
|
1224
|
+
/*======================================================*/
|
1225
|
+
|
1226
|
+
if (numArgs > 2) theList = GetFirstArgument()->nextArg->nextArg;
|
1227
|
+
|
1228
|
+
/*==========================================*/
|
1229
|
+
/* Call the BinarySaveFacts driver routine. */
|
1230
|
+
/*==========================================*/
|
1231
|
+
|
1232
|
+
factCount = BinarySaveFactsDriver(theEnv,fileName,saveCode,theList);
|
1233
|
+
returnValue->integerValue = CreateInteger(theEnv,factCount);
|
1234
|
+
}
|
1235
|
+
|
1236
|
+
/******************************************************************/
|
1237
|
+
/* BinarySaveFacts: C access routine for the bsave-facts command. */
|
1238
|
+
/******************************************************************/
|
1239
|
+
long BinarySaveFacts(
|
1240
|
+
Environment *theEnv,
|
1241
|
+
const char *file,
|
1242
|
+
SaveScope saveCode)
|
1243
|
+
{
|
1244
|
+
return BinarySaveFactsDriver(theEnv,file,saveCode,NULL);
|
1245
|
+
}
|
1246
|
+
|
1247
|
+
/**************************/
|
1248
|
+
/* BinarySaveFactsDriver: */
|
1249
|
+
/**************************/
|
1250
|
+
long BinarySaveFactsDriver(
|
1251
|
+
Environment *theEnv,
|
1252
|
+
const char *fileName,
|
1253
|
+
SaveScope saveCode,
|
1254
|
+
Expression *theList)
|
1255
|
+
{
|
1256
|
+
FILE *filePtr;
|
1257
|
+
Deftemplate **deftemplateArray;
|
1258
|
+
unsigned int templateCount;
|
1259
|
+
bool error;
|
1260
|
+
size_t neededSpace = 0;
|
1261
|
+
long factCount;
|
1262
|
+
|
1263
|
+
/*=====================================*/
|
1264
|
+
/* If embedded, clear the error flags. */
|
1265
|
+
/*=====================================*/
|
1266
|
+
|
1267
|
+
if (EvaluationData(theEnv)->CurrentExpression == NULL)
|
1268
|
+
{ ResetErrorFlags(theEnv); }
|
1269
|
+
|
1270
|
+
/*======================================================*/
|
1271
|
+
/* Open the file. Use either "fast save" or I/O Router. */
|
1272
|
+
/*======================================================*/
|
1273
|
+
|
1274
|
+
if ((filePtr = GenOpen(theEnv,fileName,"wb")) == NULL)
|
1275
|
+
{
|
1276
|
+
OpenErrorMessage(theEnv,"bsave-facts",fileName);
|
1277
|
+
return -1;
|
1278
|
+
}
|
1279
|
+
|
1280
|
+
/*===================================================*/
|
1281
|
+
/* Determine the list of specific facts to be saved. */
|
1282
|
+
/*===================================================*/
|
1283
|
+
|
1284
|
+
deftemplateArray = GetSaveFactsDeftemplateNames(theEnv,"bsave-facts",theList,
|
1285
|
+
saveCode,&templateCount,&error);
|
1286
|
+
|
1287
|
+
if (error)
|
1288
|
+
{
|
1289
|
+
GenClose(theEnv,filePtr);
|
1290
|
+
return -1;
|
1291
|
+
}
|
1292
|
+
|
1293
|
+
InitAtomicValueNeededFlags(theEnv);
|
1294
|
+
|
1295
|
+
factCount = MarkFacts(theEnv,saveCode,deftemplateArray,templateCount,&neededSpace);
|
1296
|
+
|
1297
|
+
WriteBinaryHeader(theEnv,filePtr);
|
1298
|
+
WriteNeededAtomicValues(theEnv,filePtr);
|
1299
|
+
|
1300
|
+
fwrite(&neededSpace,sizeof(size_t),1,filePtr);
|
1301
|
+
fwrite(&factCount,sizeof(unsigned long),1,filePtr);
|
1302
|
+
|
1303
|
+
SetAtomicValueIndices(theEnv,false);
|
1304
|
+
|
1305
|
+
SaveBinaryFacts(theEnv,filePtr,saveCode,deftemplateArray,templateCount,&neededSpace);
|
1306
|
+
|
1307
|
+
RestoreAtomicValueBuckets(theEnv);
|
1308
|
+
|
1309
|
+
/*=================*/
|
1310
|
+
/* Close the file. */
|
1311
|
+
/*=================*/
|
1312
|
+
|
1313
|
+
GenClose(theEnv,filePtr);
|
1314
|
+
|
1315
|
+
/*==================================*/
|
1316
|
+
/* Free the deftemplate name array. */
|
1317
|
+
/*==================================*/
|
1318
|
+
|
1319
|
+
if (theList != NULL)
|
1320
|
+
{ rm(theEnv,deftemplateArray,sizeof(Deftemplate *) * templateCount); }
|
1321
|
+
|
1322
|
+
/*=========================================*/
|
1323
|
+
/* Return the fact count to indicate no */
|
1324
|
+
/* errors occurred while saving the facts. */
|
1325
|
+
/*=========================================*/
|
1326
|
+
|
1327
|
+
return factCount;
|
1328
|
+
}
|
1329
|
+
|
1330
|
+
/*************/
|
1331
|
+
/* MarkFacts */
|
1332
|
+
/*************/
|
1333
|
+
static long MarkFacts(
|
1334
|
+
Environment *theEnv,
|
1335
|
+
SaveScope saveCode,
|
1336
|
+
Deftemplate **deftemplateArray,
|
1337
|
+
unsigned int count,
|
1338
|
+
size_t *neededSpace)
|
1339
|
+
{
|
1340
|
+
Fact *theFact;
|
1341
|
+
Defmodule *theModule;
|
1342
|
+
unsigned int i;
|
1343
|
+
bool markFact;
|
1344
|
+
long factCount = 0;
|
1345
|
+
|
1346
|
+
/*=================*/
|
1347
|
+
/* Save the facts. */
|
1348
|
+
/*=================*/
|
1349
|
+
|
1350
|
+
theModule = GetCurrentModule(theEnv);
|
1351
|
+
|
1352
|
+
for (theFact = GetNextFactInScope(theEnv,NULL);
|
1353
|
+
theFact != NULL;
|
1354
|
+
theFact = GetNextFactInScope(theEnv,theFact))
|
1355
|
+
{
|
1356
|
+
/*===========================================================*/
|
1357
|
+
/* If we're doing a local save and the facts's corresponding */
|
1358
|
+
/* deftemplate isn't in the current module, then don't save */
|
1359
|
+
/* the fact. */
|
1360
|
+
/*===========================================================*/
|
1361
|
+
|
1362
|
+
if ((saveCode == LOCAL_SAVE) &&
|
1363
|
+
(theFact->whichDeftemplate->header.whichModule->theModule != theModule))
|
1364
|
+
{ markFact = false; }
|
1365
|
+
|
1366
|
+
/*===================================================*/
|
1367
|
+
/* Otherwise, if the list of facts to be saved isn't */
|
1368
|
+
/* restricted, then set the mark flag to true. */
|
1369
|
+
/*===================================================*/
|
1370
|
+
|
1371
|
+
else if (deftemplateArray == NULL)
|
1372
|
+
{ markFact = true; }
|
1373
|
+
|
1374
|
+
/*=======================================================*/
|
1375
|
+
/* Otherwise see if the fact's corresponding deftemplate */
|
1376
|
+
/* is in the list of deftemplates whose facts are to be */
|
1377
|
+
/* saved. If it's in the list, then set the mark flag */
|
1378
|
+
/* to true, otherwise set it to false. */
|
1379
|
+
/*=======================================================*/
|
1380
|
+
|
1381
|
+
else
|
1382
|
+
{
|
1383
|
+
markFact = false;
|
1384
|
+
for (i = 0; i < count; i++)
|
1385
|
+
{
|
1386
|
+
if (deftemplateArray[i] == theFact->whichDeftemplate)
|
1387
|
+
{
|
1388
|
+
markFact = true;
|
1389
|
+
break;
|
1390
|
+
}
|
1391
|
+
}
|
1392
|
+
}
|
1393
|
+
|
1394
|
+
/*============================*/
|
1395
|
+
/* If the mark flag is set to */
|
1396
|
+
/* true, then mark the fact. */
|
1397
|
+
/*============================*/
|
1398
|
+
|
1399
|
+
if (markFact)
|
1400
|
+
{
|
1401
|
+
factCount++;
|
1402
|
+
MarkSingleFact(theEnv,theFact,neededSpace);
|
1403
|
+
}
|
1404
|
+
}
|
1405
|
+
|
1406
|
+
return factCount;
|
1407
|
+
}
|
1408
|
+
|
1409
|
+
/******************/
|
1410
|
+
/* MarkSingleFact */
|
1411
|
+
/******************/
|
1412
|
+
static void MarkSingleFact(
|
1413
|
+
Environment *theEnv,
|
1414
|
+
Fact *theFact,
|
1415
|
+
size_t *neededSpace)
|
1416
|
+
{
|
1417
|
+
TemplateSlot *sp;
|
1418
|
+
unsigned short i;
|
1419
|
+
size_t j;
|
1420
|
+
|
1421
|
+
*neededSpace += sizeof(unsigned long) + // Deftemplate name
|
1422
|
+
sizeof(bool); // Deftemplate type
|
1423
|
+
|
1424
|
+
theFact->whichDeftemplate->header.name->neededSymbol = true;
|
1425
|
+
|
1426
|
+
if (theFact->whichDeftemplate->implied)
|
1427
|
+
{
|
1428
|
+
*neededSpace += (sizeof(unsigned short) + // Number of slots
|
1429
|
+
sizeof(struct bsaveSlotValue) +
|
1430
|
+
sizeof(unsigned long)); // Number of atoms
|
1431
|
+
|
1432
|
+
CLIPSValue *theValue = &theFact->theProposition.contents[0];
|
1433
|
+
|
1434
|
+
for (j = 0 ; j < theValue->multifieldValue->length ; j++)
|
1435
|
+
{ MarkNeededAtom(theEnv,&theValue->multifieldValue->contents[j],neededSpace); }
|
1436
|
+
}
|
1437
|
+
else
|
1438
|
+
{
|
1439
|
+
*neededSpace += (sizeof(unsigned short) + // Number of slots
|
1440
|
+
(sizeof(struct bsaveSlotValue) * theFact->whichDeftemplate->numberOfSlots) +
|
1441
|
+
sizeof(unsigned long)); // Number of atoms
|
1442
|
+
|
1443
|
+
sp = theFact->whichDeftemplate->slotList;
|
1444
|
+
for (i = 0 ; i < theFact->whichDeftemplate->numberOfSlots ; i++)
|
1445
|
+
{
|
1446
|
+
CLIPSValue *theValue = &theFact->theProposition.contents[i];
|
1447
|
+
|
1448
|
+
sp->slotName->neededSymbol = true;
|
1449
|
+
|
1450
|
+
if (theValue->header->type == MULTIFIELD_TYPE)
|
1451
|
+
{
|
1452
|
+
for (j = 0 ; j < theValue->multifieldValue->length ; j++)
|
1453
|
+
{ MarkNeededAtom(theEnv,&theValue->multifieldValue->contents[j],neededSpace); }
|
1454
|
+
}
|
1455
|
+
else
|
1456
|
+
{ MarkNeededAtom(theEnv,theValue,neededSpace); }
|
1457
|
+
sp = sp->next;
|
1458
|
+
}
|
1459
|
+
}
|
1460
|
+
}
|
1461
|
+
|
1462
|
+
/******************/
|
1463
|
+
/* MarkNeededAtom */
|
1464
|
+
/******************/
|
1465
|
+
static void MarkNeededAtom(
|
1466
|
+
Environment *theEnv,
|
1467
|
+
CLIPSValue *theValue,
|
1468
|
+
size_t *neededSpace)
|
1469
|
+
{
|
1470
|
+
*neededSpace += sizeof(struct bsaveSlotValueAtom);
|
1471
|
+
|
1472
|
+
/* =====================================
|
1473
|
+
Assumes slot value atoms can only be
|
1474
|
+
floats, integers, symbols, strings,
|
1475
|
+
instance-names, instance-addresses,
|
1476
|
+
fact-addresses or external-addresses
|
1477
|
+
===================================== */
|
1478
|
+
|
1479
|
+
// TBD fact address and external address
|
1480
|
+
|
1481
|
+
switch (theValue->header->type)
|
1482
|
+
{
|
1483
|
+
case SYMBOL_TYPE:
|
1484
|
+
case STRING_TYPE:
|
1485
|
+
case INSTANCE_NAME_TYPE:
|
1486
|
+
theValue->lexemeValue->neededSymbol = true;
|
1487
|
+
break;
|
1488
|
+
case FLOAT_TYPE:
|
1489
|
+
theValue->floatValue->neededFloat = true;
|
1490
|
+
break;
|
1491
|
+
case INTEGER_TYPE:
|
1492
|
+
theValue->integerValue->neededInteger = true;
|
1493
|
+
break;
|
1494
|
+
#if OBJECT_SYSTEM
|
1495
|
+
case INSTANCE_ADDRESS_TYPE:
|
1496
|
+
GetFullInstanceName(theEnv,theValue->instanceValue)->neededSymbol = true;
|
1497
|
+
break;
|
1498
|
+
#endif
|
1499
|
+
}
|
1500
|
+
}
|
1501
|
+
|
1502
|
+
/*********************/
|
1503
|
+
/* WriteBinaryHeader */
|
1504
|
+
/*********************/
|
1505
|
+
static void WriteBinaryHeader(
|
1506
|
+
Environment *theEnv,
|
1507
|
+
FILE *filePtr)
|
1508
|
+
{
|
1509
|
+
fwrite(BINARY_FACTS_PREFIX_ID,
|
1510
|
+
(STD_SIZE) (strlen(BINARY_FACTS_PREFIX_ID) + 1),1,filePtr);
|
1511
|
+
fwrite(BINARY_FACTS_VERSION_ID,
|
1512
|
+
(STD_SIZE) (strlen(BINARY_FACTS_VERSION_ID) + 1),1,filePtr);
|
1513
|
+
}
|
1514
|
+
|
1515
|
+
/*******************/
|
1516
|
+
/* SaveBinaryFacts */
|
1517
|
+
/*******************/
|
1518
|
+
static long SaveBinaryFacts(
|
1519
|
+
Environment *theEnv,
|
1520
|
+
FILE *filePtr,
|
1521
|
+
SaveScope saveCode,
|
1522
|
+
Deftemplate **deftemplateArray,
|
1523
|
+
unsigned int count,
|
1524
|
+
size_t *neededSpace)
|
1525
|
+
{
|
1526
|
+
Fact *theFact;
|
1527
|
+
Defmodule *theModule;
|
1528
|
+
unsigned int i;
|
1529
|
+
bool saveFact;
|
1530
|
+
long factCount = 0;
|
1531
|
+
|
1532
|
+
/*=================*/
|
1533
|
+
/* Save the facts. */
|
1534
|
+
/*=================*/
|
1535
|
+
|
1536
|
+
theModule = GetCurrentModule(theEnv);
|
1537
|
+
|
1538
|
+
for (theFact = GetNextFactInScope(theEnv,NULL);
|
1539
|
+
theFact != NULL;
|
1540
|
+
theFact = GetNextFactInScope(theEnv,theFact))
|
1541
|
+
{
|
1542
|
+
/*===========================================================*/
|
1543
|
+
/* If we're doing a local save and the facts's corresponding */
|
1544
|
+
/* deftemplate isn't in the current module, then don't save */
|
1545
|
+
/* the fact. */
|
1546
|
+
/*===========================================================*/
|
1547
|
+
|
1548
|
+
if ((saveCode == LOCAL_SAVE) &&
|
1549
|
+
(theFact->whichDeftemplate->header.whichModule->theModule != theModule))
|
1550
|
+
{ saveFact = false; }
|
1551
|
+
|
1552
|
+
/*===================================================*/
|
1553
|
+
/* Otherwise, if the list of facts to be saved isn't */
|
1554
|
+
/* restricted, then set the mark flag to true. */
|
1555
|
+
/*===================================================*/
|
1556
|
+
|
1557
|
+
else if (deftemplateArray == NULL)
|
1558
|
+
{ saveFact = true; }
|
1559
|
+
|
1560
|
+
/*=======================================================*/
|
1561
|
+
/* Otherwise see if the fact's corresponding deftemplate */
|
1562
|
+
/* is in the list of deftemplates whose facts are to be */
|
1563
|
+
/* saved. If it's in the list, then set the mark flag */
|
1564
|
+
/* to true, otherwise set it to false. */
|
1565
|
+
/*=======================================================*/
|
1566
|
+
|
1567
|
+
else
|
1568
|
+
{
|
1569
|
+
saveFact = false;
|
1570
|
+
for (i = 0; i < count; i++)
|
1571
|
+
{
|
1572
|
+
if (deftemplateArray[i] == theFact->whichDeftemplate)
|
1573
|
+
{
|
1574
|
+
saveFact = true;
|
1575
|
+
break;
|
1576
|
+
}
|
1577
|
+
}
|
1578
|
+
}
|
1579
|
+
|
1580
|
+
/*============================*/
|
1581
|
+
/* If the mark flag is set to */
|
1582
|
+
/* true, then mark the fact. */
|
1583
|
+
/*============================*/
|
1584
|
+
|
1585
|
+
if (saveFact)
|
1586
|
+
{
|
1587
|
+
factCount++;
|
1588
|
+
SaveSingleFactBinary(theEnv,filePtr,theFact);
|
1589
|
+
}
|
1590
|
+
}
|
1591
|
+
|
1592
|
+
return factCount;
|
1593
|
+
}
|
1594
|
+
|
1595
|
+
/************************/
|
1596
|
+
/* SaveSingleFactBinary */
|
1597
|
+
/************************/
|
1598
|
+
static void SaveSingleFactBinary(
|
1599
|
+
Environment *theEnv,
|
1600
|
+
FILE *filePtr,
|
1601
|
+
Fact *theFact)
|
1602
|
+
{
|
1603
|
+
unsigned long nameIndex;
|
1604
|
+
unsigned short i;
|
1605
|
+
size_t j;
|
1606
|
+
struct bsaveSlotValue bs;
|
1607
|
+
unsigned long totalValueCount = 0;
|
1608
|
+
size_t slotLen;
|
1609
|
+
unsigned short slotCount;
|
1610
|
+
bool implied;
|
1611
|
+
|
1612
|
+
/*=================================*/
|
1613
|
+
/* Write out the deftemplate name. */
|
1614
|
+
/*=================================*/
|
1615
|
+
|
1616
|
+
nameIndex = theFact->whichDeftemplate->header.name->bucket;
|
1617
|
+
fwrite(&nameIndex,sizeof(unsigned long),1,filePtr);
|
1618
|
+
|
1619
|
+
/*================================*/
|
1620
|
+
/* Save out the deftemplate type. */
|
1621
|
+
/*================================*/
|
1622
|
+
|
1623
|
+
implied = theFact->whichDeftemplate->implied;
|
1624
|
+
fwrite(&implied,sizeof(bool),1,filePtr);
|
1625
|
+
|
1626
|
+
/*================================*/
|
1627
|
+
/* Write out the number of slots. */
|
1628
|
+
/*================================*/
|
1629
|
+
|
1630
|
+
if (theFact->whichDeftemplate->implied)
|
1631
|
+
{ slotCount = 1; }
|
1632
|
+
else
|
1633
|
+
{ slotCount = theFact->whichDeftemplate->numberOfSlots; }
|
1634
|
+
|
1635
|
+
fwrite(&slotCount,sizeof(unsigned short),1,filePtr);
|
1636
|
+
|
1637
|
+
/*============================================*/
|
1638
|
+
/* Write out the slot names and value counts. */
|
1639
|
+
/*============================================*/
|
1640
|
+
|
1641
|
+
if (theFact->whichDeftemplate->implied)
|
1642
|
+
{
|
1643
|
+
CLIPSValue *theValue = &theFact->theProposition.contents[0];
|
1644
|
+
|
1645
|
+
bs.slotName = ULONG_MAX;
|
1646
|
+
bs.valueCount = (unsigned long) theValue->multifieldValue->length;
|
1647
|
+
fwrite(&bs,sizeof(struct bsaveSlotValue),1,filePtr);
|
1648
|
+
totalValueCount += bs.valueCount;
|
1649
|
+
}
|
1650
|
+
else
|
1651
|
+
{
|
1652
|
+
TemplateSlot *sp = theFact->whichDeftemplate->slotList;
|
1653
|
+
for (i = 0 ; i < slotCount; i++)
|
1654
|
+
{
|
1655
|
+
CLIPSValue *theValue = &theFact->theProposition.contents[i];
|
1656
|
+
|
1657
|
+
/*==================================================*/
|
1658
|
+
/* Write out the number of atoms in the slot value. */
|
1659
|
+
/*==================================================*/
|
1660
|
+
|
1661
|
+
bs.slotName = sp->slotName->bucket;
|
1662
|
+
bs.valueCount = (unsigned long) (sp->multislot ? theValue->multifieldValue->length : 1);
|
1663
|
+
fwrite(&bs,sizeof(struct bsaveSlotValue),1,filePtr);
|
1664
|
+
totalValueCount += bs.valueCount;
|
1665
|
+
sp = sp->next;
|
1666
|
+
}
|
1667
|
+
}
|
1668
|
+
|
1669
|
+
/*====================================*/
|
1670
|
+
/* Write out the number of slot value */
|
1671
|
+
/* atoms for the whole fact. */
|
1672
|
+
/*====================================*/
|
1673
|
+
|
1674
|
+
if (slotCount != 0)
|
1675
|
+
{ fwrite(&totalValueCount,sizeof(unsigned long),1,filePtr); }
|
1676
|
+
|
1677
|
+
/*=================================*/
|
1678
|
+
/* Write out the slot value atoms. */
|
1679
|
+
/*=================================*/
|
1680
|
+
|
1681
|
+
if (theFact->whichDeftemplate->implied)
|
1682
|
+
{
|
1683
|
+
CLIPSValue *theValue = &theFact->theProposition.contents[0];
|
1684
|
+
|
1685
|
+
for (j = 0 ; j < theValue->multifieldValue->length ; j++)
|
1686
|
+
{ SaveAtomBinary(theEnv,&theValue->multifieldValue->contents[j],filePtr); }
|
1687
|
+
}
|
1688
|
+
else
|
1689
|
+
{
|
1690
|
+
TemplateSlot *sp = theFact->whichDeftemplate->slotList;
|
1691
|
+
for (i = 0 ; i < slotCount ; i++)
|
1692
|
+
{
|
1693
|
+
CLIPSValue *theValue = &theFact->theProposition.contents[i];
|
1694
|
+
|
1695
|
+
slotLen = sp->multislot ? theValue->multifieldValue->length : 1;
|
1696
|
+
|
1697
|
+
/*============================================*/
|
1698
|
+
/* Write out the type and index of each atom. */
|
1699
|
+
/*============================================*/
|
1700
|
+
|
1701
|
+
if (sp->multislot)
|
1702
|
+
{
|
1703
|
+
for (j = 0 ; j < slotLen ; j++)
|
1704
|
+
{ SaveAtomBinary(theEnv,&theValue->multifieldValue->contents[j],filePtr); }
|
1705
|
+
}
|
1706
|
+
else
|
1707
|
+
{ SaveAtomBinary(theEnv,theValue,filePtr); }
|
1708
|
+
|
1709
|
+
sp = sp->next;
|
1710
|
+
}
|
1711
|
+
}
|
1712
|
+
}
|
1713
|
+
|
1714
|
+
/******************/
|
1715
|
+
/* SaveAtomBinary */
|
1716
|
+
/******************/
|
1717
|
+
static void SaveAtomBinary(
|
1718
|
+
Environment *theEnv,
|
1719
|
+
CLIPSValue *theValue,
|
1720
|
+
FILE *bsaveFP)
|
1721
|
+
{
|
1722
|
+
struct bsaveSlotValueAtom bsa;
|
1723
|
+
|
1724
|
+
/* =====================================
|
1725
|
+
Assumes slot value atoms can only be
|
1726
|
+
floats, integers, symbols, strings,
|
1727
|
+
instance-names, instance-addresses,
|
1728
|
+
fact-addresses or external-addresses
|
1729
|
+
===================================== */
|
1730
|
+
|
1731
|
+
// TBD fact address and external address
|
1732
|
+
|
1733
|
+
bsa.type = theValue->header->type;
|
1734
|
+
switch (theValue->header->type)
|
1735
|
+
{
|
1736
|
+
case SYMBOL_TYPE:
|
1737
|
+
case STRING_TYPE:
|
1738
|
+
case INSTANCE_NAME_TYPE:
|
1739
|
+
bsa.value = theValue->lexemeValue->bucket;
|
1740
|
+
break;
|
1741
|
+
case FLOAT_TYPE:
|
1742
|
+
bsa.value = theValue->floatValue->bucket;
|
1743
|
+
break;
|
1744
|
+
case INTEGER_TYPE:
|
1745
|
+
bsa.value = theValue->integerValue->bucket;
|
1746
|
+
break;
|
1747
|
+
#if OBJECT_SYSTEM
|
1748
|
+
case INSTANCE_ADDRESS_TYPE:
|
1749
|
+
bsa.type = INSTANCE_NAME_TYPE;
|
1750
|
+
bsa.value = GetFullInstanceName(theEnv,theValue->instanceValue)->bucket;
|
1751
|
+
break;
|
1752
|
+
#endif
|
1753
|
+
default:
|
1754
|
+
bsa.value = ULONG_MAX;
|
1755
|
+
}
|
1756
|
+
|
1757
|
+
fwrite(&bsa,sizeof(struct bsaveSlotValueAtom),1,bsaveFP);
|
1758
|
+
}
|
1759
|
+
|
1760
|
+
|
1761
|
+
#endif /* DEFTEMPLATE_CONSTRUCT */
|