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.
Files changed (346) hide show
  1. checksums.yaml +7 -0
  2. data/ext/clipsruby/agenda.c +1373 -0
  3. data/ext/clipsruby/agenda.h +169 -0
  4. data/ext/clipsruby/analysis.c +1142 -0
  5. data/ext/clipsruby/analysis.h +61 -0
  6. data/ext/clipsruby/argacces.c +526 -0
  7. data/ext/clipsruby/argacces.h +77 -0
  8. data/ext/clipsruby/bload.c +884 -0
  9. data/ext/clipsruby/bload.h +94 -0
  10. data/ext/clipsruby/bmathfun.c +557 -0
  11. data/ext/clipsruby/bmathfun.h +66 -0
  12. data/ext/clipsruby/bsave.c +634 -0
  13. data/ext/clipsruby/bsave.h +130 -0
  14. data/ext/clipsruby/classcom.c +976 -0
  15. data/ext/clipsruby/classcom.h +115 -0
  16. data/ext/clipsruby/classexm.c +1376 -0
  17. data/ext/clipsruby/classexm.h +97 -0
  18. data/ext/clipsruby/classfun.c +1392 -0
  19. data/ext/clipsruby/classfun.h +164 -0
  20. data/ext/clipsruby/classinf.c +1245 -0
  21. data/ext/clipsruby/classinf.h +94 -0
  22. data/ext/clipsruby/classini.c +843 -0
  23. data/ext/clipsruby/classini.h +75 -0
  24. data/ext/clipsruby/classpsr.c +957 -0
  25. data/ext/clipsruby/classpsr.h +73 -0
  26. data/ext/clipsruby/clips.h +133 -0
  27. data/ext/clipsruby/clipsruby.c +619 -0
  28. data/ext/clipsruby/clsltpsr.c +931 -0
  29. data/ext/clipsruby/clsltpsr.h +72 -0
  30. data/ext/clipsruby/commline.c +1217 -0
  31. data/ext/clipsruby/commline.h +131 -0
  32. data/ext/clipsruby/conscomp.c +1593 -0
  33. data/ext/clipsruby/conscomp.h +150 -0
  34. data/ext/clipsruby/constant.h +264 -0
  35. data/ext/clipsruby/constrct.c +1090 -0
  36. data/ext/clipsruby/constrct.h +216 -0
  37. data/ext/clipsruby/constrnt.c +554 -0
  38. data/ext/clipsruby/constrnt.h +132 -0
  39. data/ext/clipsruby/crstrtgy.c +1088 -0
  40. data/ext/clipsruby/crstrtgy.h +85 -0
  41. data/ext/clipsruby/cstrcbin.c +185 -0
  42. data/ext/clipsruby/cstrcbin.h +61 -0
  43. data/ext/clipsruby/cstrccmp.h +43 -0
  44. data/ext/clipsruby/cstrccom.c +1791 -0
  45. data/ext/clipsruby/cstrccom.h +115 -0
  46. data/ext/clipsruby/cstrcpsr.c +835 -0
  47. data/ext/clipsruby/cstrcpsr.h +97 -0
  48. data/ext/clipsruby/cstrnbin.c +282 -0
  49. data/ext/clipsruby/cstrnbin.h +55 -0
  50. data/ext/clipsruby/cstrnchk.c +826 -0
  51. data/ext/clipsruby/cstrnchk.h +91 -0
  52. data/ext/clipsruby/cstrncmp.c +238 -0
  53. data/ext/clipsruby/cstrncmp.h +57 -0
  54. data/ext/clipsruby/cstrnops.c +1176 -0
  55. data/ext/clipsruby/cstrnops.h +47 -0
  56. data/ext/clipsruby/cstrnpsr.c +1394 -0
  57. data/ext/clipsruby/cstrnpsr.h +88 -0
  58. data/ext/clipsruby/cstrnutl.c +564 -0
  59. data/ext/clipsruby/cstrnutl.h +54 -0
  60. data/ext/clipsruby/default.c +454 -0
  61. data/ext/clipsruby/default.h +57 -0
  62. data/ext/clipsruby/defins.c +971 -0
  63. data/ext/clipsruby/defins.h +127 -0
  64. data/ext/clipsruby/developr.c +677 -0
  65. data/ext/clipsruby/developr.h +69 -0
  66. data/ext/clipsruby/dffctbin.c +477 -0
  67. data/ext/clipsruby/dffctbin.h +76 -0
  68. data/ext/clipsruby/dffctbsc.c +308 -0
  69. data/ext/clipsruby/dffctbsc.h +72 -0
  70. data/ext/clipsruby/dffctcmp.c +297 -0
  71. data/ext/clipsruby/dffctcmp.h +44 -0
  72. data/ext/clipsruby/dffctdef.c +364 -0
  73. data/ext/clipsruby/dffctdef.h +104 -0
  74. data/ext/clipsruby/dffctpsr.c +179 -0
  75. data/ext/clipsruby/dffctpsr.h +49 -0
  76. data/ext/clipsruby/dffnxbin.c +520 -0
  77. data/ext/clipsruby/dffnxbin.h +67 -0
  78. data/ext/clipsruby/dffnxcmp.c +378 -0
  79. data/ext/clipsruby/dffnxcmp.h +54 -0
  80. data/ext/clipsruby/dffnxexe.c +241 -0
  81. data/ext/clipsruby/dffnxexe.h +58 -0
  82. data/ext/clipsruby/dffnxfun.c +1192 -0
  83. data/ext/clipsruby/dffnxfun.h +155 -0
  84. data/ext/clipsruby/dffnxpsr.c +514 -0
  85. data/ext/clipsruby/dffnxpsr.h +57 -0
  86. data/ext/clipsruby/dfinsbin.c +509 -0
  87. data/ext/clipsruby/dfinsbin.h +66 -0
  88. data/ext/clipsruby/dfinscmp.c +345 -0
  89. data/ext/clipsruby/dfinscmp.h +48 -0
  90. data/ext/clipsruby/drive.c +1191 -0
  91. data/ext/clipsruby/drive.h +65 -0
  92. data/ext/clipsruby/emathfun.c +1213 -0
  93. data/ext/clipsruby/emathfun.h +99 -0
  94. data/ext/clipsruby/engine.c +1568 -0
  95. data/ext/clipsruby/engine.h +203 -0
  96. data/ext/clipsruby/entities.h +276 -0
  97. data/ext/clipsruby/envrnbld.c +514 -0
  98. data/ext/clipsruby/envrnbld.h +40 -0
  99. data/ext/clipsruby/envrnmnt.c +257 -0
  100. data/ext/clipsruby/envrnmnt.h +112 -0
  101. data/ext/clipsruby/evaluatn.c +1736 -0
  102. data/ext/clipsruby/evaluatn.h +211 -0
  103. data/ext/clipsruby/expressn.c +494 -0
  104. data/ext/clipsruby/expressn.h +154 -0
  105. data/ext/clipsruby/exprnbin.c +538 -0
  106. data/ext/clipsruby/exprnbin.h +60 -0
  107. data/ext/clipsruby/exprnops.c +564 -0
  108. data/ext/clipsruby/exprnops.h +67 -0
  109. data/ext/clipsruby/exprnpsr.c +1112 -0
  110. data/ext/clipsruby/exprnpsr.h +98 -0
  111. data/ext/clipsruby/extconf.rb +2 -0
  112. data/ext/clipsruby/extnfunc.c +1015 -0
  113. data/ext/clipsruby/extnfunc.h +157 -0
  114. data/ext/clipsruby/factbin.c +447 -0
  115. data/ext/clipsruby/factbin.h +56 -0
  116. data/ext/clipsruby/factbld.c +1035 -0
  117. data/ext/clipsruby/factbld.h +63 -0
  118. data/ext/clipsruby/factcmp.c +386 -0
  119. data/ext/clipsruby/factcmp.h +46 -0
  120. data/ext/clipsruby/factcom.c +759 -0
  121. data/ext/clipsruby/factcom.h +80 -0
  122. data/ext/clipsruby/factfile.c +1761 -0
  123. data/ext/clipsruby/factfile.h +54 -0
  124. data/ext/clipsruby/factfun.c +682 -0
  125. data/ext/clipsruby/factfun.h +77 -0
  126. data/ext/clipsruby/factgen.c +1305 -0
  127. data/ext/clipsruby/factgen.h +229 -0
  128. data/ext/clipsruby/facthsh.c +438 -0
  129. data/ext/clipsruby/facthsh.h +81 -0
  130. data/ext/clipsruby/factlhs.c +250 -0
  131. data/ext/clipsruby/factlhs.h +54 -0
  132. data/ext/clipsruby/factmch.c +905 -0
  133. data/ext/clipsruby/factmch.h +68 -0
  134. data/ext/clipsruby/factmngr.c +3373 -0
  135. data/ext/clipsruby/factmngr.h +325 -0
  136. data/ext/clipsruby/factprt.c +498 -0
  137. data/ext/clipsruby/factprt.h +60 -0
  138. data/ext/clipsruby/factqpsr.c +796 -0
  139. data/ext/clipsruby/factqpsr.h +61 -0
  140. data/ext/clipsruby/factqury.c +1267 -0
  141. data/ext/clipsruby/factqury.h +112 -0
  142. data/ext/clipsruby/factrete.c +978 -0
  143. data/ext/clipsruby/factrete.h +70 -0
  144. data/ext/clipsruby/factrhs.c +667 -0
  145. data/ext/clipsruby/factrhs.h +55 -0
  146. data/ext/clipsruby/filecom.c +353 -0
  147. data/ext/clipsruby/filecom.h +137 -0
  148. data/ext/clipsruby/filertr.c +481 -0
  149. data/ext/clipsruby/filertr.h +94 -0
  150. data/ext/clipsruby/fileutil.c +1020 -0
  151. data/ext/clipsruby/fileutil.h +50 -0
  152. data/ext/clipsruby/generate.c +1079 -0
  153. data/ext/clipsruby/generate.h +57 -0
  154. data/ext/clipsruby/genrcbin.c +902 -0
  155. data/ext/clipsruby/genrcbin.h +69 -0
  156. data/ext/clipsruby/genrccmp.c +640 -0
  157. data/ext/clipsruby/genrccmp.h +59 -0
  158. data/ext/clipsruby/genrccom.c +2017 -0
  159. data/ext/clipsruby/genrccom.h +119 -0
  160. data/ext/clipsruby/genrcexe.c +737 -0
  161. data/ext/clipsruby/genrcexe.h +73 -0
  162. data/ext/clipsruby/genrcfun.c +890 -0
  163. data/ext/clipsruby/genrcfun.h +185 -0
  164. data/ext/clipsruby/genrcpsr.c +1618 -0
  165. data/ext/clipsruby/genrcpsr.h +80 -0
  166. data/ext/clipsruby/globlbin.c +458 -0
  167. data/ext/clipsruby/globlbin.h +71 -0
  168. data/ext/clipsruby/globlbsc.c +361 -0
  169. data/ext/clipsruby/globlbsc.h +83 -0
  170. data/ext/clipsruby/globlcmp.c +330 -0
  171. data/ext/clipsruby/globlcmp.h +52 -0
  172. data/ext/clipsruby/globlcom.c +289 -0
  173. data/ext/clipsruby/globlcom.h +63 -0
  174. data/ext/clipsruby/globldef.c +1087 -0
  175. data/ext/clipsruby/globldef.h +151 -0
  176. data/ext/clipsruby/globlpsr.c +530 -0
  177. data/ext/clipsruby/globlpsr.h +59 -0
  178. data/ext/clipsruby/immthpsr.c +431 -0
  179. data/ext/clipsruby/immthpsr.h +55 -0
  180. data/ext/clipsruby/incrrset.c +530 -0
  181. data/ext/clipsruby/incrrset.h +73 -0
  182. data/ext/clipsruby/inherpsr.c +850 -0
  183. data/ext/clipsruby/inherpsr.h +52 -0
  184. data/ext/clipsruby/inscom.c +2076 -0
  185. data/ext/clipsruby/inscom.h +182 -0
  186. data/ext/clipsruby/insfile.c +1764 -0
  187. data/ext/clipsruby/insfile.h +96 -0
  188. data/ext/clipsruby/insfun.c +1451 -0
  189. data/ext/clipsruby/insfun.h +134 -0
  190. data/ext/clipsruby/insmngr.c +2550 -0
  191. data/ext/clipsruby/insmngr.h +125 -0
  192. data/ext/clipsruby/insmoddp.c +1041 -0
  193. data/ext/clipsruby/insmoddp.h +91 -0
  194. data/ext/clipsruby/insmult.c +804 -0
  195. data/ext/clipsruby/insmult.h +62 -0
  196. data/ext/clipsruby/inspsr.c +602 -0
  197. data/ext/clipsruby/inspsr.h +60 -0
  198. data/ext/clipsruby/insquery.c +1278 -0
  199. data/ext/clipsruby/insquery.h +115 -0
  200. data/ext/clipsruby/insqypsr.c +729 -0
  201. data/ext/clipsruby/insqypsr.h +63 -0
  202. data/ext/clipsruby/iofun.c +2045 -0
  203. data/ext/clipsruby/iofun.h +116 -0
  204. data/ext/clipsruby/lgcldpnd.c +644 -0
  205. data/ext/clipsruby/lgcldpnd.h +75 -0
  206. data/ext/clipsruby/main.c +112 -0
  207. data/ext/clipsruby/match.h +142 -0
  208. data/ext/clipsruby/memalloc.c +481 -0
  209. data/ext/clipsruby/memalloc.h +197 -0
  210. data/ext/clipsruby/miscfun.c +1801 -0
  211. data/ext/clipsruby/miscfun.h +132 -0
  212. data/ext/clipsruby/modulbin.c +607 -0
  213. data/ext/clipsruby/modulbin.h +84 -0
  214. data/ext/clipsruby/modulbsc.c +347 -0
  215. data/ext/clipsruby/modulbsc.h +67 -0
  216. data/ext/clipsruby/modulcmp.c +499 -0
  217. data/ext/clipsruby/modulcmp.h +54 -0
  218. data/ext/clipsruby/moduldef.c +817 -0
  219. data/ext/clipsruby/moduldef.h +271 -0
  220. data/ext/clipsruby/modulpsr.c +1150 -0
  221. data/ext/clipsruby/modulpsr.h +69 -0
  222. data/ext/clipsruby/modulutl.c +1036 -0
  223. data/ext/clipsruby/modulutl.h +84 -0
  224. data/ext/clipsruby/msgcom.c +1221 -0
  225. data/ext/clipsruby/msgcom.h +125 -0
  226. data/ext/clipsruby/msgfun.c +1076 -0
  227. data/ext/clipsruby/msgfun.h +118 -0
  228. data/ext/clipsruby/msgpass.c +1441 -0
  229. data/ext/clipsruby/msgpass.h +103 -0
  230. data/ext/clipsruby/msgpsr.c +698 -0
  231. data/ext/clipsruby/msgpsr.h +73 -0
  232. data/ext/clipsruby/multifld.c +1404 -0
  233. data/ext/clipsruby/multifld.h +130 -0
  234. data/ext/clipsruby/multifun.c +2182 -0
  235. data/ext/clipsruby/multifun.h +102 -0
  236. data/ext/clipsruby/network.h +142 -0
  237. data/ext/clipsruby/objbin.c +1522 -0
  238. data/ext/clipsruby/objbin.h +79 -0
  239. data/ext/clipsruby/objcmp.c +1507 -0
  240. data/ext/clipsruby/objcmp.h +71 -0
  241. data/ext/clipsruby/object.h +260 -0
  242. data/ext/clipsruby/objrtbin.c +701 -0
  243. data/ext/clipsruby/objrtbin.h +79 -0
  244. data/ext/clipsruby/objrtbld.c +2393 -0
  245. data/ext/clipsruby/objrtbld.h +66 -0
  246. data/ext/clipsruby/objrtcmp.c +734 -0
  247. data/ext/clipsruby/objrtcmp.h +66 -0
  248. data/ext/clipsruby/objrtfnx.c +1330 -0
  249. data/ext/clipsruby/objrtfnx.h +222 -0
  250. data/ext/clipsruby/objrtgen.c +736 -0
  251. data/ext/clipsruby/objrtgen.h +63 -0
  252. data/ext/clipsruby/objrtmch.c +1524 -0
  253. data/ext/clipsruby/objrtmch.h +160 -0
  254. data/ext/clipsruby/parsefun.c +415 -0
  255. data/ext/clipsruby/parsefun.h +67 -0
  256. data/ext/clipsruby/pattern.c +1265 -0
  257. data/ext/clipsruby/pattern.h +163 -0
  258. data/ext/clipsruby/pprint.c +328 -0
  259. data/ext/clipsruby/pprint.h +79 -0
  260. data/ext/clipsruby/prccode.c +1478 -0
  261. data/ext/clipsruby/prccode.h +145 -0
  262. data/ext/clipsruby/prcdrfun.c +640 -0
  263. data/ext/clipsruby/prcdrfun.h +95 -0
  264. data/ext/clipsruby/prcdrpsr.c +1068 -0
  265. data/ext/clipsruby/prcdrpsr.h +79 -0
  266. data/ext/clipsruby/prdctfun.c +869 -0
  267. data/ext/clipsruby/prdctfun.h +77 -0
  268. data/ext/clipsruby/prntutil.c +878 -0
  269. data/ext/clipsruby/prntutil.h +125 -0
  270. data/ext/clipsruby/proflfun.c +827 -0
  271. data/ext/clipsruby/proflfun.h +118 -0
  272. data/ext/clipsruby/reorder.c +2082 -0
  273. data/ext/clipsruby/reorder.h +172 -0
  274. data/ext/clipsruby/reteutil.c +1732 -0
  275. data/ext/clipsruby/reteutil.h +111 -0
  276. data/ext/clipsruby/retract.c +710 -0
  277. data/ext/clipsruby/retract.h +74 -0
  278. data/ext/clipsruby/router.c +737 -0
  279. data/ext/clipsruby/router.h +147 -0
  280. data/ext/clipsruby/rulebin.c +1136 -0
  281. data/ext/clipsruby/rulebin.h +153 -0
  282. data/ext/clipsruby/rulebld.c +1328 -0
  283. data/ext/clipsruby/rulebld.h +62 -0
  284. data/ext/clipsruby/rulebsc.c +517 -0
  285. data/ext/clipsruby/rulebsc.h +91 -0
  286. data/ext/clipsruby/rulecmp.c +733 -0
  287. data/ext/clipsruby/rulecmp.h +63 -0
  288. data/ext/clipsruby/rulecom.c +1583 -0
  289. data/ext/clipsruby/rulecom.h +116 -0
  290. data/ext/clipsruby/rulecstr.c +892 -0
  291. data/ext/clipsruby/rulecstr.h +53 -0
  292. data/ext/clipsruby/ruledef.c +559 -0
  293. data/ext/clipsruby/ruledef.h +179 -0
  294. data/ext/clipsruby/ruledlt.c +599 -0
  295. data/ext/clipsruby/ruledlt.h +58 -0
  296. data/ext/clipsruby/rulelhs.c +1216 -0
  297. data/ext/clipsruby/rulelhs.h +52 -0
  298. data/ext/clipsruby/rulepsr.c +1073 -0
  299. data/ext/clipsruby/rulepsr.h +61 -0
  300. data/ext/clipsruby/scanner.c +856 -0
  301. data/ext/clipsruby/scanner.h +112 -0
  302. data/ext/clipsruby/setup.h +488 -0
  303. data/ext/clipsruby/sortfun.c +433 -0
  304. data/ext/clipsruby/sortfun.h +55 -0
  305. data/ext/clipsruby/strngfun.c +1173 -0
  306. data/ext/clipsruby/strngfun.h +96 -0
  307. data/ext/clipsruby/strngrtr.c +523 -0
  308. data/ext/clipsruby/strngrtr.h +97 -0
  309. data/ext/clipsruby/symblbin.c +648 -0
  310. data/ext/clipsruby/symblbin.h +64 -0
  311. data/ext/clipsruby/symblcmp.c +893 -0
  312. data/ext/clipsruby/symblcmp.h +61 -0
  313. data/ext/clipsruby/symbol.c +1961 -0
  314. data/ext/clipsruby/symbol.h +243 -0
  315. data/ext/clipsruby/sysdep.c +894 -0
  316. data/ext/clipsruby/sysdep.h +164 -0
  317. data/ext/clipsruby/textpro.c +1388 -0
  318. data/ext/clipsruby/textpro.h +77 -0
  319. data/ext/clipsruby/tmpltbin.c +609 -0
  320. data/ext/clipsruby/tmpltbin.h +108 -0
  321. data/ext/clipsruby/tmpltbsc.c +327 -0
  322. data/ext/clipsruby/tmpltbsc.h +87 -0
  323. data/ext/clipsruby/tmpltcmp.c +450 -0
  324. data/ext/clipsruby/tmpltcmp.h +57 -0
  325. data/ext/clipsruby/tmpltdef.c +584 -0
  326. data/ext/clipsruby/tmpltdef.h +155 -0
  327. data/ext/clipsruby/tmpltfun.c +2477 -0
  328. data/ext/clipsruby/tmpltfun.h +122 -0
  329. data/ext/clipsruby/tmpltlhs.c +379 -0
  330. data/ext/clipsruby/tmpltlhs.h +50 -0
  331. data/ext/clipsruby/tmpltpsr.c +819 -0
  332. data/ext/clipsruby/tmpltpsr.h +59 -0
  333. data/ext/clipsruby/tmpltrhs.c +595 -0
  334. data/ext/clipsruby/tmpltrhs.h +55 -0
  335. data/ext/clipsruby/tmpltutl.c +637 -0
  336. data/ext/clipsruby/tmpltutl.h +82 -0
  337. data/ext/clipsruby/userdata.c +156 -0
  338. data/ext/clipsruby/userdata.h +72 -0
  339. data/ext/clipsruby/userfunctions.c +70 -0
  340. data/ext/clipsruby/usrsetup.h +7 -0
  341. data/ext/clipsruby/utility.c +1594 -0
  342. data/ext/clipsruby/utility.h +250 -0
  343. data/ext/clipsruby/watch.c +865 -0
  344. data/ext/clipsruby/watch.h +124 -0
  345. data/lib/clipsruby.rb +1 -0
  346. 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 */