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,3373 @@
1
+ /*******************************************************/
2
+ /* "C" Language Integrated Production System */
3
+ /* */
4
+ /* CLIPS Version 6.41 03/15/23 */
5
+ /* */
6
+ /* FACT MANAGER MODULE */
7
+ /*******************************************************/
8
+
9
+ /*************************************************************/
10
+ /* Purpose: Provides core routines for maintaining the fact */
11
+ /* list including assert/retract operations, data */
12
+ /* structure creation/deletion, printing, slot access, */
13
+ /* and other utility functions. */
14
+ /* */
15
+ /* Principal Programmer(s): */
16
+ /* Gary D. Riley */
17
+ /* */
18
+ /* Contributing Programmer(s): */
19
+ /* Brian L. Dantes */
20
+ /* */
21
+ /* Revision History: */
22
+ /* */
23
+ /* 6.23: Added support for templates maintaining their */
24
+ /* own list of facts. */
25
+ /* */
26
+ /* 6.24: Removed LOGICAL_DEPENDENCIES compilation flag. */
27
+ /* */
28
+ /* Renamed BOOLEAN macro type to intBool. */
29
+ /* */
30
+ /* AssignFactSlotDefaults function does not */
31
+ /* properly handle defaults for multifield slots. */
32
+ /* DR0869 */
33
+ /* */
34
+ /* Support for ppfact command. */
35
+ /* */
36
+ /* 6.30: Callback function support for assertion, */
37
+ /* retraction, and modification of facts. */
38
+ /* */
39
+ /* Updates to fact pattern entity record. */
40
+ /* */
41
+ /* Changed integer type/precision. */
42
+ /* */
43
+ /* Changed garbage collection algorithm. */
44
+ /* */
45
+ /* Removed conditional code for unsupported */
46
+ /* compilers/operating systems (IBM_MCW, */
47
+ /* MAC_MCW, and IBM_TBC). */
48
+ /* */
49
+ /* Added const qualifiers to remove C++ */
50
+ /* deprecation warnings. */
51
+ /* */
52
+ /* Converted API macros to function calls. */
53
+ /* */
54
+ /* Removed unused global variables. */
55
+ /* */
56
+ /* Added code to prevent a clear command from */
57
+ /* being executed during fact assertions via */
58
+ /* JoinOperationInProgress mechanism. */
59
+ /* */
60
+ /* Added code to keep track of pointers to */
61
+ /* constructs that are contained externally to */
62
+ /* to constructs, DanglingConstructs. */
63
+ /* */
64
+ /* 6.31: Added NULL check for slotName in function */
65
+ /* EnvGetFactSlot. Return value of FALSE now */
66
+ /* returned if garbage flag set for fact. */
67
+ /* */
68
+ /* Added constraint checking for slot value in */
69
+ /* EnvPutFactSlot function. */
70
+ /* */
71
+ /* Calling EnvFactExistp for a fact that has */
72
+ /* been created, but not asserted now returns */
73
+ /* FALSE. */
74
+ /* */
75
+ /* Calling EnvRetract for a fact that has been */
76
+ /* created, but not asserted now returns FALSE. */
77
+ /* */
78
+ /* Calling EnvAssignFactSlotDefaults or */
79
+ /* EnvPutFactSlot for a fact that has been */
80
+ /* asserted now returns FALSE. */
81
+ /* */
82
+ /* Retracted and existing facts cannot be */
83
+ /* asserted. */
84
+ /* */
85
+ /* Crash bug fix for modifying fact with invalid */
86
+ /* slot name. */
87
+ /* */
88
+ /* 6.40: Added Env prefix to GetEvaluationError and */
89
+ /* SetEvaluationError functions. */
90
+ /* */
91
+ /* Pragma once and other inclusion changes. */
92
+ /* */
93
+ /* Added support for booleans with <stdbool.h>. */
94
+ /* */
95
+ /* Removed use of void pointers for specific */
96
+ /* data structures. */
97
+ /* */
98
+ /* ALLOW_ENVIRONMENT_GLOBALS no longer supported. */
99
+ /* */
100
+ /* Callbacks must be environment aware. */
101
+ /* */
102
+ /* UDF redesign. */
103
+ /* */
104
+ /* Removed initial-fact support. */
105
+ /* */
106
+ /* Watch facts for modify command only prints */
107
+ /* changed slots. */
108
+ /* */
109
+ /* Modify command preserves fact id and address. */
110
+ /* */
111
+ /* Assert returns duplicate fact. FALSE is now */
112
+ /* returned only if an error occurs. */
113
+ /* */
114
+ /* Pretty print functions accept optional logical */
115
+ /* name argument. */
116
+ /* */
117
+ /* 6.41: Used gensnprintf in place of gensprintf and. */
118
+ /* sprintf. */
119
+ /* */
120
+ /* Missing break statement in AssertString switch */
121
+ /* block. */
122
+ /* */
123
+ /* Calling FMPutSlot with empty multifield to */
124
+ /* multifield slot did not assign value. */
125
+ /* */
126
+ /* FMModify was releasing a multifield that was */
127
+ /* allocated to the fact just modified. */
128
+ /* */
129
+ /*************************************************************/
130
+
131
+ #include <stdio.h>
132
+
133
+ #include "setup.h"
134
+
135
+ #if DEFTEMPLATE_CONSTRUCT && DEFRULE_CONSTRUCT
136
+
137
+ #include "commline.h"
138
+ #include "default.h"
139
+ #include "engine.h"
140
+ #include "factbin.h"
141
+ #include "factcmp.h"
142
+ #include "factcom.h"
143
+ #include "factfile.h"
144
+ #include "factfun.h"
145
+ #include "factmch.h"
146
+ #include "factqury.h"
147
+ #include "factrhs.h"
148
+ #include "lgcldpnd.h"
149
+ #include "memalloc.h"
150
+ #include "multifld.h"
151
+ #include "retract.h"
152
+ #include "prntutil.h"
153
+ #include "router.h"
154
+ #include "strngrtr.h"
155
+ #include "sysdep.h"
156
+ #include "tmpltbsc.h"
157
+ #include "tmpltfun.h"
158
+ #include "tmpltutl.h"
159
+ #include "utility.h"
160
+ #include "watch.h"
161
+ #include "cstrnchk.h"
162
+
163
+ #include "factmngr.h"
164
+
165
+ /***************************************/
166
+ /* LOCAL INTERNAL FUNCTION DEFINITIONS */
167
+ /***************************************/
168
+
169
+ static void ResetFacts(Environment *,void *);
170
+ static bool ClearFactsReady(Environment *,void *);
171
+ static void RemoveGarbageFacts(Environment *,void *);
172
+ static void DeallocateFactData(Environment *);
173
+ static bool RetractCallback(Fact *,Environment *);
174
+
175
+ /**************************************************************/
176
+ /* InitializeFacts: Initializes the fact data representation. */
177
+ /* Facts are only available when both the defrule and */
178
+ /* deftemplate constructs are available. */
179
+ /**************************************************************/
180
+ void InitializeFacts(
181
+ Environment *theEnv)
182
+ {
183
+ struct patternEntityRecord factInfo =
184
+ { { "FACT_ADDRESS_TYPE", FACT_ADDRESS_TYPE,1,0,0,
185
+ (EntityPrintFunction *) PrintFactIdentifier,
186
+ (EntityPrintFunction *) PrintFactIdentifierInLongForm,
187
+ (bool (*)(void *,Environment *)) RetractCallback,
188
+ NULL,
189
+ (void *(*)(void *,void *)) GetNextFact,
190
+ (EntityBusyCountFunction *) DecrementFactCallback,
191
+ (EntityBusyCountFunction *) IncrementFactCallback,
192
+ NULL,NULL,NULL,NULL,NULL
193
+ },
194
+ (void (*)(Environment *,void *)) DecrementFactBasisCount,
195
+ (void (*)(Environment *,void *)) IncrementFactBasisCount,
196
+ (void (*)(Environment *,void *)) MatchFactFunction,
197
+ NULL,
198
+ (bool (*)(Environment *,void *)) FactIsDeleted
199
+ };
200
+
201
+ Fact dummyFact = { { { { FACT_ADDRESS_TYPE } , NULL, NULL, 0, 0L } },
202
+ NULL, NULL, -1L, 0, 1,
203
+ NULL, NULL, NULL, NULL, NULL,
204
+ { {MULTIFIELD_TYPE } , 1, 0UL, NULL, { { { NULL } } } } };
205
+
206
+ AllocateEnvironmentData(theEnv,FACTS_DATA,sizeof(struct factsData),DeallocateFactData);
207
+
208
+ memcpy(&FactData(theEnv)->FactInfo,&factInfo,sizeof(struct patternEntityRecord));
209
+ dummyFact.patternHeader.theInfo = &FactData(theEnv)->FactInfo;
210
+ memcpy(&FactData(theEnv)->DummyFact,&dummyFact,sizeof(struct fact));
211
+ FactData(theEnv)->LastModuleIndex = -1;
212
+
213
+ /*=========================================*/
214
+ /* Initialize the fact hash table (used to */
215
+ /* quickly determine if a fact exists). */
216
+ /*=========================================*/
217
+
218
+ InitializeFactHashTable(theEnv);
219
+
220
+ /*============================================*/
221
+ /* Initialize the fact callback functions for */
222
+ /* use with the reset and clear commands. */
223
+ /*============================================*/
224
+
225
+ AddResetFunction(theEnv,"facts",ResetFacts,60,NULL);
226
+ AddClearReadyFunction(theEnv,"facts",ClearFactsReady,0,NULL);
227
+
228
+ /*=============================*/
229
+ /* Initialize periodic garbage */
230
+ /* collection for facts. */
231
+ /*=============================*/
232
+
233
+ AddCleanupFunction(theEnv,"facts",RemoveGarbageFacts,0,NULL);
234
+
235
+ /*===================================*/
236
+ /* Initialize fact pattern matching. */
237
+ /*===================================*/
238
+
239
+ InitializeFactPatterns(theEnv);
240
+
241
+ /*==================================*/
242
+ /* Initialize the facts keyword for */
243
+ /* use with the watch command. */
244
+ /*==================================*/
245
+
246
+ #if DEBUGGING_FUNCTIONS
247
+ AddWatchItem(theEnv,"facts",0,&FactData(theEnv)->WatchFacts,80,
248
+ DeftemplateWatchAccess,DeftemplateWatchPrint);
249
+ #endif
250
+
251
+ /*=========================================*/
252
+ /* Initialize fact commands and functions. */
253
+ /*=========================================*/
254
+
255
+ FactCommandDefinitions(theEnv);
256
+ FactFileCommandDefinitions(theEnv);
257
+ FactFunctionDefinitions(theEnv);
258
+
259
+ /*==============================*/
260
+ /* Initialize fact set queries. */
261
+ /*==============================*/
262
+
263
+ #if FACT_SET_QUERIES
264
+ SetupFactQuery(theEnv);
265
+ #endif
266
+
267
+ /*==================================*/
268
+ /* Initialize fact patterns for use */
269
+ /* with the bload/bsave commands. */
270
+ /*==================================*/
271
+
272
+ #if (BLOAD || BLOAD_ONLY || BLOAD_AND_BSAVE) && (! RUN_TIME)
273
+ FactBinarySetup(theEnv);
274
+ #endif
275
+
276
+ /*===================================*/
277
+ /* Initialize fact patterns for use */
278
+ /* with the constructs-to-c command. */
279
+ /*===================================*/
280
+
281
+ #if CONSTRUCT_COMPILER && (! RUN_TIME)
282
+ FactPatternsCompilerSetup(theEnv);
283
+ #endif
284
+ }
285
+
286
+ /***********************************/
287
+ /* DeallocateFactData: Deallocates */
288
+ /* environment data for facts. */
289
+ /***********************************/
290
+ static void DeallocateFactData(
291
+ Environment *theEnv)
292
+ {
293
+ struct factHashEntry *tmpFHEPtr, *nextFHEPtr;
294
+ Fact *tmpFactPtr, *nextFactPtr;
295
+ unsigned long i;
296
+ struct patternMatch *theMatch, *tmpMatch;
297
+
298
+ for (i = 0; i < FactData(theEnv)->FactHashTableSize; i++)
299
+ {
300
+ tmpFHEPtr = FactData(theEnv)->FactHashTable[i];
301
+
302
+ while (tmpFHEPtr != NULL)
303
+ {
304
+ nextFHEPtr = tmpFHEPtr->next;
305
+ rtn_struct(theEnv,factHashEntry,tmpFHEPtr);
306
+ tmpFHEPtr = nextFHEPtr;
307
+ }
308
+ }
309
+
310
+ rm(theEnv,FactData(theEnv)->FactHashTable,
311
+ sizeof(struct factHashEntry *) * FactData(theEnv)->FactHashTableSize);
312
+
313
+ tmpFactPtr = FactData(theEnv)->FactList;
314
+ while (tmpFactPtr != NULL)
315
+ {
316
+ nextFactPtr = tmpFactPtr->nextFact;
317
+
318
+ theMatch = (struct patternMatch *) tmpFactPtr->list;
319
+ while (theMatch != NULL)
320
+ {
321
+ tmpMatch = theMatch->next;
322
+ rtn_struct(theEnv,patternMatch,theMatch);
323
+ theMatch = tmpMatch;
324
+ }
325
+
326
+ ReturnEntityDependencies(theEnv,(struct patternEntity *) tmpFactPtr);
327
+
328
+ ReturnFact(theEnv,tmpFactPtr);
329
+ tmpFactPtr = nextFactPtr;
330
+ }
331
+
332
+ tmpFactPtr = FactData(theEnv)->GarbageFacts;
333
+ while (tmpFactPtr != NULL)
334
+ {
335
+ nextFactPtr = tmpFactPtr->nextFact;
336
+ ReturnFact(theEnv,tmpFactPtr);
337
+ tmpFactPtr = nextFactPtr;
338
+ }
339
+
340
+ DeallocateCallListWithArg(theEnv,FactData(theEnv)->ListOfAssertFunctions);
341
+ DeallocateCallListWithArg(theEnv,FactData(theEnv)->ListOfRetractFunctions);
342
+ DeallocateModifyCallList(theEnv,FactData(theEnv)->ListOfModifyFunctions);
343
+ }
344
+
345
+ /**********************************************/
346
+ /* PrintFactWithIdentifier: Displays a single */
347
+ /* fact preceded by its fact identifier. */
348
+ /**********************************************/
349
+ void PrintFactWithIdentifier(
350
+ Environment *theEnv,
351
+ const char *logicalName,
352
+ Fact *factPtr,
353
+ const char *changeMap)
354
+ {
355
+ char printSpace[20];
356
+
357
+ gensnprintf(printSpace,sizeof(printSpace),"f-%-5lld ",factPtr->factIndex);
358
+ WriteString(theEnv,logicalName,printSpace);
359
+ PrintFact(theEnv,logicalName,factPtr,false,false,changeMap);
360
+ }
361
+
362
+ /****************************************************/
363
+ /* PrintFactIdentifier: Displays a fact identifier. */
364
+ /****************************************************/
365
+ void PrintFactIdentifier(
366
+ Environment *theEnv,
367
+ const char *logicalName,
368
+ Fact *factPtr)
369
+ {
370
+ char printSpace[20];
371
+
372
+ gensnprintf(printSpace,sizeof(printSpace),"f-%lld",factPtr->factIndex);
373
+ WriteString(theEnv,logicalName,printSpace);
374
+ }
375
+
376
+ /********************************************/
377
+ /* PrintFactIdentifierInLongForm: Display a */
378
+ /* fact identifier in a longer format. */
379
+ /********************************************/
380
+ void PrintFactIdentifierInLongForm(
381
+ Environment *theEnv,
382
+ const char *logicalName,
383
+ Fact *factPtr)
384
+ {
385
+ if (PrintUtilityData(theEnv)->AddressesToStrings) WriteString(theEnv,logicalName,"\"");
386
+ if (factPtr != &FactData(theEnv)->DummyFact)
387
+ {
388
+ WriteString(theEnv,logicalName,"<Fact-");
389
+ WriteInteger(theEnv,logicalName,factPtr->factIndex);
390
+ WriteString(theEnv,logicalName,">");
391
+ }
392
+ else
393
+ { WriteString(theEnv,logicalName,"<Dummy Fact>"); }
394
+
395
+ if (PrintUtilityData(theEnv)->AddressesToStrings) WriteString(theEnv,logicalName,"\"");
396
+ }
397
+
398
+ /*******************************************/
399
+ /* DecrementFactBasisCount: Decrements the */
400
+ /* partial match busy count of a fact */
401
+ /*******************************************/
402
+ void DecrementFactBasisCount(
403
+ Environment *theEnv,
404
+ Fact *factPtr)
405
+ {
406
+ Multifield *theSegment;
407
+ size_t i;
408
+
409
+ ReleaseFact(factPtr);
410
+
411
+ if (factPtr->basisSlots != NULL)
412
+ {
413
+ theSegment = factPtr->basisSlots;
414
+ factPtr->basisSlots->busyCount--;
415
+ }
416
+ else
417
+ { theSegment = &factPtr->theProposition; }
418
+
419
+ for (i = 0 ; i < theSegment->length ; i++)
420
+ { AtomDeinstall(theEnv,theSegment->contents[i].header->type,theSegment->contents[i].value); }
421
+
422
+ if ((factPtr->basisSlots != NULL) && (factPtr->basisSlots->busyCount == 0))
423
+ {
424
+ ReturnMultifield(theEnv,factPtr->basisSlots);
425
+ factPtr->basisSlots = NULL;
426
+ }
427
+ }
428
+
429
+ /*******************************************/
430
+ /* IncrementFactBasisCount: Increments the */
431
+ /* partial match busy count of a fact. */
432
+ /*******************************************/
433
+ void IncrementFactBasisCount(
434
+ Environment *theEnv,
435
+ Fact *factPtr)
436
+ {
437
+ Multifield *theSegment;
438
+ size_t i;
439
+
440
+ RetainFact(factPtr);
441
+
442
+ theSegment = &factPtr->theProposition;
443
+
444
+ if (theSegment->length != 0)
445
+ {
446
+ if (factPtr->basisSlots != NULL)
447
+ {
448
+ factPtr->basisSlots->busyCount++;
449
+ }
450
+ else
451
+ {
452
+ factPtr->basisSlots = CopyMultifield(theEnv,theSegment);
453
+ factPtr->basisSlots->busyCount = 1;
454
+ }
455
+ theSegment = factPtr->basisSlots;
456
+ }
457
+
458
+ for (i = 0 ; i < theSegment->length ; i++)
459
+ {
460
+ AtomInstall(theEnv,theSegment->contents[i].header->type,theSegment->contents[i].value);
461
+ }
462
+ }
463
+
464
+ /******************/
465
+ /* FactIsDeleted: */
466
+ /******************/
467
+ bool FactIsDeleted(
468
+ Environment *theEnv,
469
+ Fact *theFact)
470
+ {
471
+ #if MAC_XCD
472
+ #pragma unused(theEnv)
473
+ #endif
474
+
475
+ return theFact->garbage;
476
+ }
477
+
478
+ /**************************************************/
479
+ /* PrintFact: Displays the printed representation */
480
+ /* of a fact containing the relation name and */
481
+ /* all of the fact's slots or fields. */
482
+ /**************************************************/
483
+ void PrintFact(
484
+ Environment *theEnv,
485
+ const char *logicalName,
486
+ Fact *factPtr,
487
+ bool separateLines,
488
+ bool ignoreDefaults,
489
+ const char *changeMap)
490
+ {
491
+ Multifield *theMultifield;
492
+
493
+ /*=========================================*/
494
+ /* Print a deftemplate (non-ordered) fact. */
495
+ /*=========================================*/
496
+
497
+ if (factPtr->whichDeftemplate->implied == false)
498
+ {
499
+ PrintTemplateFact(theEnv,logicalName,factPtr,separateLines,ignoreDefaults,changeMap);
500
+ return;
501
+ }
502
+
503
+ /*==============================*/
504
+ /* Print an ordered fact (which */
505
+ /* has an implied deftemplate). */
506
+ /*==============================*/
507
+
508
+ WriteString(theEnv,logicalName,"(");
509
+
510
+ WriteString(theEnv,logicalName,factPtr->whichDeftemplate->header.name->contents);
511
+
512
+ theMultifield = factPtr->theProposition.contents[0].multifieldValue;
513
+ if (theMultifield->length != 0)
514
+ {
515
+ WriteString(theEnv,logicalName," ");
516
+ PrintMultifieldDriver(theEnv,logicalName,theMultifield,0,
517
+ theMultifield->length,false);
518
+ }
519
+
520
+ WriteString(theEnv,logicalName,")");
521
+ }
522
+
523
+ /*********************************************/
524
+ /* MatchFactFunction: Filters a fact through */
525
+ /* the appropriate fact pattern network. */
526
+ /*********************************************/
527
+ void MatchFactFunction(
528
+ Environment *theEnv,
529
+ Fact *theFact)
530
+ {
531
+ FactPatternMatch(theEnv,theFact,theFact->whichDeftemplate->patternNetwork,0,0,NULL,NULL);
532
+ }
533
+
534
+ /**********************************************/
535
+ /* RetractDriver: Driver routine for Retract. */
536
+ /**********************************************/
537
+ RetractError RetractDriver(
538
+ Environment *theEnv,
539
+ Fact *theFact,
540
+ bool modifyOperation,
541
+ char *changeMap)
542
+ {
543
+ Deftemplate *theTemplate = theFact->whichDeftemplate;
544
+ struct callFunctionItemWithArg *theRetractFunction;
545
+
546
+ FactData(theEnv)->retractError = RE_NO_ERROR;
547
+
548
+ /*===========================================*/
549
+ /* Retracting a retracted fact does nothing. */
550
+ /*===========================================*/
551
+
552
+ if (theFact->garbage)
553
+ { return RE_NO_ERROR; }
554
+
555
+ /*===========================================*/
556
+ /* A fact can not be retracted while another */
557
+ /* fact is being asserted or retracted. */
558
+ /*===========================================*/
559
+
560
+ if (EngineData(theEnv)->JoinOperationInProgress)
561
+ {
562
+ PrintErrorID(theEnv,"FACTMNGR",1,true);
563
+ WriteString(theEnv,STDERR,"Facts may not be retracted during pattern-matching.\n");
564
+ SetEvaluationError(theEnv,true);
565
+ FactData(theEnv)->retractError = RE_COULD_NOT_RETRACT_ERROR;
566
+ return RE_COULD_NOT_RETRACT_ERROR;
567
+ }
568
+
569
+ /*====================================*/
570
+ /* A NULL fact pointer indicates that */
571
+ /* all facts should be retracted. */
572
+ /*====================================*/
573
+
574
+ if (theFact == NULL)
575
+ { return RetractAllFacts(theEnv); }
576
+
577
+ /*=================================================*/
578
+ /* Check to see if the fact has not been asserted. */
579
+ /*=================================================*/
580
+
581
+ if (theFact->factIndex == 0)
582
+ {
583
+ SystemError(theEnv,"FACTMNGR",5);
584
+ ExitRouter(theEnv,EXIT_FAILURE);
585
+ }
586
+
587
+ /*===========================================*/
588
+ /* Execute the list of functions that are */
589
+ /* to be called before each fact retraction. */
590
+ /*===========================================*/
591
+
592
+ for (theRetractFunction = FactData(theEnv)->ListOfRetractFunctions;
593
+ theRetractFunction != NULL;
594
+ theRetractFunction = theRetractFunction->next)
595
+ {
596
+ (*theRetractFunction->func)(theEnv,theFact,theRetractFunction->context);
597
+ }
598
+
599
+ /*============================*/
600
+ /* Print retraction output if */
601
+ /* facts are being watched. */
602
+ /*============================*/
603
+
604
+ #if DEBUGGING_FUNCTIONS
605
+ if (theFact->whichDeftemplate->watch &&
606
+ (! ConstructData(theEnv)->ClearReadyInProgress) &&
607
+ (! ConstructData(theEnv)->ClearInProgress))
608
+ {
609
+ WriteString(theEnv,STDOUT,"<== ");
610
+ PrintFactWithIdentifier(theEnv,STDOUT,theFact,changeMap);
611
+ WriteString(theEnv,STDOUT,"\n");
612
+ }
613
+ #endif
614
+
615
+ /*==================================*/
616
+ /* Set the change flag to indicate */
617
+ /* the fact-list has been modified. */
618
+ /*==================================*/
619
+
620
+ FactData(theEnv)->ChangeToFactList = true;
621
+
622
+ /*===============================================*/
623
+ /* Remove any links between the fact and partial */
624
+ /* matches in the join network. These links are */
625
+ /* used to keep track of logical dependencies. */
626
+ /*===============================================*/
627
+
628
+ RemoveEntityDependencies(theEnv,(struct patternEntity *) theFact);
629
+
630
+ /*===========================================*/
631
+ /* Remove the fact from the fact hash table. */
632
+ /*===========================================*/
633
+
634
+ RemoveHashedFact(theEnv,theFact);
635
+
636
+ /*=========================================*/
637
+ /* Remove the fact from its template list. */
638
+ /*=========================================*/
639
+
640
+ if (theFact == theTemplate->lastFact)
641
+ { theTemplate->lastFact = theFact->previousTemplateFact; }
642
+
643
+ if (theFact->previousTemplateFact == NULL)
644
+ {
645
+ theTemplate->factList = theTemplate->factList->nextTemplateFact;
646
+ if (theTemplate->factList != NULL)
647
+ { theTemplate->factList->previousTemplateFact = NULL; }
648
+ }
649
+ else
650
+ {
651
+ theFact->previousTemplateFact->nextTemplateFact = theFact->nextTemplateFact;
652
+ if (theFact->nextTemplateFact != NULL)
653
+ { theFact->nextTemplateFact->previousTemplateFact = theFact->previousTemplateFact; }
654
+ }
655
+
656
+ /*=====================================*/
657
+ /* Remove the fact from the fact list. */
658
+ /*=====================================*/
659
+
660
+ if (theFact == FactData(theEnv)->LastFact)
661
+ { FactData(theEnv)->LastFact = theFact->previousFact; }
662
+
663
+ if (theFact->previousFact == NULL)
664
+ {
665
+ FactData(theEnv)->FactList = FactData(theEnv)->FactList->nextFact;
666
+ if (FactData(theEnv)->FactList != NULL)
667
+ { FactData(theEnv)->FactList->previousFact = NULL; }
668
+ }
669
+ else
670
+ {
671
+ theFact->previousFact->nextFact = theFact->nextFact;
672
+ if (theFact->nextFact != NULL)
673
+ { theFact->nextFact->previousFact = theFact->previousFact; }
674
+ }
675
+
676
+ /*===================================================*/
677
+ /* Add the fact to the fact garbage list unless this */
678
+ /* fact is being retract as part of a modify action. */
679
+ /*===================================================*/
680
+
681
+ if (! modifyOperation)
682
+ {
683
+ theFact->nextFact = FactData(theEnv)->GarbageFacts;
684
+ FactData(theEnv)->GarbageFacts = theFact;
685
+ UtilityData(theEnv)->CurrentGarbageFrame->dirty = true;
686
+ }
687
+ else
688
+ {
689
+ theFact->nextFact = NULL;
690
+ }
691
+ theFact->garbage = true;
692
+
693
+ /*===================================================*/
694
+ /* Reset the evaluation error flag since expressions */
695
+ /* will be evaluated as part of the retract. */
696
+ /*===================================================*/
697
+
698
+ SetEvaluationError(theEnv,false);
699
+
700
+ /*===========================================*/
701
+ /* Loop through the list of all the patterns */
702
+ /* that matched the fact and process the */
703
+ /* retract operation for each one. */
704
+ /*===========================================*/
705
+
706
+ EngineData(theEnv)->JoinOperationInProgress = true;
707
+ NetworkRetract(theEnv,(struct patternMatch *) theFact->list);
708
+ theFact->list = NULL;
709
+ EngineData(theEnv)->JoinOperationInProgress = false;
710
+
711
+ /*=========================================*/
712
+ /* Free partial matches that were released */
713
+ /* by the retraction of the fact. */
714
+ /*=========================================*/
715
+
716
+ if (EngineData(theEnv)->ExecutingRule == NULL)
717
+ { FlushGarbagePartialMatches(theEnv); }
718
+
719
+ /*=========================================*/
720
+ /* Retract other facts that were logically */
721
+ /* dependent on the fact just retracted. */
722
+ /*=========================================*/
723
+
724
+ ForceLogicalRetractions(theEnv);
725
+
726
+ /*==================================*/
727
+ /* Update busy counts and ephemeral */
728
+ /* garbage information. */
729
+ /*==================================*/
730
+
731
+ FactDeinstall(theEnv,theFact);
732
+
733
+ /*====================================*/
734
+ /* Return the appropriate error code. */
735
+ /*====================================*/
736
+
737
+ if (GetEvaluationError(theEnv))
738
+ {
739
+ FactData(theEnv)->retractError = RE_RULE_NETWORK_ERROR;
740
+ return RE_RULE_NETWORK_ERROR;
741
+ }
742
+
743
+ FactData(theEnv)->retractError = RE_NO_ERROR;
744
+ return RE_NO_ERROR;
745
+ }
746
+
747
+ /*******************/
748
+ /* RetractCallback */
749
+ /*******************/
750
+ static bool RetractCallback(
751
+ Fact *theFact,
752
+ Environment *theEnv)
753
+ {
754
+ return (RetractDriver(theEnv,theFact,false,NULL) == RE_NO_ERROR);
755
+ }
756
+
757
+ /******************************************************/
758
+ /* Retract: C access routine for the retract command. */
759
+ /******************************************************/
760
+ RetractError Retract(
761
+ Fact *theFact)
762
+ {
763
+ GCBlock gcb;
764
+ RetractError rv;
765
+ Environment *theEnv;
766
+
767
+ if (theFact == NULL)
768
+ { return RE_NULL_POINTER_ERROR; }
769
+
770
+ if (theFact->garbage)
771
+ { return RE_NO_ERROR; }
772
+
773
+ theEnv = theFact->whichDeftemplate->header.env;
774
+
775
+ /*=====================================*/
776
+ /* If embedded, clear the error flags. */
777
+ /*=====================================*/
778
+
779
+ if (EvaluationData(theEnv)->CurrentExpression == NULL)
780
+ { ResetErrorFlags(theEnv); }
781
+
782
+ GCBlockStart(theEnv,&gcb);
783
+ rv = RetractDriver(theEnv,theFact,false,NULL);
784
+ GCBlockEnd(theEnv,&gcb);
785
+
786
+ return rv;
787
+ }
788
+
789
+ /*******************************************************************/
790
+ /* RemoveGarbageFacts: Returns facts that have been retracted to */
791
+ /* the pool of available memory. It is necessary to postpone */
792
+ /* returning the facts to memory because RHS actions retrieve */
793
+ /* their variable bindings directly from the fact data structure */
794
+ /* and the facts may be in use in other data structures. */
795
+ /*******************************************************************/
796
+ static void RemoveGarbageFacts(
797
+ Environment *theEnv,
798
+ void *context)
799
+ {
800
+ Fact *factPtr, *nextPtr, *lastPtr = NULL;
801
+
802
+ factPtr = FactData(theEnv)->GarbageFacts;
803
+
804
+ while (factPtr != NULL)
805
+ {
806
+ nextPtr = factPtr->nextFact;
807
+
808
+ if (factPtr->patternHeader.busyCount == 0)
809
+ {
810
+ Multifield *theSegment;
811
+ size_t i;
812
+
813
+ theSegment = &factPtr->theProposition;
814
+ for (i = 0 ; i < theSegment->length ; i++)
815
+ { AtomDeinstall(theEnv,theSegment->contents[i].header->type,theSegment->contents[i].value); }
816
+
817
+ ReturnFact(theEnv,factPtr);
818
+ if (lastPtr == NULL) FactData(theEnv)->GarbageFacts = nextPtr;
819
+ else lastPtr->nextFact = nextPtr;
820
+ }
821
+ else
822
+ { lastPtr = factPtr; }
823
+
824
+ factPtr = nextPtr;
825
+ }
826
+ }
827
+
828
+ /********************************************************/
829
+ /* AssertDriver: Driver routine for the assert command. */
830
+ /********************************************************/
831
+ Fact *AssertDriver(
832
+ Fact *theFact,
833
+ long long reuseIndex,
834
+ Fact *factListPosition,
835
+ Fact *templatePosition,
836
+ char *changeMap)
837
+ {
838
+ size_t hashValue;
839
+ size_t length, i;
840
+ CLIPSValue *theField;
841
+ Fact *duplicate;
842
+ struct callFunctionItemWithArg *theAssertFunction;
843
+ Environment *theEnv = theFact->whichDeftemplate->header.env;
844
+
845
+ FactData(theEnv)->assertError = AE_NO_ERROR;
846
+
847
+ /*==================================================*/
848
+ /* Retracted and existing facts cannot be asserted. */
849
+ /*==================================================*/
850
+
851
+ if (theFact->garbage)
852
+ {
853
+ FactData(theEnv)->assertError = AE_RETRACTED_ERROR;
854
+ return NULL;
855
+ }
856
+
857
+ if (reuseIndex != theFact->factIndex)
858
+ {
859
+ SystemError(theEnv,"FACTMNGR",6);
860
+ ExitRouter(theEnv,EXIT_FAILURE);
861
+ }
862
+
863
+ /*==========================================*/
864
+ /* A fact can not be asserted while another */
865
+ /* fact is being asserted or retracted. */
866
+ /*==========================================*/
867
+
868
+ if (EngineData(theEnv)->JoinOperationInProgress)
869
+ {
870
+ FactData(theEnv)->assertError = AE_COULD_NOT_ASSERT_ERROR;
871
+ ReturnFact(theEnv,theFact);
872
+ PrintErrorID(theEnv,"FACTMNGR",2,true);
873
+ WriteString(theEnv,STDERR,"Facts may not be asserted during pattern-matching.\n");
874
+ return NULL;
875
+ }
876
+
877
+ /*=============================================================*/
878
+ /* Replace invalid data types in the fact with the symbol nil. */
879
+ /*=============================================================*/
880
+
881
+ length = theFact->theProposition.length;
882
+ theField = theFact->theProposition.contents;
883
+
884
+ for (i = 0; i < length; i++)
885
+ {
886
+ if (theField[i].value == VoidConstant(theEnv))
887
+ { theField[i].value = CreateSymbol(theEnv,"nil"); }
888
+ }
889
+
890
+ /*========================================================*/
891
+ /* If fact assertions are being checked for duplications, */
892
+ /* then search the fact list for a duplicate fact. */
893
+ /*========================================================*/
894
+
895
+ hashValue = HandleFactDuplication(theEnv,theFact,&duplicate,reuseIndex);
896
+ if (duplicate != NULL) return duplicate;
897
+
898
+ /*==========================================================*/
899
+ /* If necessary, add logical dependency links between the */
900
+ /* fact and the partial match which is its logical support. */
901
+ /*==========================================================*/
902
+
903
+ if (AddLogicalDependencies(theEnv,(struct patternEntity *) theFact,false) == false)
904
+ {
905
+ if (reuseIndex == 0)
906
+ { ReturnFact(theEnv,theFact); }
907
+ else
908
+ {
909
+ theFact->nextFact = FactData(theEnv)->GarbageFacts;
910
+ FactData(theEnv)->GarbageFacts = theFact;
911
+ UtilityData(theEnv)->CurrentGarbageFrame->dirty = true;
912
+ theFact->garbage = true;
913
+ }
914
+
915
+ FactData(theEnv)->assertError = AE_COULD_NOT_ASSERT_ERROR;
916
+ return NULL;
917
+ }
918
+
919
+ /*======================================*/
920
+ /* Add the fact to the fact hash table. */
921
+ /*======================================*/
922
+
923
+ AddHashedFact(theEnv,theFact,hashValue);
924
+
925
+ /*================================*/
926
+ /* Add the fact to the fact list. */
927
+ /*================================*/
928
+
929
+ if (reuseIndex == 0)
930
+ { factListPosition = FactData(theEnv)->LastFact; }
931
+
932
+ if (factListPosition == NULL)
933
+ {
934
+ theFact->nextFact = FactData(theEnv)->FactList;
935
+ FactData(theEnv)->FactList = theFact;
936
+ theFact->previousFact = NULL;
937
+ if (theFact->nextFact != NULL)
938
+ { theFact->nextFact->previousFact = theFact; }
939
+ }
940
+ else
941
+ {
942
+ theFact->nextFact = factListPosition->nextFact;
943
+ theFact->previousFact = factListPosition;
944
+ factListPosition->nextFact = theFact;
945
+ if (theFact->nextFact != NULL)
946
+ { theFact->nextFact->previousFact = theFact; }
947
+ }
948
+
949
+ if ((FactData(theEnv)->LastFact == NULL) || (theFact->nextFact == NULL))
950
+ { FactData(theEnv)->LastFact = theFact; }
951
+
952
+ /*====================================*/
953
+ /* Add the fact to its template list. */
954
+ /*====================================*/
955
+
956
+ if (reuseIndex == 0)
957
+ { templatePosition = theFact->whichDeftemplate->lastFact; }
958
+
959
+ if (templatePosition == NULL)
960
+ {
961
+ theFact->nextTemplateFact = theFact->whichDeftemplate->factList;
962
+ theFact->whichDeftemplate->factList = theFact;
963
+ theFact->previousTemplateFact = NULL;
964
+ if (theFact->nextTemplateFact != NULL)
965
+ { theFact->nextTemplateFact->previousTemplateFact = theFact; }
966
+ }
967
+ else
968
+ {
969
+ theFact->nextTemplateFact = templatePosition->nextTemplateFact;
970
+ theFact->previousTemplateFact = templatePosition;
971
+ templatePosition->nextTemplateFact = theFact;
972
+ if (theFact->nextTemplateFact != NULL)
973
+ { theFact->nextTemplateFact->previousTemplateFact = theFact; }
974
+ }
975
+
976
+ if ((theFact->whichDeftemplate->lastFact == NULL) || (theFact->nextTemplateFact == NULL))
977
+ { theFact->whichDeftemplate->lastFact = theFact; }
978
+
979
+ /*==================================*/
980
+ /* Set the fact index and time tag. */
981
+ /*==================================*/
982
+
983
+ if (reuseIndex > 0)
984
+ { theFact->factIndex = reuseIndex; }
985
+ else
986
+ { theFact->factIndex = FactData(theEnv)->NextFactIndex++; }
987
+
988
+ theFact->patternHeader.timeTag = DefruleData(theEnv)->CurrentEntityTimeTag++;
989
+
990
+ /*=====================*/
991
+ /* Update busy counts. */
992
+ /*=====================*/
993
+
994
+ FactInstall(theEnv,theFact);
995
+
996
+ if (reuseIndex == 0)
997
+ {
998
+ Multifield *theSegment = &theFact->theProposition;
999
+ for (i = 0 ; i < theSegment->length ; i++)
1000
+ {
1001
+ AtomInstall(theEnv,theSegment->contents[i].header->type,theSegment->contents[i].value);
1002
+ }
1003
+ }
1004
+
1005
+ /*==========================================*/
1006
+ /* Execute the list of functions that are */
1007
+ /* to be called before each fact assertion. */
1008
+ /*==========================================*/
1009
+
1010
+ for (theAssertFunction = FactData(theEnv)->ListOfAssertFunctions;
1011
+ theAssertFunction != NULL;
1012
+ theAssertFunction = theAssertFunction->next)
1013
+ { (*theAssertFunction->func)(theEnv,theFact,theAssertFunction->context); }
1014
+
1015
+ /*==========================*/
1016
+ /* Print assert output if */
1017
+ /* facts are being watched. */
1018
+ /*==========================*/
1019
+
1020
+ #if DEBUGGING_FUNCTIONS
1021
+ if (theFact->whichDeftemplate->watch &&
1022
+ (! ConstructData(theEnv)->ClearReadyInProgress) &&
1023
+ (! ConstructData(theEnv)->ClearInProgress))
1024
+ {
1025
+ WriteString(theEnv,STDOUT,"==> ");
1026
+ PrintFactWithIdentifier(theEnv,STDOUT,theFact,changeMap);
1027
+ WriteString(theEnv,STDOUT,"\n");
1028
+ }
1029
+ #endif
1030
+
1031
+ /*==================================*/
1032
+ /* Set the change flag to indicate */
1033
+ /* the fact-list has been modified. */
1034
+ /*==================================*/
1035
+
1036
+ FactData(theEnv)->ChangeToFactList = true;
1037
+
1038
+ /*==========================================*/
1039
+ /* Check for constraint errors in the fact. */
1040
+ /*==========================================*/
1041
+
1042
+ CheckTemplateFact(theEnv,theFact);
1043
+
1044
+ /*===================================================*/
1045
+ /* Reset the evaluation error flag since expressions */
1046
+ /* will be evaluated as part of the assert . */
1047
+ /*===================================================*/
1048
+
1049
+ SetEvaluationError(theEnv,false);
1050
+
1051
+ /*=============================================*/
1052
+ /* Pattern match the fact using the associated */
1053
+ /* deftemplate's pattern network. */
1054
+ /*=============================================*/
1055
+
1056
+ EngineData(theEnv)->JoinOperationInProgress = true;
1057
+ FactPatternMatch(theEnv,theFact,theFact->whichDeftemplate->patternNetwork,0,0,NULL,NULL);
1058
+ EngineData(theEnv)->JoinOperationInProgress = false;
1059
+
1060
+ /*===================================================*/
1061
+ /* Retract other facts that were logically dependent */
1062
+ /* on the non-existence of the fact just asserted. */
1063
+ /*===================================================*/
1064
+
1065
+ ForceLogicalRetractions(theEnv);
1066
+
1067
+ /*=========================================*/
1068
+ /* Free partial matches that were released */
1069
+ /* by the assertion of the fact. */
1070
+ /*=========================================*/
1071
+
1072
+ if (EngineData(theEnv)->ExecutingRule == NULL) FlushGarbagePartialMatches(theEnv);
1073
+
1074
+ /*===============================*/
1075
+ /* Return a pointer to the fact. */
1076
+ /*===============================*/
1077
+
1078
+ if (EvaluationData(theEnv)->EvaluationError)
1079
+ { FactData(theEnv)->assertError = AE_RULE_NETWORK_ERROR; }
1080
+
1081
+ return theFact;
1082
+ }
1083
+
1084
+ /*****************************************************/
1085
+ /* Assert: C access routine for the assert function. */
1086
+ /*****************************************************/
1087
+ Fact *Assert(
1088
+ Fact *theFact)
1089
+ {
1090
+ return AssertDriver(theFact,0,NULL,NULL,NULL);
1091
+ }
1092
+
1093
+ /*************************/
1094
+ /* GetAssertStringError: */
1095
+ /*************************/
1096
+ AssertStringError GetAssertStringError(
1097
+ Environment *theEnv)
1098
+ {
1099
+ return FactData(theEnv)->assertStringError;
1100
+ }
1101
+
1102
+ /**************************************/
1103
+ /* RetractAllFacts: Loops through the */
1104
+ /* fact-list and removes each fact. */
1105
+ /**************************************/
1106
+ RetractError RetractAllFacts(
1107
+ Environment *theEnv)
1108
+ {
1109
+ RetractError rv;
1110
+
1111
+ while (FactData(theEnv)->FactList != NULL)
1112
+ {
1113
+ if ((rv = Retract(FactData(theEnv)->FactList)) != RE_NO_ERROR)
1114
+ { return rv; }
1115
+ }
1116
+
1117
+ return RE_NO_ERROR;
1118
+ }
1119
+
1120
+ /*********************************************/
1121
+ /* CreateFact: Creates a fact data structure */
1122
+ /* of the specified deftemplate. */
1123
+ /*********************************************/
1124
+ Fact *CreateFact(
1125
+ Deftemplate *theDeftemplate)
1126
+ {
1127
+ Fact *newFact;
1128
+ unsigned short i;
1129
+ Environment *theEnv = theDeftemplate->header.env;
1130
+
1131
+ /*=================================*/
1132
+ /* A deftemplate must be specified */
1133
+ /* in order to create a fact. */
1134
+ /*=================================*/
1135
+
1136
+ if (theDeftemplate == NULL) return NULL;
1137
+
1138
+ /*============================================*/
1139
+ /* Create a fact for an explicit deftemplate. */
1140
+ /*============================================*/
1141
+
1142
+ if (theDeftemplate->implied == false)
1143
+ {
1144
+ newFact = CreateFactBySize(theEnv,theDeftemplate->numberOfSlots);
1145
+ for (i = 0;
1146
+ i < theDeftemplate->numberOfSlots;
1147
+ i++)
1148
+ { newFact->theProposition.contents[i].voidValue = VoidConstant(theEnv); }
1149
+ }
1150
+
1151
+ /*===========================================*/
1152
+ /* Create a fact for an implied deftemplate. */
1153
+ /*===========================================*/
1154
+
1155
+ else
1156
+ {
1157
+ newFact = CreateFactBySize(theEnv,1);
1158
+ newFact->theProposition.contents[0].value = CreateUnmanagedMultifield(theEnv,0L);
1159
+ }
1160
+
1161
+ /*===============================*/
1162
+ /* Return a pointer to the fact. */
1163
+ /*===============================*/
1164
+
1165
+ newFact->whichDeftemplate = theDeftemplate;
1166
+
1167
+ return newFact;
1168
+ }
1169
+
1170
+ /****************************************/
1171
+ /* GetFactSlot: Returns the slot value */
1172
+ /* from the specified slot of a fact. */
1173
+ /****************************************/
1174
+ GetSlotError GetFactSlot(
1175
+ Fact *theFact,
1176
+ const char *slotName,
1177
+ CLIPSValue *theValue)
1178
+ {
1179
+ Deftemplate *theDeftemplate;
1180
+ unsigned short whichSlot;
1181
+ Environment *theEnv = theFact->whichDeftemplate->header.env;
1182
+
1183
+ if (theFact == NULL)
1184
+ {
1185
+ return GSE_NULL_POINTER_ERROR;
1186
+ }
1187
+
1188
+ if (theFact->garbage)
1189
+ {
1190
+ theValue->lexemeValue = FalseSymbol(theEnv);
1191
+ return GSE_INVALID_TARGET_ERROR;
1192
+ }
1193
+
1194
+ /*===============================================*/
1195
+ /* Get the deftemplate associated with the fact. */
1196
+ /*===============================================*/
1197
+
1198
+ theDeftemplate = theFact->whichDeftemplate;
1199
+
1200
+ /*==============================================*/
1201
+ /* Handle retrieving the slot value from a fact */
1202
+ /* having an implied deftemplate. An implied */
1203
+ /* facts has a single multifield slot. */
1204
+ /*==============================================*/
1205
+
1206
+ if (theDeftemplate->implied)
1207
+ {
1208
+ if (slotName != NULL)
1209
+ {
1210
+ if (strcmp(slotName,"implied") != 0)
1211
+ { return GSE_SLOT_NOT_FOUND_ERROR; }
1212
+ }
1213
+
1214
+ theValue->value = theFact->theProposition.contents[0].value;
1215
+ return GSE_NO_ERROR;
1216
+ }
1217
+
1218
+ /*===================================*/
1219
+ /* Make sure the slot name requested */
1220
+ /* corresponds to a valid slot name. */
1221
+ /*===================================*/
1222
+
1223
+ if (slotName == NULL) return GSE_NULL_POINTER_ERROR;
1224
+ if (FindSlot(theDeftemplate,CreateSymbol(theEnv,slotName),&whichSlot) == NULL)
1225
+ { return GSE_SLOT_NOT_FOUND_ERROR; }
1226
+
1227
+ /*========================*/
1228
+ /* Return the slot value. */
1229
+ /*========================*/
1230
+
1231
+ theValue->value = theFact->theProposition.contents[whichSlot].value;
1232
+
1233
+ return GSE_NO_ERROR;
1234
+ }
1235
+
1236
+ /**************************************/
1237
+ /* PutFactSlot: Sets the slot value */
1238
+ /* of the specified slot of a fact. */
1239
+ /**************************************/
1240
+ bool PutFactSlot(
1241
+ Fact *theFact,
1242
+ const char *slotName,
1243
+ CLIPSValue *theValue)
1244
+ {
1245
+ Deftemplate *theDeftemplate;
1246
+ struct templateSlot *theSlot;
1247
+ unsigned short whichSlot;
1248
+ Environment *theEnv = theFact->whichDeftemplate->header.env;
1249
+
1250
+ /*========================================*/
1251
+ /* This function cannot be used on a fact */
1252
+ /* that's already been asserted. */
1253
+ /*========================================*/
1254
+
1255
+ if (theFact->factIndex != 0LL)
1256
+ { return false; }
1257
+
1258
+ /*===============================================*/
1259
+ /* Get the deftemplate associated with the fact. */
1260
+ /*===============================================*/
1261
+
1262
+ theDeftemplate = theFact->whichDeftemplate;
1263
+
1264
+ /*============================================*/
1265
+ /* Handle setting the slot value of a fact */
1266
+ /* having an implied deftemplate. An implied */
1267
+ /* facts has a single multifield slot. */
1268
+ /*============================================*/
1269
+
1270
+ if (theDeftemplate->implied)
1271
+ {
1272
+ if ((slotName != NULL) || (theValue->header->type != MULTIFIELD_TYPE))
1273
+ { return false; }
1274
+
1275
+ if (theFact->theProposition.contents[0].header->type == MULTIFIELD_TYPE)
1276
+ { ReturnMultifield(theEnv,theFact->theProposition.contents[0].multifieldValue); }
1277
+
1278
+ theFact->theProposition.contents[0].value = CopyMultifield(theEnv,theValue->multifieldValue);
1279
+
1280
+ return true;
1281
+ }
1282
+
1283
+ /*===================================*/
1284
+ /* Make sure the slot name requested */
1285
+ /* corresponds to a valid slot name. */
1286
+ /*===================================*/
1287
+
1288
+ if ((theSlot = FindSlot(theDeftemplate,CreateSymbol(theEnv,slotName),&whichSlot)) == NULL)
1289
+ { return false; }
1290
+
1291
+ /*=============================================*/
1292
+ /* Make sure a single field value is not being */
1293
+ /* stored in a multifield slot or vice versa. */
1294
+ /*=============================================*/
1295
+
1296
+ if (((theSlot->multislot == 0) && (theValue->header->type == MULTIFIELD_TYPE)) ||
1297
+ ((theSlot->multislot == 1) && (theValue->header->type != MULTIFIELD_TYPE)))
1298
+ { return false; }
1299
+
1300
+ /*=================================*/
1301
+ /* Check constraints for the slot. */
1302
+ /*=================================*/
1303
+
1304
+ if (theSlot->constraints != NULL)
1305
+ {
1306
+ if (ConstraintCheckValue(theEnv,theValue->header->type,theValue->value,theSlot->constraints) != NO_VIOLATION)
1307
+ { return false; }
1308
+ }
1309
+
1310
+ /*=====================*/
1311
+ /* Set the slot value. */
1312
+ /*=====================*/
1313
+
1314
+ if (theFact->theProposition.contents[whichSlot].header->type == MULTIFIELD_TYPE)
1315
+ { ReturnMultifield(theEnv,theFact->theProposition.contents[whichSlot].multifieldValue); }
1316
+
1317
+ if (theValue->header->type == MULTIFIELD_TYPE)
1318
+ { theFact->theProposition.contents[whichSlot].multifieldValue = CopyMultifield(theEnv,theValue->multifieldValue); }
1319
+ else
1320
+ { theFact->theProposition.contents[whichSlot].value = theValue->value; }
1321
+
1322
+ return true;
1323
+ }
1324
+
1325
+ /*******************************************************/
1326
+ /* AssignFactSlotDefaults: Sets a fact's slot values */
1327
+ /* to its default value if the value of the slot has */
1328
+ /* not yet been set. */
1329
+ /*******************************************************/
1330
+ bool AssignFactSlotDefaults(
1331
+ Fact *theFact)
1332
+ {
1333
+ Deftemplate *theDeftemplate;
1334
+ struct templateSlot *slotPtr;
1335
+ unsigned short i;
1336
+ UDFValue theResult;
1337
+ Environment *theEnv = theFact->whichDeftemplate->header.env;
1338
+
1339
+ /*========================================*/
1340
+ /* This function cannot be used on a fact */
1341
+ /* that's already been asserted. */
1342
+ /*========================================*/
1343
+
1344
+ if (theFact->factIndex != 0LL)
1345
+ { return false; }
1346
+
1347
+ /*===============================================*/
1348
+ /* Get the deftemplate associated with the fact. */
1349
+ /*===============================================*/
1350
+
1351
+ theDeftemplate = theFact->whichDeftemplate;
1352
+
1353
+ /*================================================*/
1354
+ /* The value for the implied multifield slot of */
1355
+ /* an implied deftemplate is set to a multifield */
1356
+ /* of length zero when the fact is created. */
1357
+ /*================================================*/
1358
+
1359
+ if (theDeftemplate->implied) return true;
1360
+
1361
+ /*============================================*/
1362
+ /* Loop through each slot of the deftemplate. */
1363
+ /*============================================*/
1364
+
1365
+ for (i = 0, slotPtr = theDeftemplate->slotList;
1366
+ i < theDeftemplate->numberOfSlots;
1367
+ i++, slotPtr = slotPtr->next)
1368
+ {
1369
+ /*===================================*/
1370
+ /* If the slot's value has been set, */
1371
+ /* then move on to the next slot. */
1372
+ /*===================================*/
1373
+
1374
+ if (theFact->theProposition.contents[i].value != VoidConstant(theEnv)) continue;
1375
+
1376
+ /*======================================================*/
1377
+ /* Assign the default value for the slot if one exists. */
1378
+ /*======================================================*/
1379
+
1380
+ if (DeftemplateSlotDefault(theEnv,theDeftemplate,slotPtr,&theResult,false))
1381
+ {
1382
+ theFact->theProposition.contents[i].value = theResult.value;
1383
+ }
1384
+ }
1385
+
1386
+ /*==========================================*/
1387
+ /* Return true to indicate that the default */
1388
+ /* values have been successfully set. */
1389
+ /*==========================================*/
1390
+
1391
+ return true;
1392
+ }
1393
+
1394
+ /********************************************************/
1395
+ /* DeftemplateSlotDefault: Determines the default value */
1396
+ /* for the specified slot of a deftemplate. */
1397
+ /********************************************************/
1398
+ bool DeftemplateSlotDefault(
1399
+ Environment *theEnv,
1400
+ Deftemplate *theDeftemplate,
1401
+ struct templateSlot *slotPtr,
1402
+ UDFValue *theResult,
1403
+ bool garbageMultifield)
1404
+ {
1405
+ /*================================================*/
1406
+ /* The value for the implied multifield slot of an */
1407
+ /* implied deftemplate does not have a default. */
1408
+ /*=================================================*/
1409
+
1410
+ if (theDeftemplate->implied) return false;
1411
+
1412
+ /*===============================================*/
1413
+ /* If the (default ?NONE) attribute was declared */
1414
+ /* for the slot, then return false to indicate */
1415
+ /* the default values for the fact couldn't be */
1416
+ /* supplied since this attribute requires that a */
1417
+ /* default value can't be used for the slot. */
1418
+ /*===============================================*/
1419
+
1420
+ if (slotPtr->noDefault) return false;
1421
+
1422
+ /*==============================================*/
1423
+ /* Otherwise if a static default was specified, */
1424
+ /* use this as the default value. */
1425
+ /*==============================================*/
1426
+
1427
+ else if (slotPtr->defaultPresent)
1428
+ {
1429
+ if (slotPtr->multislot)
1430
+ {
1431
+ StoreInMultifield(theEnv,theResult,slotPtr->defaultList,garbageMultifield);
1432
+ }
1433
+ else
1434
+ {
1435
+ theResult->value = slotPtr->defaultList->value;
1436
+ }
1437
+ }
1438
+
1439
+ /*================================================*/
1440
+ /* Otherwise if a dynamic-default was specified, */
1441
+ /* evaluate it and use this as the default value. */
1442
+ /*================================================*/
1443
+
1444
+ else if (slotPtr->defaultDynamic)
1445
+ {
1446
+ if (! EvaluateAndStoreInDataObject(theEnv,slotPtr->multislot,
1447
+ (Expression *) slotPtr->defaultList,
1448
+ theResult,garbageMultifield))
1449
+ { return false; }
1450
+ }
1451
+
1452
+ /*====================================*/
1453
+ /* Otherwise derive the default value */
1454
+ /* from the slot's constraints. */
1455
+ /*====================================*/
1456
+
1457
+ else
1458
+ {
1459
+ DeriveDefaultFromConstraints(theEnv,slotPtr->constraints,theResult,
1460
+ slotPtr->multislot,garbageMultifield);
1461
+ }
1462
+
1463
+ /*==========================================*/
1464
+ /* Return true to indicate that the default */
1465
+ /* values have been successfully set. */
1466
+ /*==========================================*/
1467
+
1468
+ return true;
1469
+ }
1470
+
1471
+ /***************************************************************/
1472
+ /* CopyFactSlotValues: Copies the slot values from one fact to */
1473
+ /* another. Both facts must have the same relation name. */
1474
+ /***************************************************************/
1475
+ bool CopyFactSlotValues(
1476
+ Environment *theEnv,
1477
+ Fact *theDestFact,
1478
+ Fact *theSourceFact)
1479
+ {
1480
+ Deftemplate *theDeftemplate;
1481
+ struct templateSlot *slotPtr;
1482
+ unsigned short i;
1483
+
1484
+ /*===================================*/
1485
+ /* Both facts must be the same type. */
1486
+ /*===================================*/
1487
+
1488
+ theDeftemplate = theSourceFact->whichDeftemplate;
1489
+ if (theDestFact->whichDeftemplate != theDeftemplate)
1490
+ { return false; }
1491
+
1492
+ /*===================================================*/
1493
+ /* Loop through each slot of the deftemplate copying */
1494
+ /* the source fact value to the destination fact. */
1495
+ /*===================================================*/
1496
+
1497
+ for (i = 0, slotPtr = theDeftemplate->slotList;
1498
+ i < theDeftemplate->numberOfSlots;
1499
+ i++, slotPtr = slotPtr->next)
1500
+ {
1501
+ if (theSourceFact->theProposition.contents[i].header->type != MULTIFIELD_TYPE)
1502
+ {
1503
+ theDestFact->theProposition.contents[i].value =
1504
+ theSourceFact->theProposition.contents[i].value;
1505
+ }
1506
+ else
1507
+ {
1508
+ theDestFact->theProposition.contents[i].value =
1509
+ CopyMultifield(theEnv,theSourceFact->theProposition.contents[i].multifieldValue);
1510
+ }
1511
+ }
1512
+
1513
+ /*========================================*/
1514
+ /* Return true to indicate that fact slot */
1515
+ /* values were successfully copied. */
1516
+ /*========================================*/
1517
+
1518
+ return true;
1519
+ }
1520
+
1521
+ /*********************************************/
1522
+ /* CreateFactBySize: Allocates a fact data */
1523
+ /* structure based on the number of slots. */
1524
+ /*********************************************/
1525
+ Fact *CreateFactBySize(
1526
+ Environment *theEnv,
1527
+ size_t size)
1528
+ {
1529
+ Fact *theFact;
1530
+ size_t newSize;
1531
+
1532
+ if (size <= 0) newSize = 1;
1533
+ else newSize = size;
1534
+
1535
+ theFact = get_var_struct(theEnv,fact,sizeof(struct clipsValue) * (newSize - 1));
1536
+
1537
+ theFact->patternHeader.header.type = FACT_ADDRESS_TYPE;
1538
+ theFact->garbage = false;
1539
+ theFact->factIndex = 0LL;
1540
+ theFact->patternHeader.busyCount = 0;
1541
+ theFact->patternHeader.theInfo = &FactData(theEnv)->FactInfo;
1542
+ theFact->patternHeader.dependents = NULL;
1543
+ theFact->whichDeftemplate = NULL;
1544
+ theFact->nextFact = NULL;
1545
+ theFact->previousFact = NULL;
1546
+ theFact->previousTemplateFact = NULL;
1547
+ theFact->nextTemplateFact = NULL;
1548
+ theFact->list = NULL;
1549
+ theFact->basisSlots = NULL;
1550
+
1551
+ theFact->theProposition.length = size;
1552
+ theFact->theProposition.busyCount = 0;
1553
+
1554
+ return(theFact);
1555
+ }
1556
+
1557
+ /*********************************************/
1558
+ /* ReturnFact: Returns a fact data structure */
1559
+ /* to the pool of free memory. */
1560
+ /*********************************************/
1561
+ void ReturnFact(
1562
+ Environment *theEnv,
1563
+ Fact *theFact)
1564
+ {
1565
+ Multifield *theSegment, *subSegment;
1566
+ size_t newSize, i;
1567
+
1568
+ theSegment = &theFact->theProposition;
1569
+
1570
+ for (i = 0; i < theSegment->length; i++)
1571
+ {
1572
+ if (theSegment->contents[i].header->type == MULTIFIELD_TYPE)
1573
+ {
1574
+ subSegment = theSegment->contents[i].multifieldValue;
1575
+ if (subSegment != NULL)
1576
+ {
1577
+ if (subSegment->busyCount == 0)
1578
+ { ReturnMultifield(theEnv,subSegment); }
1579
+ else
1580
+ { AddToMultifieldList(theEnv,subSegment); }
1581
+ }
1582
+ }
1583
+ }
1584
+
1585
+ if (theFact->theProposition.length == 0) newSize = 1;
1586
+ else newSize = theFact->theProposition.length;
1587
+
1588
+ rtn_var_struct(theEnv,fact,sizeof(struct clipsValue) * (newSize - 1),theFact);
1589
+ }
1590
+
1591
+ /*************************************************************/
1592
+ /* FactInstall: Increments the fact, deftemplate, and atomic */
1593
+ /* data value busy counts associated with the fact. */
1594
+ /*************************************************************/
1595
+ void FactInstall(
1596
+ Environment *theEnv,
1597
+ Fact *newFact)
1598
+ {
1599
+ FactData(theEnv)->NumberOfFacts++;
1600
+ newFact->whichDeftemplate->busyCount++;
1601
+ newFact->patternHeader.busyCount++;
1602
+ }
1603
+
1604
+ /***************************************************************/
1605
+ /* FactDeinstall: Decrements the fact, deftemplate, and atomic */
1606
+ /* data value busy counts associated with the fact. */
1607
+ /***************************************************************/
1608
+ void FactDeinstall(
1609
+ Environment *theEnv,
1610
+ Fact *newFact)
1611
+ {
1612
+ FactData(theEnv)->NumberOfFacts--;
1613
+ newFact->whichDeftemplate->busyCount--;
1614
+ newFact->patternHeader.busyCount--;
1615
+ }
1616
+
1617
+ /***********************************************/
1618
+ /* IncrementFactCallback: Increments the */
1619
+ /* number of references to a specified fact. */
1620
+ /***********************************************/
1621
+ void IncrementFactCallback(
1622
+ Environment *theEnv,
1623
+ Fact *factPtr)
1624
+ {
1625
+ #if MAC_XCD
1626
+ #pragma unused(theEnv)
1627
+ #endif
1628
+ if (factPtr == NULL) return;
1629
+
1630
+ factPtr->patternHeader.busyCount++;
1631
+ }
1632
+
1633
+ /***********************************************/
1634
+ /* DecrementFactCallback: Decrements the */
1635
+ /* number of references to a specified fact. */
1636
+ /***********************************************/
1637
+ void DecrementFactCallback(
1638
+ Environment *theEnv,
1639
+ Fact *factPtr)
1640
+ {
1641
+ #if MAC_XCD
1642
+ #pragma unused(theEnv)
1643
+ #endif
1644
+ if (factPtr == NULL) return;
1645
+
1646
+ factPtr->patternHeader.busyCount--;
1647
+ }
1648
+
1649
+ /****************************************/
1650
+ /* RetainFact: Increments the number of */
1651
+ /* references to a specified fact. */
1652
+ /****************************************/
1653
+ void RetainFact(
1654
+ Fact *factPtr)
1655
+ {
1656
+ if (factPtr == NULL) return;
1657
+
1658
+ factPtr->patternHeader.busyCount++;
1659
+ }
1660
+
1661
+ /*****************************************/
1662
+ /* ReleaseFact: Decrements the number of */
1663
+ /* references to a specified fact. */
1664
+ /*****************************************/
1665
+ void ReleaseFact(
1666
+ Fact *factPtr)
1667
+ {
1668
+ if (factPtr == NULL) return;
1669
+
1670
+ factPtr->patternHeader.busyCount--;
1671
+ }
1672
+
1673
+ /*********************************************************/
1674
+ /* GetNextFact: If passed a NULL pointer, returns the */
1675
+ /* first fact in the fact-list. Otherwise returns the */
1676
+ /* next fact following the fact passed as an argument. */
1677
+ /*********************************************************/
1678
+ Fact *GetNextFact(
1679
+ Environment *theEnv,
1680
+ Fact *factPtr)
1681
+ {
1682
+ if (factPtr == NULL)
1683
+ { return FactData(theEnv)->FactList; }
1684
+
1685
+ if (factPtr->garbage) return NULL;
1686
+
1687
+ return factPtr->nextFact;
1688
+ }
1689
+
1690
+ /**************************************************/
1691
+ /* GetNextFactInScope: Returns the next fact that */
1692
+ /* is in scope of the current module. Works in */
1693
+ /* a similar fashion to GetNextFact, but skips */
1694
+ /* facts that are out of scope. */
1695
+ /**************************************************/
1696
+ Fact *GetNextFactInScope(
1697
+ Environment *theEnv,
1698
+ Fact *theFact)
1699
+ {
1700
+ /*=======================================================*/
1701
+ /* If fact passed as an argument is a NULL pointer, then */
1702
+ /* we're just beginning a traversal of the fact list. If */
1703
+ /* the module index has changed since that last time the */
1704
+ /* fact list was traversed by this routine, then */
1705
+ /* determine all of the deftemplates that are in scope */
1706
+ /* of the current module. */
1707
+ /*=======================================================*/
1708
+
1709
+ if (theFact == NULL)
1710
+ {
1711
+ theFact = FactData(theEnv)->FactList;
1712
+ if (FactData(theEnv)->LastModuleIndex != DefmoduleData(theEnv)->ModuleChangeIndex)
1713
+ {
1714
+ UpdateDeftemplateScope(theEnv);
1715
+ FactData(theEnv)->LastModuleIndex = DefmoduleData(theEnv)->ModuleChangeIndex;
1716
+ }
1717
+ }
1718
+
1719
+ /*==================================================*/
1720
+ /* Otherwise, if the fact passed as an argument has */
1721
+ /* been retracted, then there's no way to determine */
1722
+ /* the next fact, so return a NULL pointer. */
1723
+ /*==================================================*/
1724
+
1725
+ else if (theFact->garbage)
1726
+ { return NULL; }
1727
+
1728
+ /*==================================================*/
1729
+ /* Otherwise, start the search for the next fact in */
1730
+ /* scope with the fact immediately following the */
1731
+ /* fact passed as an argument. */
1732
+ /*==================================================*/
1733
+
1734
+ else
1735
+ { theFact = theFact->nextFact; }
1736
+
1737
+ /*================================================*/
1738
+ /* Continue traversing the fact-list until a fact */
1739
+ /* is found that's associated with a deftemplate */
1740
+ /* that's in scope. */
1741
+ /*================================================*/
1742
+
1743
+ while (theFact != NULL)
1744
+ {
1745
+ if (theFact->whichDeftemplate->inScope) return theFact;
1746
+
1747
+ theFact = theFact->nextFact;
1748
+ }
1749
+
1750
+ return NULL;
1751
+ }
1752
+
1753
+ /*************************************/
1754
+ /* FactPPForm: Returns the pretty */
1755
+ /* print representation of a fact. */
1756
+ /*************************************/
1757
+ void FactPPForm(
1758
+ Fact *theFact,
1759
+ StringBuilder *theSB,
1760
+ bool ignoreDefaults)
1761
+ {
1762
+ Environment *theEnv = theFact->whichDeftemplate->header.env;
1763
+
1764
+ OpenStringBuilderDestination(theEnv,"FactPPForm",theSB);
1765
+ PrintFact(theEnv,"FactPPForm",theFact,true,ignoreDefaults,NULL);
1766
+ CloseStringBuilderDestination(theEnv,"FactPPForm");
1767
+ }
1768
+
1769
+ /**********************************/
1770
+ /* FactIndex: C access routine */
1771
+ /* for the fact-index function. */
1772
+ /**********************************/
1773
+ long long FactIndex(
1774
+ Fact *factPtr)
1775
+ {
1776
+ return factPtr->factIndex;
1777
+ }
1778
+
1779
+ /*************************************/
1780
+ /* AssertString: C access routine */
1781
+ /* for the assert-string function. */
1782
+ /*************************************/
1783
+ Fact *AssertString(
1784
+ Environment *theEnv,
1785
+ const char *theString)
1786
+ {
1787
+ Fact *theFact, *rv;
1788
+ GCBlock gcb;
1789
+ int danglingConstructs;
1790
+
1791
+ if (theString == NULL)
1792
+ {
1793
+ FactData(theEnv)->assertStringError = ASE_NULL_POINTER_ERROR;
1794
+ return NULL;
1795
+ }
1796
+
1797
+ danglingConstructs = ConstructData(theEnv)->DanglingConstructs;
1798
+
1799
+ /*=====================================*/
1800
+ /* If embedded, clear the error flags. */
1801
+ /*=====================================*/
1802
+
1803
+ if (EvaluationData(theEnv)->CurrentExpression == NULL)
1804
+ { ResetErrorFlags(theEnv); }
1805
+
1806
+ GCBlockStart(theEnv,&gcb);
1807
+
1808
+ if ((theFact = StringToFact(theEnv,theString)) == NULL)
1809
+ {
1810
+ FactData(theEnv)->assertStringError = ASE_PARSING_ERROR;
1811
+ GCBlockEnd(theEnv,&gcb);
1812
+ return NULL;
1813
+ }
1814
+
1815
+ if (EvaluationData(theEnv)->CurrentExpression == NULL)
1816
+ { ConstructData(theEnv)->DanglingConstructs = danglingConstructs; }
1817
+
1818
+ rv = Assert(theFact);
1819
+
1820
+ GCBlockEnd(theEnv,&gcb);
1821
+
1822
+ switch(FactData(theEnv)->assertError)
1823
+ {
1824
+ case AE_NO_ERROR:
1825
+ FactData(theEnv)->assertStringError = ASE_NO_ERROR;
1826
+ break;
1827
+
1828
+ case AE_COULD_NOT_ASSERT_ERROR:
1829
+ FactData(theEnv)->assertStringError = ASE_COULD_NOT_ASSERT_ERROR;
1830
+ break;
1831
+
1832
+ case AE_RULE_NETWORK_ERROR:
1833
+ FactData(theEnv)->assertStringError = ASE_RULE_NETWORK_ERROR;
1834
+ break;
1835
+
1836
+ case AE_NULL_POINTER_ERROR:
1837
+ case AE_RETRACTED_ERROR:
1838
+ SystemError(theEnv,"FACTMNGR",4);
1839
+ ExitRouter(theEnv,EXIT_FAILURE);
1840
+ break;
1841
+ }
1842
+
1843
+ return rv;
1844
+ }
1845
+
1846
+ /******************************************************/
1847
+ /* GetFactListChanged: Returns the flag indicating */
1848
+ /* whether a change to the fact-list has been made. */
1849
+ /******************************************************/
1850
+ bool GetFactListChanged(
1851
+ Environment *theEnv)
1852
+ {
1853
+ return(FactData(theEnv)->ChangeToFactList);
1854
+ }
1855
+
1856
+ /********************************************************/
1857
+ /* SetFactListChanged: Sets the flag indicating whether */
1858
+ /* a change to the fact-list has been made. */
1859
+ /********************************************************/
1860
+ void SetFactListChanged(
1861
+ Environment *theEnv,
1862
+ bool value)
1863
+ {
1864
+ FactData(theEnv)->ChangeToFactList = value;
1865
+ }
1866
+
1867
+ /****************************************/
1868
+ /* GetNumberOfFacts: Returns the number */
1869
+ /* of facts in the fact-list. */
1870
+ /****************************************/
1871
+ unsigned long GetNumberOfFacts(
1872
+ Environment *theEnv)
1873
+ {
1874
+ return(FactData(theEnv)->NumberOfFacts);
1875
+ }
1876
+
1877
+ /***********************************************************/
1878
+ /* ResetFacts: Reset function for facts. Sets the starting */
1879
+ /* fact index to zero and removes all facts. */
1880
+ /***********************************************************/
1881
+ static void ResetFacts(
1882
+ Environment *theEnv,
1883
+ void *context)
1884
+ {
1885
+ /*====================================*/
1886
+ /* Initialize the fact index to zero. */
1887
+ /*====================================*/
1888
+
1889
+ FactData(theEnv)->NextFactIndex = 1L;
1890
+
1891
+ /*======================================*/
1892
+ /* Remove all facts from the fact list. */
1893
+ /*======================================*/
1894
+
1895
+ RetractAllFacts(theEnv);
1896
+ }
1897
+
1898
+ /************************************************************/
1899
+ /* ClearFactsReady: Clear ready function for facts. Returns */
1900
+ /* true if facts were successfully removed and the clear */
1901
+ /* command can continue, otherwise false. */
1902
+ /************************************************************/
1903
+ static bool ClearFactsReady(
1904
+ Environment *theEnv,
1905
+ void *context)
1906
+ {
1907
+ /*======================================*/
1908
+ /* Facts can not be deleted when a join */
1909
+ /* operation is already in progress. */
1910
+ /*======================================*/
1911
+
1912
+ if (EngineData(theEnv)->JoinOperationInProgress) return false;
1913
+
1914
+ /*====================================*/
1915
+ /* Initialize the fact index to zero. */
1916
+ /*====================================*/
1917
+
1918
+ FactData(theEnv)->NextFactIndex = 1L;
1919
+
1920
+ /*======================================*/
1921
+ /* Remove all facts from the fact list. */
1922
+ /*======================================*/
1923
+
1924
+ RetractAllFacts(theEnv);
1925
+
1926
+ /*==============================================*/
1927
+ /* If for some reason there are any facts still */
1928
+ /* remaining, don't continue with the clear. */
1929
+ /*==============================================*/
1930
+
1931
+ if (GetNextFact(theEnv,NULL) != NULL) return false;
1932
+
1933
+ /*=============================*/
1934
+ /* Return true to indicate the */
1935
+ /* clear command can continue. */
1936
+ /*=============================*/
1937
+
1938
+ return true;
1939
+ }
1940
+
1941
+ /***************************************************/
1942
+ /* FindIndexedFact: Returns a pointer to a fact in */
1943
+ /* the fact list with the specified fact index. */
1944
+ /***************************************************/
1945
+ Fact *FindIndexedFact(
1946
+ Environment *theEnv,
1947
+ long long factIndexSought)
1948
+ {
1949
+ Fact *theFact;
1950
+
1951
+ for (theFact = GetNextFact(theEnv,NULL);
1952
+ theFact != NULL;
1953
+ theFact = GetNextFact(theEnv,theFact))
1954
+ {
1955
+ if (theFact->factIndex == factIndexSought)
1956
+ { return(theFact); }
1957
+ }
1958
+
1959
+ return NULL;
1960
+ }
1961
+
1962
+ /**************************************/
1963
+ /* AddAssertFunction: Adds a function */
1964
+ /* to the ListOfAssertFunctions. */
1965
+ /**************************************/
1966
+ bool AddAssertFunction(
1967
+ Environment *theEnv,
1968
+ const char *name,
1969
+ VoidCallFunctionWithArg *functionPtr,
1970
+ int priority,
1971
+ void *context)
1972
+ {
1973
+ FactData(theEnv)->ListOfAssertFunctions =
1974
+ AddFunctionToCallListWithArg(theEnv,name,priority,functionPtr,
1975
+ FactData(theEnv)->ListOfAssertFunctions,context);
1976
+ return true;
1977
+ }
1978
+
1979
+ /********************************************/
1980
+ /* RemoveAssertFunction: Removes a function */
1981
+ /* from the ListOfAssertFunctions. */
1982
+ /********************************************/
1983
+ bool RemoveAssertFunction(
1984
+ Environment *theEnv,
1985
+ const char *name)
1986
+ {
1987
+ bool found;
1988
+
1989
+ FactData(theEnv)->ListOfAssertFunctions =
1990
+ RemoveFunctionFromCallListWithArg(theEnv,name,FactData(theEnv)->ListOfAssertFunctions,&found);
1991
+
1992
+ if (found) return true;
1993
+
1994
+ return false;
1995
+ }
1996
+
1997
+ /***************************************/
1998
+ /* AddRetractFunction: Adds a function */
1999
+ /* to the ListOfRetractFunctions. */
2000
+ /***************************************/
2001
+ bool AddRetractFunction(
2002
+ Environment *theEnv,
2003
+ const char *name,
2004
+ VoidCallFunctionWithArg *functionPtr,
2005
+ int priority,
2006
+ void *context)
2007
+ {
2008
+ FactData(theEnv)->ListOfRetractFunctions =
2009
+ AddFunctionToCallListWithArg(theEnv,name,priority,functionPtr,
2010
+ FactData(theEnv)->ListOfRetractFunctions,context);
2011
+ return true;
2012
+ }
2013
+
2014
+ /*********************************************/
2015
+ /* RemoveRetractFunction: Removes a function */
2016
+ /* from the ListOfRetractFunctions. */
2017
+ /*********************************************/
2018
+ bool RemoveRetractFunction(
2019
+ Environment *theEnv,
2020
+ const char *name)
2021
+ {
2022
+ bool found;
2023
+
2024
+ FactData(theEnv)->ListOfRetractFunctions =
2025
+ RemoveFunctionFromCallListWithArg(theEnv,name,FactData(theEnv)->ListOfRetractFunctions,&found);
2026
+
2027
+ if (found) return true;
2028
+
2029
+ return false;
2030
+ }
2031
+
2032
+ /**************************************/
2033
+ /* AddModifyFunction: Adds a function */
2034
+ /* to the ListOfModifyFunctions. */
2035
+ /**************************************/
2036
+ bool AddModifyFunction(
2037
+ Environment *theEnv,
2038
+ const char *name,
2039
+ ModifyCallFunction *functionPtr,
2040
+ int priority,
2041
+ void *context)
2042
+ {
2043
+ FactData(theEnv)->ListOfModifyFunctions =
2044
+ AddModifyFunctionToCallList(theEnv,name,priority,functionPtr,
2045
+ FactData(theEnv)->ListOfModifyFunctions,context);
2046
+
2047
+ return true;
2048
+ }
2049
+
2050
+ /********************************************/
2051
+ /* RemoveModifyFunction: Removes a function */
2052
+ /* from the ListOfModifyFunctions. */
2053
+ /********************************************/
2054
+ bool RemoveModifyFunction(
2055
+ Environment *theEnv,
2056
+ const char *name)
2057
+ {
2058
+ bool found;
2059
+
2060
+ FactData(theEnv)->ListOfModifyFunctions =
2061
+ RemoveModifyFunctionFromCallList(theEnv,name,FactData(theEnv)->ListOfModifyFunctions,&found);
2062
+
2063
+ if (found) return true;
2064
+
2065
+ return false;
2066
+ }
2067
+
2068
+ /**********************************************************/
2069
+ /* AddModifyFunctionToCallList: Adds a function to a list */
2070
+ /* of functions which are called to perform certain */
2071
+ /* operations (e.g. clear, reset, and bload functions). */
2072
+ /**********************************************************/
2073
+ ModifyCallFunctionItem *AddModifyFunctionToCallList(
2074
+ Environment *theEnv,
2075
+ const char *name,
2076
+ int priority,
2077
+ ModifyCallFunction *func,
2078
+ ModifyCallFunctionItem *head,
2079
+ void *context)
2080
+ {
2081
+ ModifyCallFunctionItem *newPtr, *currentPtr, *lastPtr = NULL;
2082
+ char *nameCopy;
2083
+
2084
+ newPtr = get_struct(theEnv,modifyCallFunctionItem);
2085
+
2086
+ nameCopy = (char *) genalloc(theEnv,strlen(name) + 1);
2087
+ genstrcpy(nameCopy,name);
2088
+ newPtr->name = nameCopy;
2089
+
2090
+ newPtr->func = func;
2091
+ newPtr->priority = priority;
2092
+ newPtr->context = context;
2093
+
2094
+ if (head == NULL)
2095
+ {
2096
+ newPtr->next = NULL;
2097
+ return(newPtr);
2098
+ }
2099
+
2100
+ currentPtr = head;
2101
+ while ((currentPtr != NULL) ? (priority < currentPtr->priority) : false)
2102
+ {
2103
+ lastPtr = currentPtr;
2104
+ currentPtr = currentPtr->next;
2105
+ }
2106
+
2107
+ if (lastPtr == NULL)
2108
+ {
2109
+ newPtr->next = head;
2110
+ head = newPtr;
2111
+ }
2112
+ else
2113
+ {
2114
+ newPtr->next = currentPtr;
2115
+ lastPtr->next = newPtr;
2116
+ }
2117
+
2118
+ return(head);
2119
+ }
2120
+
2121
+ /********************************************************************/
2122
+ /* RemoveModifyFunctionFromCallList: Removes a function from a list */
2123
+ /* of functions which are called to perform certain operations */
2124
+ /* (e.g. clear, reset, and bload functions). */
2125
+ /********************************************************************/
2126
+ ModifyCallFunctionItem *RemoveModifyFunctionFromCallList(
2127
+ Environment *theEnv,
2128
+ const char *name,
2129
+ ModifyCallFunctionItem *head,
2130
+ bool *found)
2131
+ {
2132
+ ModifyCallFunctionItem *currentPtr, *lastPtr;
2133
+
2134
+ *found = false;
2135
+ lastPtr = NULL;
2136
+ currentPtr = head;
2137
+
2138
+ while (currentPtr != NULL)
2139
+ {
2140
+ if (strcmp(name,currentPtr->name) == 0)
2141
+ {
2142
+ *found = true;
2143
+ if (lastPtr == NULL)
2144
+ { head = currentPtr->next; }
2145
+ else
2146
+ { lastPtr->next = currentPtr->next; }
2147
+
2148
+ genfree(theEnv,(void *) currentPtr->name,strlen(currentPtr->name) + 1);
2149
+ rtn_struct(theEnv,modifyCallFunctionItem,currentPtr);
2150
+ return head;
2151
+ }
2152
+
2153
+ lastPtr = currentPtr;
2154
+ currentPtr = currentPtr->next;
2155
+ }
2156
+
2157
+ return head;
2158
+ }
2159
+
2160
+
2161
+ /***************************************************************/
2162
+ /* DeallocateModifyCallList: Removes all functions from a list */
2163
+ /* of functions which are called to perform certain */
2164
+ /* operations (e.g. clear, reset, and bload functions). */
2165
+ /***************************************************************/
2166
+ void DeallocateModifyCallList(
2167
+ Environment *theEnv,
2168
+ ModifyCallFunctionItem *theList)
2169
+ {
2170
+ ModifyCallFunctionItem *tmpPtr, *nextPtr;
2171
+
2172
+ tmpPtr = theList;
2173
+ while (tmpPtr != NULL)
2174
+ {
2175
+ nextPtr = tmpPtr->next;
2176
+ genfree(theEnv,(void *) tmpPtr->name,strlen(tmpPtr->name) + 1);
2177
+ rtn_struct(theEnv,modifyCallFunctionItem,tmpPtr);
2178
+ tmpPtr = nextPtr;
2179
+ }
2180
+ }
2181
+
2182
+ /**********************/
2183
+ /* CreateFactBuilder: */
2184
+ /**********************/
2185
+ FactBuilder *CreateFactBuilder(
2186
+ Environment *theEnv,
2187
+ const char *deftemplateName)
2188
+ {
2189
+ FactBuilder *theFB;
2190
+ Deftemplate *theDeftemplate;
2191
+ int i;
2192
+
2193
+ if (theEnv == NULL) return NULL;
2194
+
2195
+ if (deftemplateName != NULL)
2196
+ {
2197
+ theDeftemplate = FindDeftemplate(theEnv,deftemplateName);
2198
+ if (theDeftemplate == NULL)
2199
+ {
2200
+ FactData(theEnv)->factBuilderError = FBE_DEFTEMPLATE_NOT_FOUND_ERROR;
2201
+ return NULL;
2202
+ }
2203
+
2204
+ if (theDeftemplate->implied)
2205
+ {
2206
+ FactData(theEnv)->factBuilderError = FBE_IMPLIED_DEFTEMPLATE_ERROR;
2207
+ return NULL;
2208
+ }
2209
+ }
2210
+ else
2211
+ { theDeftemplate = NULL; }
2212
+
2213
+ theFB = get_struct(theEnv,factBuilder);
2214
+ theFB->fbEnv = theEnv;
2215
+ theFB->fbDeftemplate = theDeftemplate;
2216
+
2217
+ if ((theDeftemplate == NULL) || (theDeftemplate->numberOfSlots == 0))
2218
+ { theFB->fbValueArray = NULL; }
2219
+ else
2220
+ {
2221
+ theFB->fbValueArray = (CLIPSValue *) gm2(theEnv,sizeof(CLIPSValue) * theDeftemplate->numberOfSlots);
2222
+ for (i = 0; i < theDeftemplate->numberOfSlots; i++)
2223
+ { theFB->fbValueArray[i].voidValue = VoidConstant(theEnv); }
2224
+ }
2225
+
2226
+ FactData(theEnv)->factBuilderError = FBE_NO_ERROR;
2227
+
2228
+ return theFB;
2229
+ }
2230
+
2231
+ /*************************/
2232
+ /* FBPutSlotCLIPSInteger */
2233
+ /*************************/
2234
+ PutSlotError FBPutSlotCLIPSInteger(
2235
+ FactBuilder *theFB,
2236
+ const char *slotName,
2237
+ CLIPSInteger *slotValue)
2238
+ {
2239
+ CLIPSValue theValue;
2240
+
2241
+ theValue.integerValue = slotValue;
2242
+ return FBPutSlot(theFB,slotName,&theValue);
2243
+ }
2244
+
2245
+ /********************/
2246
+ /* FBPutSlotInteger */
2247
+ /********************/
2248
+ PutSlotError FBPutSlotInteger(
2249
+ FactBuilder *theFB,
2250
+ const char *slotName,
2251
+ long long longLongValue)
2252
+ {
2253
+ CLIPSValue theValue;
2254
+
2255
+ if (theFB == NULL)
2256
+ { return PSE_NULL_POINTER_ERROR; }
2257
+
2258
+ theValue.integerValue = CreateInteger(theFB->fbEnv,longLongValue);
2259
+ return FBPutSlot(theFB,slotName,&theValue);
2260
+ }
2261
+
2262
+ /************************/
2263
+ /* FBPutSlotCLIPSLexeme */
2264
+ /************************/
2265
+ PutSlotError FBPutSlotCLIPSLexeme(
2266
+ FactBuilder *theFB,
2267
+ const char *slotName,
2268
+ CLIPSLexeme *slotValue)
2269
+ {
2270
+ CLIPSValue theValue;
2271
+
2272
+ theValue.lexemeValue = slotValue;
2273
+ return FBPutSlot(theFB,slotName,&theValue);
2274
+ }
2275
+
2276
+ /*******************/
2277
+ /* FBPutSlotSymbol */
2278
+ /*******************/
2279
+ PutSlotError FBPutSlotSymbol(
2280
+ FactBuilder *theFB,
2281
+ const char *slotName,
2282
+ const char *stringValue)
2283
+ {
2284
+ CLIPSValue theValue;
2285
+
2286
+ if (theFB == NULL)
2287
+ { return PSE_NULL_POINTER_ERROR; }
2288
+
2289
+ theValue.lexemeValue = CreateSymbol(theFB->fbEnv,stringValue);
2290
+ return FBPutSlot(theFB,slotName,&theValue);
2291
+ }
2292
+
2293
+ /*******************/
2294
+ /* FBPutSlotString */
2295
+ /*******************/
2296
+ PutSlotError FBPutSlotString(
2297
+ FactBuilder *theFB,
2298
+ const char *slotName,
2299
+ const char *stringValue)
2300
+ {
2301
+ CLIPSValue theValue;
2302
+
2303
+ if (theFB == NULL)
2304
+ { return PSE_NULL_POINTER_ERROR; }
2305
+
2306
+ theValue.lexemeValue = CreateString(theFB->fbEnv,stringValue);
2307
+ return FBPutSlot(theFB,slotName,&theValue);
2308
+ }
2309
+
2310
+ /*************************/
2311
+ /* FBPutSlotInstanceName */
2312
+ /*************************/
2313
+ PutSlotError FBPutSlotInstanceName(
2314
+ FactBuilder *theFB,
2315
+ const char *slotName,
2316
+ const char *stringValue)
2317
+ {
2318
+ CLIPSValue theValue;
2319
+
2320
+ if (theFB == NULL)
2321
+ { return PSE_NULL_POINTER_ERROR; }
2322
+
2323
+ theValue.lexemeValue = CreateInstanceName(theFB->fbEnv,stringValue);
2324
+ return FBPutSlot(theFB,slotName,&theValue);
2325
+ }
2326
+
2327
+ /***********************/
2328
+ /* FBPutSlotCLIPSFloat */
2329
+ /***********************/
2330
+ PutSlotError FBPutSlotCLIPSFloat(
2331
+ FactBuilder *theFB,
2332
+ const char *slotName,
2333
+ CLIPSFloat *slotValue)
2334
+ {
2335
+ CLIPSValue theValue;
2336
+
2337
+ theValue.floatValue = slotValue;
2338
+ return FBPutSlot(theFB,slotName,&theValue);
2339
+ }
2340
+
2341
+ /******************/
2342
+ /* FBPutSlotFloat */
2343
+ /******************/
2344
+ PutSlotError FBPutSlotFloat(
2345
+ FactBuilder *theFB,
2346
+ const char *slotName,
2347
+ double floatValue)
2348
+ {
2349
+ CLIPSValue theValue;
2350
+
2351
+ if (theFB == NULL)
2352
+ { return PSE_NULL_POINTER_ERROR; }
2353
+
2354
+ theValue.floatValue = CreateFloat(theFB->fbEnv,floatValue);
2355
+ return FBPutSlot(theFB,slotName,&theValue);
2356
+ }
2357
+
2358
+ /*****************/
2359
+ /* FBPutSlotFact */
2360
+ /*****************/
2361
+ PutSlotError FBPutSlotFact(
2362
+ FactBuilder *theFB,
2363
+ const char *slotName,
2364
+ Fact *slotValue)
2365
+ {
2366
+ CLIPSValue theValue;
2367
+
2368
+ theValue.factValue = slotValue;
2369
+ return FBPutSlot(theFB,slotName,&theValue);
2370
+ }
2371
+
2372
+ /*********************/
2373
+ /* FBPutSlotInstance */
2374
+ /*********************/
2375
+ PutSlotError FBPutSlotInstance(
2376
+ FactBuilder *theFB,
2377
+ const char *slotName,
2378
+ Instance *slotValue)
2379
+ {
2380
+ CLIPSValue theValue;
2381
+
2382
+ theValue.instanceValue = slotValue;
2383
+ return FBPutSlot(theFB,slotName,&theValue);
2384
+ }
2385
+
2386
+ /*********************************/
2387
+ /* FBPutSlotCLIPSExternalAddress */
2388
+ /*********************************/
2389
+ PutSlotError FBPutSlotCLIPSExternalAddress(
2390
+ FactBuilder *theFB,
2391
+ const char *slotName,
2392
+ CLIPSExternalAddress *slotValue)
2393
+ {
2394
+ CLIPSValue theValue;
2395
+
2396
+ theValue.externalAddressValue = slotValue;
2397
+ return FBPutSlot(theFB,slotName,&theValue);
2398
+ }
2399
+
2400
+ /***********************/
2401
+ /* FBPutSlotMultifield */
2402
+ /***********************/
2403
+ PutSlotError FBPutSlotMultifield(
2404
+ FactBuilder *theFB,
2405
+ const char *slotName,
2406
+ Multifield *slotValue)
2407
+ {
2408
+ CLIPSValue theValue;
2409
+
2410
+ theValue.multifieldValue = slotValue;
2411
+ return FBPutSlot(theFB,slotName,&theValue);
2412
+ }
2413
+
2414
+ /**************/
2415
+ /* FBPutSlot: */
2416
+ /**************/
2417
+ PutSlotError FBPutSlot(
2418
+ FactBuilder *theFB,
2419
+ const char *slotName,
2420
+ CLIPSValue *slotValue)
2421
+ {
2422
+ Environment *theEnv;
2423
+ struct templateSlot *theSlot;
2424
+ unsigned short whichSlot;
2425
+ CLIPSValue oldValue;
2426
+ int i;
2427
+ ConstraintViolationType cvType;
2428
+
2429
+ /*==========================*/
2430
+ /* Check for NULL pointers. */
2431
+ /*==========================*/
2432
+
2433
+ if ((theFB == NULL) || (slotName == NULL) || (slotValue == NULL))
2434
+ { return PSE_NULL_POINTER_ERROR; }
2435
+
2436
+ if ((theFB->fbDeftemplate == NULL) || (slotValue->value == NULL))
2437
+ { return PSE_NULL_POINTER_ERROR; }
2438
+
2439
+ theEnv = theFB->fbEnv;
2440
+
2441
+ /*===================================*/
2442
+ /* Make sure the slot name requested */
2443
+ /* corresponds to a valid slot name. */
2444
+ /*===================================*/
2445
+
2446
+ if ((theSlot = FindSlot(theFB->fbDeftemplate,CreateSymbol(theFB->fbEnv,slotName),&whichSlot)) == NULL)
2447
+ { return PSE_SLOT_NOT_FOUND_ERROR; }
2448
+
2449
+ /*=============================================*/
2450
+ /* Make sure a single field value is not being */
2451
+ /* stored in a multifield slot or vice versa. */
2452
+ /*=============================================*/
2453
+
2454
+ if (((theSlot->multislot == 0) && (slotValue->header->type == MULTIFIELD_TYPE)) ||
2455
+ ((theSlot->multislot == 1) && (slotValue->header->type != MULTIFIELD_TYPE)))
2456
+ { return PSE_CARDINALITY_ERROR; }
2457
+
2458
+ /*=================================*/
2459
+ /* Check constraints for the slot. */
2460
+ /*=================================*/
2461
+
2462
+ if (theSlot->constraints != NULL)
2463
+ {
2464
+ if ((cvType = ConstraintCheckValue(theEnv,slotValue->header->type,slotValue->value,theSlot->constraints)) != NO_VIOLATION)
2465
+ {
2466
+ switch(cvType)
2467
+ {
2468
+ case NO_VIOLATION:
2469
+ case FUNCTION_RETURN_TYPE_VIOLATION:
2470
+ SystemError(theEnv,"FACTMNGR",2);
2471
+ ExitRouter(theEnv,EXIT_FAILURE);
2472
+ break;
2473
+
2474
+ case TYPE_VIOLATION:
2475
+ return PSE_TYPE_ERROR;
2476
+
2477
+ case RANGE_VIOLATION:
2478
+ return PSE_RANGE_ERROR;
2479
+
2480
+ case ALLOWED_VALUES_VIOLATION:
2481
+ return PSE_ALLOWED_VALUES_ERROR;
2482
+
2483
+ case CARDINALITY_VIOLATION:
2484
+ return PSE_CARDINALITY_ERROR;
2485
+
2486
+ case ALLOWED_CLASSES_VIOLATION:
2487
+ return PSE_ALLOWED_CLASSES_ERROR;
2488
+ }
2489
+ }
2490
+ }
2491
+
2492
+ /*==========================*/
2493
+ /* Set up the change array. */
2494
+ /*==========================*/
2495
+
2496
+ if (theFB->fbValueArray == NULL)
2497
+ {
2498
+ theFB->fbValueArray = (CLIPSValue *) gm2(theFB->fbEnv,sizeof(CLIPSValue) * theFB->fbDeftemplate->numberOfSlots);
2499
+ for (i = 0; i < theFB->fbDeftemplate->numberOfSlots; i++)
2500
+ { theFB->fbValueArray[i].voidValue = theFB->fbEnv->VoidConstant; }
2501
+ }
2502
+
2503
+ /*=====================*/
2504
+ /* Set the slot value. */
2505
+ /*=====================*/
2506
+
2507
+ oldValue.value = theFB->fbValueArray[whichSlot].value;
2508
+
2509
+ if (oldValue.header->type == MULTIFIELD_TYPE)
2510
+ {
2511
+ if (MultifieldsEqual(oldValue.multifieldValue,slotValue->multifieldValue))
2512
+ { return PSE_NO_ERROR; }
2513
+ }
2514
+ else
2515
+ {
2516
+ if (oldValue.value == slotValue->value)
2517
+ { return PSE_NO_ERROR; }
2518
+ }
2519
+
2520
+ Release(theEnv,oldValue.header);
2521
+
2522
+ if (oldValue.header->type == MULTIFIELD_TYPE)
2523
+ { ReturnMultifield(theEnv,oldValue.multifieldValue); }
2524
+
2525
+ if (slotValue->header->type == MULTIFIELD_TYPE)
2526
+ { theFB->fbValueArray[whichSlot].multifieldValue = CopyMultifield(theEnv,slotValue->multifieldValue); }
2527
+ else
2528
+ { theFB->fbValueArray[whichSlot].value = slotValue->value; }
2529
+
2530
+ Retain(theEnv,theFB->fbValueArray[whichSlot].header);
2531
+
2532
+ return PSE_NO_ERROR;
2533
+ }
2534
+
2535
+ /*************/
2536
+ /* FBAssert: */
2537
+ /*************/
2538
+ Fact *FBAssert(
2539
+ FactBuilder *theFB)
2540
+ {
2541
+ Environment *theEnv;
2542
+ int i;
2543
+ Fact *theFact;
2544
+
2545
+ if (theFB == NULL) return NULL;
2546
+ theEnv = theFB->fbEnv;
2547
+
2548
+ if (theFB->fbDeftemplate == NULL)
2549
+ {
2550
+ FactData(theEnv)->factBuilderError = FBE_NULL_POINTER_ERROR;
2551
+ return NULL;
2552
+ }
2553
+
2554
+ theFact = CreateFact(theFB->fbDeftemplate);
2555
+
2556
+ for (i = 0; i < theFB->fbDeftemplate->numberOfSlots; i++)
2557
+ {
2558
+ if (theFB->fbValueArray[i].voidValue != VoidConstant(theEnv))
2559
+ {
2560
+ theFact->theProposition.contents[i].value = theFB->fbValueArray[i].value;
2561
+ Release(theEnv,theFB->fbValueArray[i].header);
2562
+ theFB->fbValueArray[i].voidValue = VoidConstant(theEnv);
2563
+ }
2564
+ }
2565
+
2566
+ AssignFactSlotDefaults(theFact);
2567
+
2568
+ theFact = Assert(theFact);
2569
+
2570
+ switch (FactData(theEnv)->assertError)
2571
+ {
2572
+ case AE_NO_ERROR:
2573
+ FactData(theEnv)->factBuilderError = FBE_NO_ERROR;
2574
+ break;
2575
+
2576
+ case AE_NULL_POINTER_ERROR:
2577
+ case AE_RETRACTED_ERROR:
2578
+ SystemError(theEnv,"FACTMNGR",1);
2579
+ ExitRouter(theEnv,EXIT_FAILURE);
2580
+ break;
2581
+
2582
+ case AE_COULD_NOT_ASSERT_ERROR:
2583
+ FactData(theEnv)->factBuilderError = FBE_COULD_NOT_ASSERT_ERROR;
2584
+ break;
2585
+
2586
+ case AE_RULE_NETWORK_ERROR:
2587
+ FactData(theEnv)->factBuilderError = FBE_RULE_NETWORK_ERROR;
2588
+ break;
2589
+ }
2590
+
2591
+ return theFact;
2592
+ }
2593
+
2594
+ /**************/
2595
+ /* FBDispose: */
2596
+ /**************/
2597
+ void FBDispose(
2598
+ FactBuilder *theFB)
2599
+ {
2600
+ Environment *theEnv;
2601
+
2602
+ if (theFB == NULL) return;
2603
+
2604
+ theEnv = theFB->fbEnv;
2605
+
2606
+ FBAbort(theFB);
2607
+
2608
+ if (theFB->fbValueArray != NULL)
2609
+ { rm(theEnv,theFB->fbValueArray,sizeof(CLIPSValue) * theFB->fbDeftemplate->numberOfSlots); }
2610
+
2611
+ rtn_struct(theEnv,factBuilder,theFB);
2612
+ }
2613
+
2614
+ /************/
2615
+ /* FBAbort: */
2616
+ /************/
2617
+ void FBAbort(
2618
+ FactBuilder *theFB)
2619
+ {
2620
+ Environment *theEnv;
2621
+ GCBlock gcb;
2622
+ int i;
2623
+
2624
+ if (theFB == NULL) return;
2625
+
2626
+ if (theFB->fbDeftemplate == NULL) return;
2627
+
2628
+ theEnv = theFB->fbEnv;
2629
+
2630
+ GCBlockStart(theEnv,&gcb);
2631
+
2632
+ for (i = 0; i < theFB->fbDeftemplate->numberOfSlots; i++)
2633
+ {
2634
+ Release(theEnv,theFB->fbValueArray[i].header);
2635
+
2636
+ if (theFB->fbValueArray[i].header->type == MULTIFIELD_TYPE)
2637
+ { ReturnMultifield(theEnv,theFB->fbValueArray[i].multifieldValue); }
2638
+
2639
+ theFB->fbValueArray[i].voidValue = VoidConstant(theEnv);
2640
+ }
2641
+
2642
+ GCBlockEnd(theEnv,&gcb);
2643
+ }
2644
+
2645
+ /********************/
2646
+ /* FBSetDeftemplate */
2647
+ /********************/
2648
+ FactBuilderError FBSetDeftemplate(
2649
+ FactBuilder *theFB,
2650
+ const char *deftemplateName)
2651
+ {
2652
+ Deftemplate *theDeftemplate;
2653
+ Environment *theEnv;
2654
+ int i;
2655
+
2656
+ if (theFB == NULL)
2657
+ { return FBE_NULL_POINTER_ERROR; }
2658
+
2659
+ theEnv = theFB->fbEnv;
2660
+
2661
+ FBAbort(theFB);
2662
+
2663
+ if (deftemplateName != NULL)
2664
+ {
2665
+ theDeftemplate = FindDeftemplate(theFB->fbEnv,deftemplateName);
2666
+
2667
+ if (theDeftemplate == NULL)
2668
+ {
2669
+ FactData(theEnv)->factBuilderError = FBE_DEFTEMPLATE_NOT_FOUND_ERROR;
2670
+ return FBE_DEFTEMPLATE_NOT_FOUND_ERROR;
2671
+ }
2672
+
2673
+ if (theDeftemplate->implied)
2674
+ {
2675
+ FactData(theEnv)->factBuilderError = FBE_IMPLIED_DEFTEMPLATE_ERROR;
2676
+ return FBE_IMPLIED_DEFTEMPLATE_ERROR;
2677
+ }
2678
+ }
2679
+ else
2680
+ { theDeftemplate = NULL; }
2681
+
2682
+ if (theFB->fbValueArray != NULL)
2683
+ { rm(theEnv,theFB->fbValueArray,sizeof(CLIPSValue) * theFB->fbDeftemplate->numberOfSlots); }
2684
+
2685
+ theFB->fbDeftemplate = theDeftemplate;
2686
+
2687
+ if ((theDeftemplate == NULL) || (theDeftemplate->numberOfSlots == 0))
2688
+ { theFB->fbValueArray = NULL; }
2689
+ else
2690
+ {
2691
+ theFB->fbValueArray = (CLIPSValue *) gm2(theEnv,sizeof(CLIPSValue) * theDeftemplate->numberOfSlots);
2692
+ for (i = 0; i < theDeftemplate->numberOfSlots; i++)
2693
+ { theFB->fbValueArray[i].voidValue = VoidConstant(theEnv); }
2694
+ }
2695
+
2696
+ FactData(theEnv)->factBuilderError = FBE_NO_ERROR;
2697
+ return FBE_NO_ERROR;
2698
+ }
2699
+
2700
+ /************/
2701
+ /* FBError: */
2702
+ /************/
2703
+ FactBuilderError FBError(
2704
+ Environment *theEnv)
2705
+ {
2706
+ return FactData(theEnv)->factBuilderError;
2707
+ }
2708
+
2709
+ /***********************/
2710
+ /* CreateFactModifier: */
2711
+ /***********************/
2712
+ FactModifier *CreateFactModifier(
2713
+ Environment *theEnv,
2714
+ Fact *oldFact)
2715
+ {
2716
+ FactModifier *theFM;
2717
+ int i;
2718
+
2719
+ if (theEnv == NULL) return NULL;
2720
+
2721
+ if (oldFact != NULL)
2722
+ {
2723
+ if (oldFact->garbage)
2724
+ {
2725
+ FactData(theEnv)->factModifierError = FME_RETRACTED_ERROR;
2726
+ return NULL;
2727
+ }
2728
+
2729
+ if (oldFact->whichDeftemplate->implied)
2730
+ {
2731
+ FactData(theEnv)->factModifierError = FME_IMPLIED_DEFTEMPLATE_ERROR;
2732
+ return NULL;
2733
+ }
2734
+
2735
+ RetainFact(oldFact);
2736
+ }
2737
+
2738
+ theFM = get_struct(theEnv,factModifier);
2739
+ theFM->fmEnv = theEnv;
2740
+ theFM->fmOldFact = oldFact;
2741
+
2742
+ if ((oldFact == NULL) || (oldFact->whichDeftemplate->numberOfSlots == 0))
2743
+ {
2744
+ theFM->fmValueArray = NULL;
2745
+ theFM->changeMap = NULL;
2746
+ }
2747
+ else
2748
+ {
2749
+ theFM->fmValueArray = (CLIPSValue *) gm2(theEnv,sizeof(CLIPSValue) * oldFact->whichDeftemplate->numberOfSlots);
2750
+
2751
+ for (i = 0; i < oldFact->whichDeftemplate->numberOfSlots; i++)
2752
+ { theFM->fmValueArray[i].voidValue = VoidConstant(theEnv); }
2753
+
2754
+ theFM->changeMap = (char *) gm2(theEnv,CountToBitMapSize(oldFact->whichDeftemplate->numberOfSlots));
2755
+ ClearBitString((void *) theFM->changeMap,CountToBitMapSize(oldFact->whichDeftemplate->numberOfSlots));
2756
+ }
2757
+
2758
+ FactData(theEnv)->factModifierError = FME_NO_ERROR;
2759
+ return theFM;
2760
+ }
2761
+
2762
+ /*************************/
2763
+ /* FMPutSlotCLIPSInteger */
2764
+ /*************************/
2765
+ PutSlotError FMPutSlotCLIPSInteger(
2766
+ FactModifier *theFM,
2767
+ const char *slotName,
2768
+ CLIPSInteger *slotValue)
2769
+ {
2770
+ CLIPSValue theValue;
2771
+
2772
+ theValue.integerValue = slotValue;
2773
+ return FMPutSlot(theFM,slotName,&theValue);
2774
+ }
2775
+
2776
+ /********************/
2777
+ /* FMPutSlotInteger */
2778
+ /********************/
2779
+ PutSlotError FMPutSlotInteger(
2780
+ FactModifier *theFM,
2781
+ const char *slotName,
2782
+ long long longLongValue)
2783
+ {
2784
+ CLIPSValue theValue;
2785
+
2786
+ if (theFM == NULL)
2787
+ { return PSE_NULL_POINTER_ERROR; }
2788
+
2789
+ theValue.integerValue = CreateInteger(theFM->fmEnv,longLongValue);
2790
+ return FMPutSlot(theFM,slotName,&theValue);
2791
+ }
2792
+
2793
+ /************************/
2794
+ /* FMPutSlotCLIPSLexeme */
2795
+ /************************/
2796
+ PutSlotError FMPutSlotCLIPSLexeme(
2797
+ FactModifier *theFM,
2798
+ const char *slotName,
2799
+ CLIPSLexeme *slotValue)
2800
+ {
2801
+ CLIPSValue theValue;
2802
+
2803
+ theValue.lexemeValue = slotValue;
2804
+ return FMPutSlot(theFM,slotName,&theValue);
2805
+ }
2806
+
2807
+ /*******************/
2808
+ /* FMPutSlotSymbol */
2809
+ /*******************/
2810
+ PutSlotError FMPutSlotSymbol(
2811
+ FactModifier *theFM,
2812
+ const char *slotName,
2813
+ const char *stringValue)
2814
+ {
2815
+ CLIPSValue theValue;
2816
+
2817
+ if (theFM == NULL)
2818
+ { return PSE_NULL_POINTER_ERROR; }
2819
+
2820
+ theValue.lexemeValue = CreateSymbol(theFM->fmEnv,stringValue);
2821
+ return FMPutSlot(theFM,slotName,&theValue);
2822
+ }
2823
+
2824
+ /*******************/
2825
+ /* FMPutSlotString */
2826
+ /*******************/
2827
+ PutSlotError FMPutSlotString(
2828
+ FactModifier *theFM,
2829
+ const char *slotName,
2830
+ const char *stringValue)
2831
+ {
2832
+ CLIPSValue theValue;
2833
+
2834
+ if (theFM == NULL)
2835
+ { return PSE_NULL_POINTER_ERROR; }
2836
+
2837
+ theValue.lexemeValue = CreateString(theFM->fmEnv,stringValue);
2838
+ return FMPutSlot(theFM,slotName,&theValue);
2839
+ }
2840
+
2841
+ /*************************/
2842
+ /* FMPutSlotInstanceName */
2843
+ /*************************/
2844
+ PutSlotError FMPutSlotInstanceName(
2845
+ FactModifier *theFM,
2846
+ const char *slotName,
2847
+ const char *stringValue)
2848
+ {
2849
+ CLIPSValue theValue;
2850
+
2851
+ if (theFM == NULL)
2852
+ { return PSE_NULL_POINTER_ERROR; }
2853
+
2854
+ theValue.lexemeValue = CreateInstanceName(theFM->fmEnv,stringValue);
2855
+ return FMPutSlot(theFM,slotName,&theValue);
2856
+ }
2857
+
2858
+ /***********************/
2859
+ /* FMPutSlotCLIPSFloat */
2860
+ /***********************/
2861
+ PutSlotError FMPutSlotCLIPSFloat(
2862
+ FactModifier *theFM,
2863
+ const char *slotName,
2864
+ CLIPSFloat *slotValue)
2865
+ {
2866
+ CLIPSValue theValue;
2867
+
2868
+ theValue.floatValue = slotValue;
2869
+ return FMPutSlot(theFM,slotName,&theValue);
2870
+ }
2871
+
2872
+ /******************/
2873
+ /* FMPutSlotFloat */
2874
+ /******************/
2875
+ PutSlotError FMPutSlotFloat(
2876
+ FactModifier *theFM,
2877
+ const char *slotName,
2878
+ double floatValue)
2879
+ {
2880
+ CLIPSValue theValue;
2881
+
2882
+ if (theFM == NULL)
2883
+ { return PSE_NULL_POINTER_ERROR; }
2884
+
2885
+ theValue.floatValue = CreateFloat(theFM->fmEnv,floatValue);
2886
+ return FMPutSlot(theFM,slotName,&theValue);
2887
+ }
2888
+
2889
+ /*****************/
2890
+ /* FMPutSlotFact */
2891
+ /*****************/
2892
+ PutSlotError FMPutSlotFact(
2893
+ FactModifier *theFM,
2894
+ const char *slotName,
2895
+ Fact *slotValue)
2896
+ {
2897
+ CLIPSValue theValue;
2898
+
2899
+ theValue.factValue = slotValue;
2900
+ return FMPutSlot(theFM,slotName,&theValue);
2901
+ }
2902
+
2903
+ /*********************/
2904
+ /* FMPutSlotInstance */
2905
+ /*********************/
2906
+ PutSlotError FMPutSlotInstance(
2907
+ FactModifier *theFM,
2908
+ const char *slotName,
2909
+ Instance *slotValue)
2910
+ {
2911
+ CLIPSValue theValue;
2912
+
2913
+ theValue.instanceValue = slotValue;
2914
+ return FMPutSlot(theFM,slotName,&theValue);
2915
+ }
2916
+
2917
+ /****************************/
2918
+ /* FMPutSlotExternalAddress */
2919
+ /****************************/
2920
+ PutSlotError FMPutSlotExternalAddress(
2921
+ FactModifier *theFM,
2922
+ const char *slotName,
2923
+ CLIPSExternalAddress *slotValue)
2924
+ {
2925
+ CLIPSValue theValue;
2926
+
2927
+ theValue.externalAddressValue = slotValue;
2928
+ return FMPutSlot(theFM,slotName,&theValue);
2929
+ }
2930
+
2931
+ /***********************/
2932
+ /* FMPutSlotMultifield */
2933
+ /***********************/
2934
+ PutSlotError FMPutSlotMultifield(
2935
+ FactModifier *theFM,
2936
+ const char *slotName,
2937
+ Multifield *slotValue)
2938
+ {
2939
+ CLIPSValue theValue;
2940
+
2941
+ theValue.multifieldValue = slotValue;
2942
+ return FMPutSlot(theFM,slotName,&theValue);
2943
+ }
2944
+
2945
+ /**************/
2946
+ /* FMPutSlot: */
2947
+ /**************/
2948
+ PutSlotError FMPutSlot(
2949
+ FactModifier *theFM,
2950
+ const char *slotName,
2951
+ CLIPSValue *slotValue)
2952
+ {
2953
+ Environment *theEnv;
2954
+ struct templateSlot *theSlot;
2955
+ unsigned short whichSlot;
2956
+ CLIPSValue oldValue;
2957
+ CLIPSValue oldFactValue;
2958
+ int i;
2959
+ ConstraintViolationType cvType;
2960
+
2961
+ /*==========================*/
2962
+ /* Check for NULL pointers. */
2963
+ /*==========================*/
2964
+
2965
+ if ((theFM == NULL) || (slotName == NULL) || (slotValue == NULL))
2966
+ { return PSE_NULL_POINTER_ERROR; }
2967
+
2968
+ if ((theFM->fmOldFact == NULL) || (slotValue->value == NULL))
2969
+ { return PSE_NULL_POINTER_ERROR; }
2970
+
2971
+ theEnv = theFM->fmEnv;
2972
+
2973
+ /*==================================*/
2974
+ /* Deleted facts can't be modified. */
2975
+ /*==================================*/
2976
+
2977
+ if (theFM->fmOldFact->garbage)
2978
+ { return PSE_INVALID_TARGET_ERROR; }
2979
+
2980
+ /*===================================*/
2981
+ /* Make sure the slot name requested */
2982
+ /* corresponds to a valid slot name. */
2983
+ /*===================================*/
2984
+
2985
+ if ((theSlot = FindSlot(theFM->fmOldFact->whichDeftemplate,CreateSymbol(theEnv,slotName),&whichSlot)) == NULL)
2986
+ { return PSE_SLOT_NOT_FOUND_ERROR; }
2987
+
2988
+ /*=============================================*/
2989
+ /* Make sure a single field value is not being */
2990
+ /* stored in a multifield slot or vice versa. */
2991
+ /*=============================================*/
2992
+
2993
+ if (((theSlot->multislot == 0) && (slotValue->header->type == MULTIFIELD_TYPE)) ||
2994
+ ((theSlot->multislot == 1) && (slotValue->header->type != MULTIFIELD_TYPE)))
2995
+ { return PSE_CARDINALITY_ERROR; }
2996
+
2997
+ /*=================================*/
2998
+ /* Check constraints for the slot. */
2999
+ /*=================================*/
3000
+
3001
+ if (theSlot->constraints != NULL)
3002
+ {
3003
+ if ((cvType = ConstraintCheckValue(theEnv,slotValue->header->type,slotValue->value,theSlot->constraints)) != NO_VIOLATION)
3004
+ {
3005
+ switch(cvType)
3006
+ {
3007
+ case NO_VIOLATION:
3008
+ case FUNCTION_RETURN_TYPE_VIOLATION:
3009
+ SystemError(theEnv,"FACTMNGR",3);
3010
+ ExitRouter(theEnv,EXIT_FAILURE);
3011
+ break;
3012
+
3013
+ case TYPE_VIOLATION:
3014
+ return PSE_TYPE_ERROR;
3015
+
3016
+ case RANGE_VIOLATION:
3017
+ return PSE_RANGE_ERROR;
3018
+
3019
+ case ALLOWED_VALUES_VIOLATION:
3020
+ return PSE_ALLOWED_VALUES_ERROR;
3021
+
3022
+ case CARDINALITY_VIOLATION:
3023
+ return PSE_CARDINALITY_ERROR;
3024
+
3025
+ case ALLOWED_CLASSES_VIOLATION:
3026
+ return PSE_ALLOWED_CLASSES_ERROR;
3027
+ }
3028
+ }
3029
+ }
3030
+
3031
+ /*===========================*/
3032
+ /* Set up the change arrays. */
3033
+ /*===========================*/
3034
+
3035
+ if (theFM->fmValueArray == NULL)
3036
+ {
3037
+ theFM->fmValueArray = (CLIPSValue *) gm2(theFM->fmEnv,sizeof(CLIPSValue) * theFM->fmOldFact->whichDeftemplate->numberOfSlots);
3038
+ for (i = 0; i < theFM->fmOldFact->whichDeftemplate->numberOfSlots; i++)
3039
+ { theFM->fmValueArray[i].voidValue = theFM->fmEnv->VoidConstant; }
3040
+ }
3041
+
3042
+ if (theFM->changeMap == NULL)
3043
+ {
3044
+ theFM->changeMap = (char *) gm2(theFM->fmEnv,CountToBitMapSize(theFM->fmOldFact->whichDeftemplate->numberOfSlots));
3045
+ ClearBitString((void *) theFM->changeMap,CountToBitMapSize(theFM->fmOldFact->whichDeftemplate->numberOfSlots));
3046
+ }
3047
+
3048
+ /*=====================*/
3049
+ /* Set the slot value. */
3050
+ /*=====================*/
3051
+
3052
+ oldValue.value = theFM->fmValueArray[whichSlot].value;
3053
+ oldFactValue.value = theFM->fmOldFact->theProposition.contents[whichSlot].value;
3054
+
3055
+ if (oldFactValue.header->type == MULTIFIELD_TYPE)
3056
+ {
3057
+ if (MultifieldsEqual(oldFactValue.multifieldValue,slotValue->multifieldValue))
3058
+ {
3059
+ Release(theFM->fmEnv,oldValue.header);
3060
+ if (oldValue.header->type == MULTIFIELD_TYPE)
3061
+ { ReturnMultifield(theFM->fmEnv,oldValue.multifieldValue); }
3062
+ theFM->fmValueArray[whichSlot].voidValue = theFM->fmEnv->VoidConstant;
3063
+ ClearBitMap(theFM->changeMap,whichSlot);
3064
+ return PSE_NO_ERROR;
3065
+ }
3066
+
3067
+ if ((oldValue.header->type == MULTIFIELD_TYPE) &&
3068
+ MultifieldsEqual(oldValue.multifieldValue,slotValue->multifieldValue))
3069
+ { return PSE_NO_ERROR; }
3070
+ }
3071
+ else
3072
+ {
3073
+ if (slotValue->value == oldFactValue.value)
3074
+ {
3075
+ Release(theFM->fmEnv,oldValue.header);
3076
+ theFM->fmValueArray[whichSlot].voidValue = theFM->fmEnv->VoidConstant;
3077
+ ClearBitMap(theFM->changeMap,whichSlot);
3078
+ return PSE_NO_ERROR;
3079
+ }
3080
+
3081
+ if (oldValue.value == slotValue->value)
3082
+ { return PSE_NO_ERROR; }
3083
+ }
3084
+
3085
+ SetBitMap(theFM->changeMap,whichSlot);
3086
+
3087
+ Release(theFM->fmEnv,oldValue.header);
3088
+
3089
+ if (oldValue.header->type == MULTIFIELD_TYPE)
3090
+ { ReturnMultifield(theFM->fmEnv,oldValue.multifieldValue); }
3091
+
3092
+ if (slotValue->header->type == MULTIFIELD_TYPE)
3093
+ { theFM->fmValueArray[whichSlot].multifieldValue = CopyMultifield(theFM->fmEnv,slotValue->multifieldValue); }
3094
+ else
3095
+ { theFM->fmValueArray[whichSlot].value = slotValue->value; }
3096
+
3097
+ Retain(theFM->fmEnv,theFM->fmValueArray[whichSlot].header);
3098
+
3099
+ return PSE_NO_ERROR;
3100
+ }
3101
+
3102
+ /*************/
3103
+ /* FMModify: */
3104
+ /*************/
3105
+ Fact *FMModify(
3106
+ FactModifier *theFM)
3107
+ {
3108
+ Environment *theEnv;
3109
+ Fact *rv;
3110
+ GCBlock gcb;
3111
+ unsigned int i;
3112
+
3113
+ if (theFM == NULL)
3114
+ { return NULL; }
3115
+
3116
+ theEnv = theFM->fmEnv;
3117
+
3118
+ if (theFM->fmOldFact == NULL)
3119
+ {
3120
+ FactData(theEnv)->factModifierError = FME_NULL_POINTER_ERROR;
3121
+ return NULL;
3122
+ }
3123
+
3124
+ if (theFM->fmOldFact->garbage)
3125
+ {
3126
+ FactData(theEnv)->factModifierError = FME_RETRACTED_ERROR;
3127
+ return NULL;
3128
+ }
3129
+
3130
+ if (theFM->changeMap == NULL)
3131
+ { return theFM->fmOldFact; }
3132
+
3133
+ if (! BitStringHasBitsSet(theFM->changeMap,CountToBitMapSize(theFM->fmOldFact->whichDeftemplate->numberOfSlots)))
3134
+ { return theFM->fmOldFact; }
3135
+
3136
+ rv = ReplaceFact(theFM->fmEnv,theFM->fmOldFact,theFM->fmValueArray,theFM->changeMap);
3137
+
3138
+ if ((FactData(theEnv)->assertError == AE_RULE_NETWORK_ERROR) ||
3139
+ (FactData(theEnv)->retractError == RE_RULE_NETWORK_ERROR))
3140
+ { FactData(theEnv)->factModifierError = FME_RULE_NETWORK_ERROR; }
3141
+ else if ((FactData(theEnv)->retractError == RE_COULD_NOT_RETRACT_ERROR) ||
3142
+ (FactData(theEnv)->assertError == AE_COULD_NOT_ASSERT_ERROR))
3143
+ { FactData(theEnv)->factModifierError = FME_COULD_NOT_MODIFY_ERROR; }
3144
+ else
3145
+ { FactData(theEnv)->factModifierError = FME_NO_ERROR; }
3146
+
3147
+ GCBlockStart(theEnv,&gcb);
3148
+
3149
+ for (i = 0; i < theFM->fmOldFact->whichDeftemplate->numberOfSlots; i++)
3150
+ {
3151
+ Release(theEnv,theFM->fmValueArray[i].header);
3152
+ theFM->fmValueArray[i].voidValue = theFM->fmEnv->VoidConstant;
3153
+ }
3154
+
3155
+ ClearBitString((void *) theFM->changeMap,CountToBitMapSize(theFM->fmOldFact->whichDeftemplate->numberOfSlots));
3156
+
3157
+ GCBlockEnd(theEnv,&gcb);
3158
+
3159
+ if ((rv != NULL) && (rv != theFM->fmOldFact))
3160
+ {
3161
+ ReleaseFact(theFM->fmOldFact);
3162
+ theFM->fmOldFact = rv;
3163
+ RetainFact(theFM->fmOldFact);
3164
+ }
3165
+
3166
+ return rv;
3167
+ }
3168
+
3169
+ /**************/
3170
+ /* FMDispose: */
3171
+ /**************/
3172
+ void FMDispose(
3173
+ FactModifier *theFM)
3174
+ {
3175
+ GCBlock gcb;
3176
+ Environment *theEnv = theFM->fmEnv;
3177
+ int i;
3178
+
3179
+ GCBlockStart(theEnv,&gcb);
3180
+
3181
+ /*========================*/
3182
+ /* Clear the value array. */
3183
+ /*========================*/
3184
+
3185
+ if (theFM->fmOldFact != NULL)
3186
+ {
3187
+ for (i = 0; i < theFM->fmOldFact->whichDeftemplate->numberOfSlots; i++)
3188
+ {
3189
+ Release(theEnv,theFM->fmValueArray[i].header);
3190
+
3191
+ if (theFM->fmValueArray[i].header->type == MULTIFIELD_TYPE)
3192
+ { ReturnMultifield(theEnv,theFM->fmValueArray[i].multifieldValue); }
3193
+ }
3194
+ }
3195
+
3196
+ /*=====================================*/
3197
+ /* Return the value and change arrays. */
3198
+ /*=====================================*/
3199
+
3200
+ if (theFM->fmValueArray != NULL)
3201
+ { rm(theEnv,theFM->fmValueArray,sizeof(CLIPSValue) * theFM->fmOldFact->whichDeftemplate->numberOfSlots); }
3202
+
3203
+ if (theFM->changeMap != NULL)
3204
+ { rm(theEnv,(void *) theFM->changeMap,CountToBitMapSize(theFM->fmOldFact->whichDeftemplate->numberOfSlots)); }
3205
+
3206
+ /*====================================*/
3207
+ /* Return the FactModifier structure. */
3208
+ /*====================================*/
3209
+
3210
+ if (theFM->fmOldFact != NULL)
3211
+ { ReleaseFact(theFM->fmOldFact); }
3212
+
3213
+ rtn_struct(theEnv,factModifier,theFM);
3214
+
3215
+ GCBlockEnd(theEnv,&gcb);
3216
+ }
3217
+
3218
+ /************/
3219
+ /* FMAbort: */
3220
+ /************/
3221
+ void FMAbort(
3222
+ FactModifier *theFM)
3223
+ {
3224
+ GCBlock gcb;
3225
+ Environment *theEnv;
3226
+ unsigned int i;
3227
+
3228
+ if (theFM == NULL) return;
3229
+
3230
+ if (theFM->fmOldFact == NULL) return;
3231
+
3232
+ theEnv = theFM->fmEnv;
3233
+
3234
+ GCBlockStart(theEnv,&gcb);
3235
+
3236
+ for (i = 0; i < theFM->fmOldFact->whichDeftemplate->numberOfSlots; i++)
3237
+ {
3238
+ Release(theEnv,theFM->fmValueArray[i].header);
3239
+
3240
+ if (theFM->fmValueArray[i].header->type == MULTIFIELD_TYPE)
3241
+ { ReturnMultifield(theEnv,theFM->fmValueArray[i].multifieldValue); }
3242
+
3243
+ theFM->fmValueArray[i].voidValue = theFM->fmEnv->VoidConstant;
3244
+ }
3245
+
3246
+ if (theFM->changeMap != NULL)
3247
+ { ClearBitString((void *) theFM->changeMap,CountToBitMapSize(theFM->fmOldFact->whichDeftemplate->numberOfSlots)); }
3248
+
3249
+ GCBlockEnd(theEnv,&gcb);
3250
+ }
3251
+
3252
+ /**************/
3253
+ /* FMSetFact: */
3254
+ /**************/
3255
+ FactModifierError FMSetFact(
3256
+ FactModifier *theFM,
3257
+ Fact *oldFact)
3258
+ {
3259
+ Environment *theEnv;
3260
+ unsigned short currentSlotCount, newSlotCount;
3261
+ unsigned int i;
3262
+
3263
+ if (theFM == NULL)
3264
+ { return FME_NULL_POINTER_ERROR; }
3265
+
3266
+ theEnv = theFM->fmEnv;
3267
+
3268
+ /*=================================================*/
3269
+ /* Modifiers can only be created for non-retracted */
3270
+ /* deftemplate facts with at least one slot. */
3271
+ /*=================================================*/
3272
+
3273
+ if (oldFact != NULL)
3274
+ {
3275
+ if (oldFact->garbage)
3276
+ {
3277
+ FactData(theEnv)->factModifierError = FME_RETRACTED_ERROR;
3278
+ return FME_RETRACTED_ERROR;
3279
+ }
3280
+
3281
+ if (oldFact->whichDeftemplate->implied)
3282
+ {
3283
+ FactData(theEnv)->factModifierError = FME_IMPLIED_DEFTEMPLATE_ERROR;
3284
+ return FME_IMPLIED_DEFTEMPLATE_ERROR;
3285
+ }
3286
+ }
3287
+
3288
+ /*========================*/
3289
+ /* Clear the value array. */
3290
+ /*========================*/
3291
+
3292
+ if (theFM->fmValueArray != NULL)
3293
+ {
3294
+ for (i = 0; i < theFM->fmOldFact->whichDeftemplate->numberOfSlots; i++)
3295
+ {
3296
+ Release(theEnv,theFM->fmValueArray[i].header);
3297
+
3298
+ if (theFM->fmValueArray[i].header->type == MULTIFIELD_TYPE)
3299
+ { ReturnMultifield(theEnv,theFM->fmValueArray[i].multifieldValue); }
3300
+ }
3301
+ }
3302
+
3303
+ /*==================================================*/
3304
+ /* Resize the value and change arrays if necessary. */
3305
+ /*==================================================*/
3306
+
3307
+ if (theFM->fmOldFact == NULL)
3308
+ { currentSlotCount = 0; }
3309
+ else
3310
+ { currentSlotCount = theFM->fmOldFact->whichDeftemplate->numberOfSlots; }
3311
+
3312
+ if (oldFact == NULL)
3313
+ { newSlotCount = 0; }
3314
+ else
3315
+ { newSlotCount = oldFact->whichDeftemplate->numberOfSlots; }
3316
+
3317
+ if (newSlotCount != currentSlotCount)
3318
+ {
3319
+ if (theFM->fmValueArray != NULL)
3320
+ { rm(theEnv,theFM->fmValueArray,sizeof(CLIPSValue) * currentSlotCount); }
3321
+
3322
+ if (theFM->changeMap != NULL)
3323
+ { rm(theEnv,(void *) theFM->changeMap,currentSlotCount); }
3324
+
3325
+ if (newSlotCount == 0)
3326
+ {
3327
+ theFM->fmValueArray = NULL;
3328
+ theFM->changeMap = NULL;
3329
+ }
3330
+ else
3331
+ {
3332
+ theFM->fmValueArray = (CLIPSValue *) gm2(theEnv,sizeof(CLIPSValue) * newSlotCount);
3333
+ theFM->changeMap = (char *) gm2(theEnv,CountToBitMapSize(newSlotCount));
3334
+ }
3335
+ }
3336
+
3337
+ /*=================================*/
3338
+ /* Update the fact being modified. */
3339
+ /*=================================*/
3340
+
3341
+ RetainFact(oldFact);
3342
+ ReleaseFact(theFM->fmOldFact);
3343
+ theFM->fmOldFact = oldFact;
3344
+
3345
+ /*=========================================*/
3346
+ /* Initialize the value and change arrays. */
3347
+ /*=========================================*/
3348
+
3349
+ for (i = 0; i < newSlotCount; i++)
3350
+ { theFM->fmValueArray[i].voidValue = theFM->fmEnv->VoidConstant; }
3351
+
3352
+ if (newSlotCount != 0)
3353
+ { ClearBitString((void *) theFM->changeMap,CountToBitMapSize(newSlotCount)); }
3354
+
3355
+ /*================================================================*/
3356
+ /* Return true to indicate the modifier was successfully created. */
3357
+ /*================================================================*/
3358
+
3359
+ FactData(theEnv)->factModifierError = FME_NO_ERROR;
3360
+ return FME_NO_ERROR;
3361
+ }
3362
+
3363
+ /************/
3364
+ /* FMError: */
3365
+ /************/
3366
+ FactModifierError FMError(
3367
+ Environment *theEnv)
3368
+ {
3369
+ return FactData(theEnv)->factModifierError;
3370
+ }
3371
+
3372
+ #endif /* DEFTEMPLATE_CONSTRUCT && DEFRULE_CONSTRUCT */
3373
+