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,2477 @@
1
+ /*******************************************************/
2
+ /* "C" Language Integrated Production System */
3
+ /* */
4
+ /* CLIPS Version 6.41 12/04/22 */
5
+ /* */
6
+ /* DEFTEMPLATE FUNCTIONS MODULE */
7
+ /*******************************************************/
8
+
9
+ /*************************************************************/
10
+ /* Purpose: Implements the modify and duplicate functions. */
11
+ /* */
12
+ /* Principal Programmer(s): */
13
+ /* Gary D. Riley */
14
+ /* */
15
+ /* Contributing Programmer(s): */
16
+ /* */
17
+ /* Revision History: */
18
+ /* */
19
+ /* 6.23: Correction for FalseSymbol/TrueSymbol. DR0859 */
20
+ /* */
21
+ /* 6.24: Added deftemplate-slot-names, */
22
+ /* deftemplate-slot-default-value, */
23
+ /* deftemplate-slot-cardinality, */
24
+ /* deftemplate-slot-allowed-values, */
25
+ /* deftemplate-slot-range, */
26
+ /* deftemplate-slot-types, */
27
+ /* deftemplate-slot-multip, */
28
+ /* deftemplate-slot-singlep, */
29
+ /* deftemplate-slot-existp, and */
30
+ /* deftemplate-slot-defaultp functions. */
31
+ /* */
32
+ /* Renamed BOOLEAN macro type to intBool. */
33
+ /* */
34
+ /* 6.30: Support for deftemplate slot facets. */
35
+ /* */
36
+ /* Removed conditional code for unsupported */
37
+ /* compilers/operating systems (IBM_MCW and */
38
+ /* MAC_MCW). */
39
+ /* */
40
+ /* Added deftemplate-slot-facet-existp and */
41
+ /* deftemplate-slot-facet-value functions. */
42
+ /* */
43
+ /* Support for long long integers. */
44
+ /* */
45
+ /* Used gensprintf instead of sprintf. */
46
+ /* */
47
+ /* Support for modify callback function. */
48
+ /* */
49
+ /* Added additional argument to function */
50
+ /* CheckDeftemplateAndSlotArguments to specify */
51
+ /* the expected number of arguments. */
52
+ /* */
53
+ /* Added const qualifiers to remove C++ */
54
+ /* deprecation warnings. */
55
+ /* */
56
+ /* Converted API macros to function calls. */
57
+ /* */
58
+ /* Added code to prevent a clear command from */
59
+ /* being executed during fact assertions via */
60
+ /* Increment/DecrementClearReadyLocks API. */
61
+ /* */
62
+ /* 6.31: Error messages are now generated when modify */
63
+ /* and duplicate functions are given a retracted */
64
+ /* fact. */
65
+ /* */
66
+ /* 6.40: Added Env prefix to GetEvaluationError and */
67
+ /* SetEvaluationError functions. */
68
+ /* */
69
+ /* Pragma once and other inclusion changes. */
70
+ /* */
71
+ /* Added support for booleans with <stdbool.h>. */
72
+ /* */
73
+ /* Removed use of void pointers for specific */
74
+ /* data structures. */
75
+ /* */
76
+ /* ALLOW_ENVIRONMENT_GLOBALS no longer supported. */
77
+ /* */
78
+ /* Callbacks must be environment aware. */
79
+ /* */
80
+ /* UDF redesign. */
81
+ /* */
82
+ /* Eval support for run time and bload only. */
83
+ /* */
84
+ /* Watch facts for modify command only prints */
85
+ /* changed slots. */
86
+ /* */
87
+ /* Modify command preserves fact id and address. */
88
+ /* */
89
+ /* Assert returns duplicate fact. FALSE is now */
90
+ /* returned only if an error occurs. */
91
+ /* */
92
+ /* For the modify command, specifying the fact */
93
+ /* using a fact-index is no longer limited to */
94
+ /* top-level commands. */
95
+ /* */
96
+ /* 6.41: Added error message for using ordered facts */
97
+ /* with functions expecting deftemplate facts. */
98
+ /* */
99
+ /* Used gensnprintf in place of gensprintf and. */
100
+ /* sprintf. */
101
+ /* */
102
+ /*************************************************************/
103
+
104
+ #include "setup.h"
105
+
106
+ #if DEFTEMPLATE_CONSTRUCT
107
+
108
+ #include <stdio.h>
109
+ #include <string.h>
110
+
111
+ #include "argacces.h"
112
+ #include "commline.h"
113
+ #include "constant.h"
114
+ #include "cstrnchk.h"
115
+ #include "default.h"
116
+ #include "envrnmnt.h"
117
+ #include "exprnpsr.h"
118
+ #include "factmngr.h"
119
+ #include "factrhs.h"
120
+ #include "memalloc.h"
121
+ #include "modulutl.h"
122
+ #include "multifld.h"
123
+ #include "pprint.h"
124
+ #include "prcdrpsr.h"
125
+ #include "prntutil.h"
126
+ #include "reorder.h"
127
+ #include "router.h"
128
+ #include "scanner.h"
129
+ #include "symbol.h"
130
+ #include "sysdep.h"
131
+ #include "tmpltdef.h"
132
+ #include "tmpltlhs.h"
133
+ #include "tmpltrhs.h"
134
+ #include "tmpltutl.h"
135
+ #include "utility.h"
136
+
137
+ #include "tmpltfun.h"
138
+
139
+ /***************************************/
140
+ /* LOCAL INTERNAL FUNCTION DEFINITIONS */
141
+ /***************************************/
142
+
143
+ static CLIPSLexeme *CheckDeftemplateAndSlotArguments(UDFContext *,Deftemplate **);
144
+ static void FreeTemplateValueArray(Environment *,CLIPSValue *,Deftemplate *);
145
+ static struct expr *ModAndDupParse(Environment *,struct expr *,const char *,const char *);
146
+ #if (! RUN_TIME) && (! BLOAD_ONLY)
147
+ static CLIPSLexeme *FindTemplateForFactAddress(CLIPSLexeme *,struct lhsParseNode *);
148
+ #endif
149
+
150
+ /****************************************************************/
151
+ /* DeftemplateFunctions: Initializes the deftemplate functions. */
152
+ /****************************************************************/
153
+ void DeftemplateFunctions(
154
+ Environment *theEnv)
155
+ {
156
+ #if ! RUN_TIME
157
+ AddUDF(theEnv,"modify","bf",0,UNBOUNDED,"*;lf",ModifyCommand,"ModifyCommand",NULL);
158
+ AddUDF(theEnv,"duplicate","bf",0,UNBOUNDED,"*;lf",DuplicateCommand,"DuplicateCommand",NULL);
159
+
160
+ AddUDF(theEnv,"deftemplate-slot-names","bm",1,1,"y",DeftemplateSlotNamesFunction,"DeftemplateSlotNamesFunction",NULL);
161
+ AddUDF(theEnv,"deftemplate-slot-default-value","*",2,2,"y",DeftemplateSlotDefaultValueFunction,"DeftemplateSlotDefaultValueFunction",NULL);
162
+ AddUDF(theEnv,"deftemplate-slot-cardinality","*",2,2,"y",DeftemplateSlotCardinalityFunction,"DeftemplateSlotCardinalityFunction",NULL);
163
+ AddUDF(theEnv,"deftemplate-slot-allowed-values","*",2,2,"y",DeftemplateSlotAllowedValuesFunction,"DeftemplateSlotAllowedValuesFunction",NULL);
164
+ AddUDF(theEnv,"deftemplate-slot-range","*",2,2,"y",DeftemplateSlotRangeFunction,"DeftemplateSlotRangeFunction",NULL);
165
+ AddUDF(theEnv,"deftemplate-slot-types","*",2,2,"y",DeftemplateSlotTypesFunction,"DeftemplateSlotTypesFunction",NULL);
166
+
167
+ AddUDF(theEnv,"deftemplate-slot-multip","b",2,2,"y",DeftemplateSlotMultiPFunction,"DeftemplateSlotMultiPFunction",NULL);
168
+ AddUDF(theEnv,"deftemplate-slot-singlep","b",2,2,"y",DeftemplateSlotSinglePFunction,"DeftemplateSlotSinglePFunction",NULL);
169
+ AddUDF(theEnv,"deftemplate-slot-existp","b",2,2,"y",DeftemplateSlotExistPFunction,"DeftemplateSlotExistPFunction",NULL);
170
+ AddUDF(theEnv,"deftemplate-slot-defaultp","y",2,2,"y",DeftemplateSlotDefaultPFunction,"DeftemplateSlotDefaultPFunction",NULL);
171
+
172
+ AddUDF(theEnv,"deftemplate-slot-facet-existp","b",3,3,"y",DeftemplateSlotFacetExistPFunction,"DeftemplateSlotFacetExistPFunction",NULL);
173
+
174
+ AddUDF(theEnv,"deftemplate-slot-facet-value","*",3,3,"y",DeftemplateSlotFacetValueFunction,"DeftemplateSlotFacetValueFunction",NULL);
175
+
176
+ FuncSeqOvlFlags(theEnv,"modify",false,false);
177
+ FuncSeqOvlFlags(theEnv,"duplicate",false,false);
178
+ #else
179
+ #if MAC_XCD
180
+ #pragma unused(theEnv)
181
+ #endif
182
+ #endif
183
+
184
+ AddFunctionParser(theEnv,"modify",ModifyParse);
185
+ AddFunctionParser(theEnv,"duplicate",DuplicateParse);
186
+ }
187
+
188
+ /***************************/
189
+ /* FreeTemplateValueArray: */
190
+ /***************************/
191
+ static void FreeTemplateValueArray(
192
+ Environment *theEnv,
193
+ CLIPSValue *theValueArray,
194
+ Deftemplate *templatePtr)
195
+ {
196
+ unsigned short i;
197
+
198
+ if (theValueArray == NULL) return;
199
+
200
+ for (i = 0; i < templatePtr->numberOfSlots; i++)
201
+ {
202
+ if (theValueArray[i].header->type == MULTIFIELD_TYPE)
203
+ { ReturnMultifield(theEnv,theValueArray[i].multifieldValue); }
204
+ }
205
+
206
+ rm(theEnv,theValueArray,sizeof(CLIPSValue) * templatePtr->numberOfSlots);
207
+ }
208
+
209
+ /*************************************************************/
210
+ /* ModifyCommand: H/L access routine for the modify command. */
211
+ /*************************************************************/
212
+ void ModifyCommand(
213
+ Environment *theEnv,
214
+ UDFContext *context,
215
+ UDFValue *returnValue)
216
+ {
217
+ long long factNum;
218
+ Fact *oldFact;
219
+ struct expr *testPtr;
220
+ UDFValue computeResult;
221
+ Deftemplate *templatePtr;
222
+ struct templateSlot *slotPtr;
223
+ size_t i;
224
+ long long position;
225
+ int replacementCount = 0;
226
+ bool found;
227
+ CLIPSValue *theValueArray;
228
+ char *changeMap;
229
+
230
+ /*===================================================*/
231
+ /* Set the default return value to the symbol FALSE. */
232
+ /*===================================================*/
233
+
234
+ returnValue->lexemeValue = FalseSymbol(theEnv);
235
+
236
+ /*==================================================*/
237
+ /* Evaluate the first argument which is used to get */
238
+ /* a pointer to the fact to be modified/duplicated. */
239
+ /*==================================================*/
240
+
241
+ testPtr = GetFirstArgument();
242
+ IncrementClearReadyLocks(theEnv);
243
+ EvaluateExpression(theEnv,testPtr,&computeResult);
244
+ DecrementClearReadyLocks(theEnv);
245
+
246
+ /*==============================================================*/
247
+ /* If an integer is supplied, then treat it as a fact-index and */
248
+ /* search the fact-list for the fact with that fact-index. */
249
+ /*==============================================================*/
250
+
251
+ if (computeResult.header->type == INTEGER_TYPE)
252
+ {
253
+ factNum = computeResult.integerValue->contents;
254
+ if (factNum < 0)
255
+ {
256
+ ExpectedTypeError2(theEnv,"modify",1);
257
+ SetEvaluationError(theEnv,true);
258
+ return;
259
+ }
260
+
261
+ oldFact = GetNextFact(theEnv,NULL);
262
+ while (oldFact != NULL)
263
+ {
264
+ if (oldFact->factIndex == factNum)
265
+ { break; }
266
+ else
267
+ { oldFact = oldFact->nextFact; }
268
+ }
269
+
270
+ if (oldFact == NULL)
271
+ {
272
+ char tempBuffer[20];
273
+ gensnprintf(tempBuffer,sizeof(tempBuffer),"f-%lld",factNum);
274
+ CantFindItemErrorMessage(theEnv,"fact",tempBuffer,false);
275
+ return;
276
+ }
277
+ }
278
+
279
+ /*==========================================*/
280
+ /* Otherwise, if a pointer is supplied then */
281
+ /* no lookup is required. */
282
+ /*==========================================*/
283
+
284
+ else if (computeResult.header->type == FACT_ADDRESS_TYPE)
285
+ { oldFact = computeResult.factValue; }
286
+
287
+ /*===========================================*/
288
+ /* Otherwise, the first argument is invalid. */
289
+ /*===========================================*/
290
+
291
+ else
292
+ {
293
+ ExpectedTypeError2(theEnv,"modify",1);
294
+ SetEvaluationError(theEnv,true);
295
+ return;
296
+ }
297
+
298
+ /*=====================================*/
299
+ /* Retracted facts cannot be modified. */
300
+ /*=====================================*/
301
+
302
+ if (oldFact->garbage)
303
+ {
304
+ FactRetractedErrorMessage(theEnv,oldFact);
305
+ return;
306
+ }
307
+
308
+ /*==================================*/
309
+ /* See if it is a deftemplate fact. */
310
+ /*==================================*/
311
+
312
+ templatePtr = oldFact->whichDeftemplate;
313
+
314
+ if (templatePtr->implied)
315
+ {
316
+ OrderedFactFunctionError(theEnv,"modify");
317
+ SetEvaluationError(theEnv,true);
318
+ return;
319
+ }
320
+
321
+ /*========================================================*/
322
+ /* Create a data object array to hold the updated values. */
323
+ /*========================================================*/
324
+
325
+ if (templatePtr->numberOfSlots == 0)
326
+ {
327
+ theValueArray = NULL;
328
+ changeMap = NULL;
329
+ }
330
+ else
331
+ {
332
+ theValueArray = (CLIPSValue *) gm2(theEnv,sizeof(void *) * templatePtr->numberOfSlots);
333
+ changeMap = (char *) gm2(theEnv,CountToBitMapSize(templatePtr->numberOfSlots));
334
+ ClearBitString((void *) changeMap,CountToBitMapSize(templatePtr->numberOfSlots));
335
+ }
336
+
337
+ /*================================================================*/
338
+ /* Duplicate the values from the old fact (skipping multifields). */
339
+ /*================================================================*/
340
+
341
+ for (i = 0; i < oldFact->theProposition.length; i++)
342
+ { theValueArray[i].voidValue = VoidConstant(theEnv); }
343
+
344
+ /*========================*/
345
+ /* Start replacing slots. */
346
+ /*========================*/
347
+
348
+ testPtr = testPtr->nextArg;
349
+ while (testPtr != NULL)
350
+ {
351
+ /*============================================================*/
352
+ /* If the slot identifier is an integer, then the slot was */
353
+ /* previously identified and its position within the template */
354
+ /* was stored. Otherwise, the position of the slot within the */
355
+ /* deftemplate has to be determined by comparing the name of */
356
+ /* the slot against the list of slots for the deftemplate. */
357
+ /*============================================================*/
358
+
359
+ if (testPtr->type == INTEGER_TYPE)
360
+ { position = testPtr->integerValue->contents; }
361
+ else
362
+ {
363
+ found = false;
364
+ position = 0;
365
+ slotPtr = templatePtr->slotList;
366
+ while (slotPtr != NULL)
367
+ {
368
+ if (slotPtr->slotName == testPtr->lexemeValue)
369
+ {
370
+ found = true;
371
+ slotPtr = NULL;
372
+ }
373
+ else
374
+ {
375
+ slotPtr = slotPtr->next;
376
+ position++;
377
+ }
378
+ }
379
+
380
+ if (! found)
381
+ {
382
+ InvalidDeftemplateSlotMessage(theEnv,testPtr->lexemeValue->contents,
383
+ templatePtr->header.name->contents,true);
384
+ SetEvaluationError(theEnv,true);
385
+ FreeTemplateValueArray(theEnv,theValueArray,templatePtr);
386
+ if (changeMap != NULL)
387
+ { rm(theEnv,(void *) changeMap,CountToBitMapSize(templatePtr->numberOfSlots)); }
388
+ return;
389
+ }
390
+ }
391
+
392
+ /*===================================================*/
393
+ /* If a single field slot is being replaced, then... */
394
+ /*===================================================*/
395
+
396
+ if (oldFact->theProposition.contents[position].header->type != MULTIFIELD_TYPE)
397
+ {
398
+ /*======================================================*/
399
+ /* If the list of values to store in the slot is empty */
400
+ /* or contains more than one member than an error has */
401
+ /* occured because a single field slot can only contain */
402
+ /* a single value. */
403
+ /*======================================================*/
404
+
405
+ if ((testPtr->argList == NULL) ? true : (testPtr->argList->nextArg != NULL))
406
+ {
407
+ MultiIntoSingleFieldSlotError(theEnv,GetNthSlot(templatePtr,position),templatePtr);
408
+ FreeTemplateValueArray(theEnv,theValueArray,templatePtr);
409
+ if (changeMap != NULL)
410
+ { rm(theEnv,(void *) changeMap,CountToBitMapSize(templatePtr->numberOfSlots)); }
411
+ return;
412
+ }
413
+
414
+ /*===================================================*/
415
+ /* Evaluate the expression to be stored in the slot. */
416
+ /*===================================================*/
417
+
418
+ IncrementClearReadyLocks(theEnv);
419
+ EvaluateExpression(theEnv,testPtr->argList,&computeResult);
420
+ SetEvaluationError(theEnv,false);
421
+ DecrementClearReadyLocks(theEnv);
422
+
423
+ /*====================================================*/
424
+ /* If the expression evaluated to a multifield value, */
425
+ /* then an error occured since a multifield value can */
426
+ /* not be stored in a single field slot. */
427
+ /*====================================================*/
428
+
429
+ if (computeResult.header->type == MULTIFIELD_TYPE)
430
+ {
431
+ MultiIntoSingleFieldSlotError(theEnv,GetNthSlot(templatePtr,position),templatePtr);
432
+ FreeTemplateValueArray(theEnv,theValueArray,templatePtr);
433
+ if (changeMap != NULL)
434
+ { rm(theEnv,(void *) changeMap,CountToBitMapSize(templatePtr->numberOfSlots)); }
435
+ return;
436
+ }
437
+
438
+ /*=============================*/
439
+ /* Store the value in the slot */
440
+ /*=============================*/
441
+
442
+ if (oldFact->theProposition.contents[position].value != computeResult.value)
443
+ {
444
+ replacementCount++;
445
+ theValueArray[position].value = computeResult.value;
446
+ if (changeMap != NULL)
447
+ { SetBitMap(changeMap,position); }
448
+ }
449
+ }
450
+
451
+ /*=================================*/
452
+ /* Else replace a multifield slot. */
453
+ /*=================================*/
454
+
455
+ else
456
+ {
457
+ /*======================================*/
458
+ /* Determine the new value of the slot. */
459
+ /*======================================*/
460
+
461
+ IncrementClearReadyLocks(theEnv);
462
+ StoreInMultifield(theEnv,&computeResult,testPtr->argList,false);
463
+ SetEvaluationError(theEnv,false);
464
+ DecrementClearReadyLocks(theEnv);
465
+
466
+ /*=============================*/
467
+ /* Store the value in the slot */
468
+ /*=============================*/
469
+
470
+ if ((oldFact->theProposition.contents[position].header->type != computeResult.header->type) ||
471
+ (! MultifieldsEqual((Multifield *) oldFact->theProposition.contents[position].value,(Multifield *) computeResult.value)))
472
+ {
473
+ theValueArray[position].value = computeResult.value;
474
+ replacementCount++;
475
+ if (changeMap != NULL)
476
+ { SetBitMap(changeMap,position); }
477
+ }
478
+ else
479
+ { ReturnMultifield(theEnv,computeResult.multifieldValue); }
480
+ }
481
+
482
+ testPtr = testPtr->nextArg;
483
+ }
484
+
485
+ /*==================================*/
486
+ /* If no slots have changed, then a */
487
+ /* retract/assert is not performed. */
488
+ /*==================================*/
489
+
490
+ if (replacementCount == 0)
491
+ {
492
+ if (theValueArray != NULL)
493
+ { rm(theEnv,theValueArray,sizeof(void *) * templatePtr->numberOfSlots); }
494
+ if (changeMap != NULL)
495
+ { rm(theEnv,(void *) changeMap,CountToBitMapSize(templatePtr->numberOfSlots)); }
496
+
497
+ returnValue->value = oldFact;
498
+ return;
499
+ }
500
+
501
+ /*=========================================*/
502
+ /* Replace the old values with the values. */
503
+ /*=========================================*/
504
+
505
+ if ((oldFact = ReplaceFact(theEnv,oldFact,theValueArray,changeMap)) != NULL)
506
+ { returnValue->factValue = oldFact; }
507
+
508
+ /*=============================*/
509
+ /* Free the data object array. */
510
+ /*=============================*/
511
+
512
+ if (theValueArray != NULL)
513
+ { rm(theEnv,theValueArray,sizeof(void *) * templatePtr->numberOfSlots); }
514
+
515
+ if (changeMap != NULL)
516
+ { rm(theEnv,(void *) changeMap,CountToBitMapSize(templatePtr->numberOfSlots)); }
517
+
518
+ return;
519
+ }
520
+
521
+ /****************/
522
+ /* ReplaceFact: */
523
+ /****************/
524
+ Fact *ReplaceFact(
525
+ Environment *theEnv,
526
+ Fact *oldFact,
527
+ CLIPSValue *theValueArray,
528
+ char *changeMap)
529
+ {
530
+ size_t i;
531
+ Fact *theFact;
532
+ Fact *factListPosition, *templatePosition;
533
+
534
+ /*===============================================*/
535
+ /* Call registered modify notification functions */
536
+ /* for the existing version of the fact. */
537
+ /*===============================================*/
538
+
539
+ if (FactData(theEnv)->ListOfModifyFunctions != NULL)
540
+ {
541
+ ModifyCallFunctionItem *theModifyFunction;
542
+
543
+ for (theModifyFunction = FactData(theEnv)->ListOfModifyFunctions;
544
+ theModifyFunction != NULL;
545
+ theModifyFunction = theModifyFunction->next)
546
+ {
547
+ (*theModifyFunction->func)(theEnv,oldFact,NULL,theModifyFunction->context);
548
+ }
549
+ }
550
+
551
+ /*==========================================*/
552
+ /* Remember the position of the fact before */
553
+ /* it is retracted so this can be restored */
554
+ /* when the modified fact is asserted. */
555
+ /*==========================================*/
556
+
557
+ factListPosition = oldFact->previousFact;
558
+ templatePosition = oldFact->previousTemplateFact;
559
+
560
+ /*===================*/
561
+ /* Retract the fact. */
562
+ /*===================*/
563
+
564
+ RetractDriver(theEnv,oldFact,true,changeMap);
565
+ oldFact->garbage = false;
566
+
567
+ /*======================================*/
568
+ /* Copy the new values to the old fact. */
569
+ /*======================================*/
570
+
571
+ for (i = 0; i < oldFact->theProposition.length; i++)
572
+ {
573
+ if (theValueArray[i].voidValue != VoidConstant(theEnv))
574
+ {
575
+ AtomDeinstall(theEnv,oldFact->theProposition.contents[i].header->type,oldFact->theProposition.contents[i].value);
576
+
577
+ if (oldFact->theProposition.contents[i].header->type == MULTIFIELD_TYPE)
578
+ {
579
+ Multifield *theSegment = oldFact->theProposition.contents[i].multifieldValue;
580
+ if (theSegment->busyCount == 0)
581
+ { ReturnMultifield(theEnv,theSegment); }
582
+ else
583
+ { AddToMultifieldList(theEnv,theSegment); }
584
+ }
585
+
586
+ oldFact->theProposition.contents[i].value = theValueArray[i].value;
587
+
588
+ AtomInstall(theEnv,oldFact->theProposition.contents[i].header->type,oldFact->theProposition.contents[i].value);
589
+ }
590
+ }
591
+
592
+ /*======================*/
593
+ /* Assert the new fact. */
594
+ /*======================*/
595
+
596
+ theFact = AssertDriver(oldFact,oldFact->factIndex,factListPosition,templatePosition,changeMap);
597
+
598
+ /*===============================================*/
599
+ /* Call registered modify notification functions */
600
+ /* for the new version of the fact. */
601
+ /*===============================================*/
602
+
603
+ if (FactData(theEnv)->ListOfModifyFunctions != NULL)
604
+ {
605
+ ModifyCallFunctionItem *theModifyFunction;
606
+
607
+ for (theModifyFunction = FactData(theEnv)->ListOfModifyFunctions;
608
+ theModifyFunction != NULL;
609
+ theModifyFunction = theModifyFunction->next)
610
+ {
611
+ (*theModifyFunction->func)(theEnv,NULL,theFact,theModifyFunction->context);
612
+ }
613
+ }
614
+
615
+ return theFact;
616
+ }
617
+
618
+ /*******************************************************************/
619
+ /* DuplicateCommand: H/L access routine for the duplicate command. */
620
+ /*******************************************************************/
621
+ void DuplicateCommand(
622
+ Environment *theEnv,
623
+ UDFContext *context,
624
+ UDFValue *returnValue)
625
+ {
626
+ long long factNum;
627
+ Fact *oldFact, *newFact, *theFact;
628
+ struct expr *testPtr;
629
+ UDFValue computeResult;
630
+ Deftemplate *templatePtr;
631
+ struct templateSlot *slotPtr;
632
+ size_t i;
633
+ long long position;
634
+ bool found;
635
+
636
+ /*===================================================*/
637
+ /* Set the default return value to the symbol FALSE. */
638
+ /*===================================================*/
639
+
640
+ returnValue->lexemeValue = FalseSymbol(theEnv);
641
+
642
+ /*==================================================*/
643
+ /* Evaluate the first argument which is used to get */
644
+ /* a pointer to the fact to be modified/duplicated. */
645
+ /*==================================================*/
646
+
647
+ testPtr = GetFirstArgument();
648
+ IncrementClearReadyLocks(theEnv);
649
+ EvaluateExpression(theEnv,testPtr,&computeResult);
650
+ DecrementClearReadyLocks(theEnv);
651
+
652
+ /*==============================================================*/
653
+ /* If an integer is supplied, then treat it as a fact-index and */
654
+ /* search the fact-list for the fact with that fact-index. */
655
+ /*==============================================================*/
656
+
657
+ if (computeResult.header->type == INTEGER_TYPE)
658
+ {
659
+ factNum = computeResult.integerValue->contents;
660
+ if (factNum < 0)
661
+ {
662
+ ExpectedTypeError2(theEnv,"duplicate",1);
663
+ SetEvaluationError(theEnv,true);
664
+ return;
665
+ }
666
+
667
+ oldFact = GetNextFact(theEnv,NULL);
668
+ while (oldFact != NULL)
669
+ {
670
+ if (oldFact->factIndex == factNum)
671
+ { break; }
672
+ else
673
+ { oldFact = oldFact->nextFact; }
674
+ }
675
+
676
+ if (oldFact == NULL)
677
+ {
678
+ char tempBuffer[20];
679
+ gensnprintf(tempBuffer,sizeof(tempBuffer),"f-%lld",factNum);
680
+ CantFindItemErrorMessage(theEnv,"fact",tempBuffer,false);
681
+ return;
682
+ }
683
+ }
684
+
685
+ /*==========================================*/
686
+ /* Otherwise, if a pointer is supplied then */
687
+ /* no lookup is required. */
688
+ /*==========================================*/
689
+
690
+ else if (computeResult.header->type == FACT_ADDRESS_TYPE)
691
+ { oldFact = computeResult.factValue; }
692
+
693
+ /*===========================================*/
694
+ /* Otherwise, the first argument is invalid. */
695
+ /*===========================================*/
696
+
697
+ else
698
+ {
699
+ ExpectedTypeError2(theEnv,"duplicate",1);
700
+ SetEvaluationError(theEnv,true);
701
+ return;
702
+ }
703
+
704
+ /*=======================================*/
705
+ /* Retracted facts cannot be duplicated. */
706
+ /*=======================================*/
707
+
708
+ if (oldFact->garbage)
709
+ {
710
+ FactRetractedErrorMessage(theEnv,oldFact);
711
+ return;
712
+ }
713
+
714
+ /*==================================*/
715
+ /* See if it is a deftemplate fact. */
716
+ /*==================================*/
717
+
718
+ templatePtr = oldFact->whichDeftemplate;
719
+
720
+ if (templatePtr->implied)
721
+ {
722
+ OrderedFactFunctionError(theEnv,"duplicate");
723
+ SetEvaluationError(theEnv,true);
724
+ return;
725
+ }
726
+
727
+ /*================================================================*/
728
+ /* Duplicate the values from the old fact (skipping multifields). */
729
+ /*================================================================*/
730
+
731
+ newFact = CreateFactBySize(theEnv,oldFact->theProposition.length);
732
+ newFact->whichDeftemplate = templatePtr;
733
+ for (i = 0; i < oldFact->theProposition.length; i++)
734
+ {
735
+ if (oldFact->theProposition.contents[i].header->type != MULTIFIELD_TYPE)
736
+ { newFact->theProposition.contents[i].value = oldFact->theProposition.contents[i].value; }
737
+ else
738
+ { newFact->theProposition.contents[i].value = NULL; }
739
+ }
740
+
741
+ /*========================*/
742
+ /* Start replacing slots. */
743
+ /*========================*/
744
+
745
+ testPtr = testPtr->nextArg;
746
+ while (testPtr != NULL)
747
+ {
748
+ /*============================================================*/
749
+ /* If the slot identifier is an integer, then the slot was */
750
+ /* previously identified and its position within the template */
751
+ /* was stored. Otherwise, the position of the slot within the */
752
+ /* deftemplate has to be determined by comparing the name of */
753
+ /* the slot against the list of slots for the deftemplate. */
754
+ /*============================================================*/
755
+
756
+ if (testPtr->type == INTEGER_TYPE)
757
+ { position = testPtr->integerValue->contents; }
758
+ else
759
+ {
760
+ found = false;
761
+ position = 0;
762
+ slotPtr = templatePtr->slotList;
763
+ while (slotPtr != NULL)
764
+ {
765
+ if (slotPtr->slotName == testPtr->lexemeValue)
766
+ {
767
+ found = true;
768
+ slotPtr = NULL;
769
+ }
770
+ else
771
+ {
772
+ slotPtr = slotPtr->next;
773
+ position++;
774
+ }
775
+ }
776
+
777
+ if (! found)
778
+ {
779
+ InvalidDeftemplateSlotMessage(theEnv,testPtr->lexemeValue->contents,
780
+ templatePtr->header.name->contents,true);
781
+ SetEvaluationError(theEnv,true);
782
+ ReturnFact(theEnv,newFact);
783
+ return;
784
+ }
785
+ }
786
+
787
+ /*===================================================*/
788
+ /* If a single field slot is being replaced, then... */
789
+ /*===================================================*/
790
+
791
+ if (newFact->theProposition.contents[position].value != NULL)
792
+ {
793
+ /*======================================================*/
794
+ /* If the list of values to store in the slot is empty */
795
+ /* or contains more than one member than an error has */
796
+ /* occured because a single field slot can only contain */
797
+ /* a single value. */
798
+ /*======================================================*/
799
+
800
+ if ((testPtr->argList == NULL) ? true : (testPtr->argList->nextArg != NULL))
801
+ {
802
+ MultiIntoSingleFieldSlotError(theEnv,GetNthSlot(templatePtr,position),templatePtr);
803
+ ReturnFact(theEnv,newFact);
804
+ return;
805
+ }
806
+
807
+ /*===================================================*/
808
+ /* Evaluate the expression to be stored in the slot. */
809
+ /*===================================================*/
810
+
811
+ IncrementClearReadyLocks(theEnv);
812
+ EvaluateExpression(theEnv,testPtr->argList,&computeResult);
813
+ SetEvaluationError(theEnv,false);
814
+ DecrementClearReadyLocks(theEnv);
815
+
816
+ /*====================================================*/
817
+ /* If the expression evaluated to a multifield value, */
818
+ /* then an error occured since a multifield value can */
819
+ /* not be stored in a single field slot. */
820
+ /*====================================================*/
821
+
822
+ if (computeResult.header->type == MULTIFIELD_TYPE)
823
+ {
824
+ ReturnFact(theEnv,newFact);
825
+ MultiIntoSingleFieldSlotError(theEnv,GetNthSlot(templatePtr,position),templatePtr);
826
+ return;
827
+ }
828
+
829
+ /*=============================*/
830
+ /* Store the value in the slot */
831
+ /*=============================*/
832
+
833
+ newFact->theProposition.contents[position].value = computeResult.value;
834
+ }
835
+
836
+ /*=================================*/
837
+ /* Else replace a multifield slot. */
838
+ /*=================================*/
839
+
840
+ else
841
+ {
842
+ /*======================================*/
843
+ /* Determine the new value of the slot. */
844
+ /*======================================*/
845
+
846
+ IncrementClearReadyLocks(theEnv);
847
+ StoreInMultifield(theEnv,&computeResult,testPtr->argList,false);
848
+ SetEvaluationError(theEnv,false);
849
+ DecrementClearReadyLocks(theEnv);
850
+
851
+ /*=============================*/
852
+ /* Store the value in the slot */
853
+ /*=============================*/
854
+
855
+ newFact->theProposition.contents[position].value = computeResult.value;
856
+ }
857
+
858
+ testPtr = testPtr->nextArg;
859
+ }
860
+
861
+ /*=====================================*/
862
+ /* Copy the multifield values from the */
863
+ /* old fact that were not replaced. */
864
+ /*=====================================*/
865
+
866
+ for (i = 0; i < oldFact->theProposition.length; i++)
867
+ {
868
+ if ((oldFact->theProposition.contents[i].header->type == MULTIFIELD_TYPE) &&
869
+ (newFact->theProposition.contents[i].value == NULL))
870
+
871
+ {
872
+ newFact->theProposition.contents[i].value =
873
+ CopyMultifield(theEnv,oldFact->theProposition.contents[i].multifieldValue);
874
+ }
875
+ }
876
+
877
+ /*===============================*/
878
+ /* Perform the duplicate action. */
879
+ /*===============================*/
880
+
881
+ theFact = AssertDriver(newFact,0,NULL,NULL,NULL);
882
+
883
+ /*========================================*/
884
+ /* The asserted fact is the return value. */
885
+ /*========================================*/
886
+
887
+ if (theFact != NULL)
888
+ {
889
+ returnValue->begin = 0;
890
+ returnValue->range = theFact->theProposition.length;
891
+ returnValue->value = theFact;
892
+ }
893
+
894
+ return;
895
+ }
896
+
897
+ /****************************************************/
898
+ /* DeftemplateSlotNamesFunction: H/L access routine */
899
+ /* for the deftemplate-slot-names function. */
900
+ /****************************************************/
901
+ void DeftemplateSlotNamesFunction(
902
+ Environment *theEnv,
903
+ UDFContext *context,
904
+ UDFValue *returnValue)
905
+ {
906
+ const char *deftemplateName;
907
+ Deftemplate *theDeftemplate;
908
+ CLIPSValue cv;
909
+
910
+ /*=============================================*/
911
+ /* Set up the default return value for errors. */
912
+ /*=============================================*/
913
+
914
+ returnValue->value = FalseSymbol(theEnv);
915
+
916
+ /*=======================================*/
917
+ /* Get the reference to the deftemplate. */
918
+ /*=======================================*/
919
+
920
+ deftemplateName = GetConstructName(context,"deftemplate-slot-names","deftemplate name");
921
+ if (deftemplateName == NULL) return;
922
+
923
+ theDeftemplate = FindDeftemplate(theEnv,deftemplateName);
924
+ if (theDeftemplate == NULL)
925
+ {
926
+ CantFindItemErrorMessage(theEnv,"deftemplate",deftemplateName,true);
927
+ return;
928
+ }
929
+
930
+ /*=====================*/
931
+ /* Get the slot names. */
932
+ /*=====================*/
933
+
934
+ DeftemplateSlotNames(theDeftemplate,&cv);
935
+ CLIPSToUDFValue(&cv,returnValue);
936
+ }
937
+
938
+ /**********************************************/
939
+ /* DeftemplateSlotNames: C access routine for */
940
+ /* the deftemplate-slot-names function. */
941
+ /**********************************************/
942
+ void DeftemplateSlotNames(
943
+ Deftemplate *theDeftemplate,
944
+ CLIPSValue *returnValue)
945
+ {
946
+ Multifield *theList;
947
+ struct templateSlot *theSlot;
948
+ unsigned long count;
949
+ Environment *theEnv = theDeftemplate->header.env;
950
+
951
+ /*===============================================*/
952
+ /* If we're dealing with an implied deftemplate, */
953
+ /* then the only slot names is "implied." */
954
+ /*===============================================*/
955
+
956
+ if (theDeftemplate->implied)
957
+ {
958
+ theList = CreateMultifield(theEnv,1);
959
+ theList->contents[0].lexemeValue = CreateSymbol(theEnv,"implied");
960
+ returnValue->value = theList;
961
+ return;
962
+ }
963
+
964
+ /*=================================*/
965
+ /* Count the number of slot names. */
966
+ /*=================================*/
967
+
968
+ for (count = 0, theSlot = theDeftemplate->slotList;
969
+ theSlot != NULL;
970
+ count++, theSlot = theSlot->next)
971
+ { /* Do Nothing */ }
972
+
973
+ /*=============================================================*/
974
+ /* Create a multifield value in which to store the slot names. */
975
+ /*=============================================================*/
976
+
977
+ theList = CreateMultifield(theEnv,count);
978
+ returnValue->value = theList;
979
+
980
+ /*===============================================*/
981
+ /* Store the slot names in the multifield value. */
982
+ /*===============================================*/
983
+
984
+ for (count = 0, theSlot = theDeftemplate->slotList;
985
+ theSlot != NULL;
986
+ count++, theSlot = theSlot->next)
987
+ {
988
+ theList->contents[count].lexemeValue = theSlot->slotName;
989
+ }
990
+ }
991
+
992
+ /*******************************************************/
993
+ /* DeftemplateSlotDefaultPFunction: H/L access routine */
994
+ /* for the deftemplate-slot-defaultp function. */
995
+ /*******************************************************/
996
+ void DeftemplateSlotDefaultPFunction(
997
+ Environment *theEnv,
998
+ UDFContext *context,
999
+ UDFValue *returnValue)
1000
+ {
1001
+ Deftemplate *theDeftemplate;
1002
+ CLIPSLexeme *slotName;
1003
+ DefaultType defaultType;
1004
+
1005
+ /*===================================================*/
1006
+ /* Retrieve the deftemplate and slot name arguments. */
1007
+ /*===================================================*/
1008
+
1009
+ slotName = CheckDeftemplateAndSlotArguments(context,&theDeftemplate);
1010
+ if (slotName == NULL)
1011
+ {
1012
+ returnValue->lexemeValue = FalseSymbol(theEnv);
1013
+ return;
1014
+ }
1015
+
1016
+ /*===============================*/
1017
+ /* Does the slot have a default? */
1018
+ /*===============================*/
1019
+
1020
+ defaultType = DeftemplateSlotDefaultP(theDeftemplate,slotName->contents);
1021
+
1022
+ if (defaultType == STATIC_DEFAULT)
1023
+ { returnValue->lexemeValue = CreateSymbol(theEnv,"static"); }
1024
+ else if (defaultType == DYNAMIC_DEFAULT)
1025
+ { returnValue->lexemeValue = CreateSymbol(theEnv,"dynamic"); }
1026
+ else
1027
+ { returnValue->lexemeValue = FalseSymbol(theEnv); }
1028
+ }
1029
+
1030
+ /*************************************************/
1031
+ /* DeftemplateSlotDefaultP: C access routine for */
1032
+ /* the deftemplate-slot-defaultp function. */
1033
+ /*************************************************/
1034
+ DefaultType DeftemplateSlotDefaultP(
1035
+ Deftemplate *theDeftemplate,
1036
+ const char *slotName)
1037
+ {
1038
+ struct templateSlot *theSlot;
1039
+ Environment *theEnv = theDeftemplate->header.env;
1040
+
1041
+ /*==================================================*/
1042
+ /* Make sure the slot exists (the symbol implied is */
1043
+ /* used for the implied slot of an ordered fact). */
1044
+ /*==================================================*/
1045
+
1046
+ if (theDeftemplate->implied)
1047
+ {
1048
+ if (strcmp(slotName,"implied") == 0)
1049
+ {
1050
+ return STATIC_DEFAULT;
1051
+ }
1052
+ else
1053
+ {
1054
+ SetEvaluationError(theEnv,true);
1055
+ InvalidDeftemplateSlotMessage(theEnv,slotName,
1056
+ theDeftemplate->header.name->contents,false);
1057
+ return NO_DEFAULT;
1058
+ }
1059
+ }
1060
+
1061
+ /*============================================*/
1062
+ /* Otherwise search for the slot name in the */
1063
+ /* list of slots defined for the deftemplate. */
1064
+ /*============================================*/
1065
+
1066
+ else if ((theSlot = FindSlot(theDeftemplate,CreateSymbol(theEnv,slotName),NULL)) == NULL)
1067
+ {
1068
+ SetEvaluationError(theEnv,true);
1069
+ InvalidDeftemplateSlotMessage(theEnv,slotName,
1070
+ theDeftemplate->header.name->contents,false);
1071
+ return NO_DEFAULT;
1072
+ }
1073
+
1074
+ /*======================================*/
1075
+ /* Return the default type of the slot. */
1076
+ /*======================================*/
1077
+
1078
+ if (theSlot->noDefault)
1079
+ { return NO_DEFAULT; }
1080
+ else if (theSlot->defaultDynamic)
1081
+ { return DYNAMIC_DEFAULT; }
1082
+
1083
+ return STATIC_DEFAULT;
1084
+ }
1085
+
1086
+ /*************************************************************/
1087
+ /* DeftemplateSlotDefaultValueFunction: H/L access routine */
1088
+ /* for the deftemplate-slot-default-value function. */
1089
+ /*************************************************************/
1090
+ void DeftemplateSlotDefaultValueFunction(
1091
+ Environment *theEnv,
1092
+ UDFContext *context,
1093
+ UDFValue *returnValue)
1094
+ {
1095
+ Deftemplate *theDeftemplate;
1096
+ CLIPSLexeme *slotName;
1097
+ CLIPSValue cv;
1098
+
1099
+ /*===================================================*/
1100
+ /* Retrieve the deftemplate and slot name arguments. */
1101
+ /*===================================================*/
1102
+
1103
+ slotName = CheckDeftemplateAndSlotArguments(context,&theDeftemplate);
1104
+ if (slotName == NULL)
1105
+ {
1106
+ returnValue->lexemeValue = FalseSymbol(theEnv);
1107
+ return;
1108
+ }
1109
+
1110
+ /*=========================================*/
1111
+ /* Get the deftemplate slot default value. */
1112
+ /*=========================================*/
1113
+
1114
+ DeftemplateSlotDefaultValue(theDeftemplate,slotName->contents,&cv);
1115
+ CLIPSToUDFValue(&cv,returnValue);
1116
+ }
1117
+
1118
+ /******************************************************/
1119
+ /* DeftemplateSlotDefaultValue: C access routine for */
1120
+ /* the deftemplate-slot-default-value function. */
1121
+ /******************************************************/
1122
+ bool DeftemplateSlotDefaultValue(
1123
+ Deftemplate *theDeftemplate,
1124
+ const char *slotName,
1125
+ CLIPSValue *theValue)
1126
+ {
1127
+ struct templateSlot *theSlot;
1128
+ UDFValue tempDO;
1129
+ Environment *theEnv = theDeftemplate->header.env;
1130
+
1131
+ /*=============================================*/
1132
+ /* Set up the default return value for errors. */
1133
+ /*=============================================*/
1134
+
1135
+ theValue->value = FalseSymbol(theEnv);
1136
+
1137
+ /*==================================================*/
1138
+ /* Make sure the slot exists (the symbol implied is */
1139
+ /* used for the implied slot of an ordered fact). */
1140
+ /*==================================================*/
1141
+
1142
+ if (theDeftemplate->implied)
1143
+ {
1144
+ if (strcmp(slotName,"implied") == 0)
1145
+ {
1146
+ theValue->value = CreateMultifield(theEnv,0L);
1147
+ return true;
1148
+ }
1149
+ else
1150
+ {
1151
+ SetEvaluationError(theEnv,true);
1152
+ InvalidDeftemplateSlotMessage(theEnv,slotName,
1153
+ theDeftemplate->header.name->contents,false);
1154
+ return false;
1155
+ }
1156
+ }
1157
+
1158
+ /*============================================*/
1159
+ /* Otherwise search for the slot name in the */
1160
+ /* list of slots defined for the deftemplate. */
1161
+ /*============================================*/
1162
+
1163
+ else if ((theSlot = FindSlot(theDeftemplate,CreateSymbol(theEnv,slotName),NULL)) == NULL)
1164
+ {
1165
+ SetEvaluationError(theEnv,true);
1166
+ InvalidDeftemplateSlotMessage(theEnv,slotName,
1167
+ theDeftemplate->header.name->contents,false);
1168
+ return false;
1169
+ }
1170
+
1171
+ /*=======================================*/
1172
+ /* Return the default value of the slot. */
1173
+ /*=======================================*/
1174
+
1175
+ if (theSlot->noDefault)
1176
+ { theValue->value = CreateSymbol(theEnv,"?NONE"); }
1177
+ else if (DeftemplateSlotDefault(theEnv,theDeftemplate,theSlot,&tempDO,true))
1178
+ {
1179
+ NormalizeMultifield(theEnv,&tempDO);
1180
+ theValue->value = tempDO.value;
1181
+ }
1182
+ else
1183
+ { return false; }
1184
+
1185
+ return true;
1186
+ }
1187
+
1188
+ /**********************************************************/
1189
+ /* DeftemplateSlotCardinalityFunction: H/L access routine */
1190
+ /* for the deftemplate-slot-cardinality function. */
1191
+ /**********************************************************/
1192
+ void DeftemplateSlotCardinalityFunction(
1193
+ Environment *theEnv,
1194
+ UDFContext *context,
1195
+ UDFValue *returnValue)
1196
+ {
1197
+ Deftemplate *theDeftemplate;
1198
+ CLIPSLexeme *slotName;
1199
+ CLIPSValue cv;
1200
+
1201
+ /*===================================================*/
1202
+ /* Retrieve the deftemplate and slot name arguments. */
1203
+ /*===================================================*/
1204
+
1205
+ slotName = CheckDeftemplateAndSlotArguments(context,&theDeftemplate);
1206
+ if (slotName == NULL)
1207
+ {
1208
+ SetMultifieldErrorValue(theEnv,returnValue);
1209
+ return;
1210
+ }
1211
+
1212
+ /*=======================================*/
1213
+ /* Get the deftemplate slot cardinality. */
1214
+ /*=======================================*/
1215
+
1216
+ DeftemplateSlotCardinality(theDeftemplate,slotName->contents,&cv);
1217
+ CLIPSToUDFValue(&cv,returnValue);
1218
+ }
1219
+
1220
+ /****************************************************/
1221
+ /* DeftemplateSlotCardinality: C access routine for */
1222
+ /* the deftemplate-slot-cardinality function. */
1223
+ /****************************************************/
1224
+ bool DeftemplateSlotCardinality(
1225
+ Deftemplate *theDeftemplate,
1226
+ const char *slotName,
1227
+ CLIPSValue *returnValue)
1228
+ {
1229
+ struct templateSlot *theSlot;
1230
+ Environment *theEnv = theDeftemplate->header.env;
1231
+
1232
+ /*===============================================*/
1233
+ /* If we're dealing with an implied deftemplate, */
1234
+ /* then the only slot names is "implied." */
1235
+ /*===============================================*/
1236
+
1237
+ if (theDeftemplate->implied)
1238
+ {
1239
+ if (strcmp(slotName,"implied") == 0)
1240
+ {
1241
+ returnValue->value = CreateMultifield(theEnv,2L);
1242
+ returnValue->multifieldValue->contents[0].integerValue = SymbolData(theEnv)->Zero;
1243
+ returnValue->multifieldValue->contents[1].lexemeValue = SymbolData(theEnv)->PositiveInfinity;
1244
+ return true;
1245
+ }
1246
+ else
1247
+ {
1248
+ returnValue->multifieldValue = CreateMultifield(theEnv,0L);
1249
+ SetEvaluationError(theEnv,true);
1250
+ InvalidDeftemplateSlotMessage(theEnv,slotName,
1251
+ theDeftemplate->header.name->contents,false);
1252
+ return false;
1253
+ }
1254
+ }
1255
+
1256
+ /*============================================*/
1257
+ /* Otherwise search for the slot name in the */
1258
+ /* list of slots defined for the deftemplate. */
1259
+ /*============================================*/
1260
+
1261
+ else if ((theSlot = FindSlot(theDeftemplate,CreateSymbol(theEnv,slotName),NULL)) == NULL)
1262
+ {
1263
+ returnValue->multifieldValue = CreateMultifield(theEnv,0L);
1264
+ SetEvaluationError(theEnv,true);
1265
+ InvalidDeftemplateSlotMessage(theEnv,slotName,
1266
+ theDeftemplate->header.name->contents,false);
1267
+ return false;
1268
+ }
1269
+
1270
+ /*=====================================*/
1271
+ /* Return the cardinality of the slot. */
1272
+ /*=====================================*/
1273
+
1274
+ if (theSlot->multislot == 0)
1275
+ {
1276
+ returnValue->multifieldValue = CreateMultifield(theEnv,0L);
1277
+ return true;
1278
+ }
1279
+
1280
+ returnValue->value = CreateMultifield(theEnv,2L);
1281
+
1282
+ if (theSlot->constraints != NULL)
1283
+ {
1284
+ returnValue->multifieldValue->contents[0].value = theSlot->constraints->minFields->value;
1285
+ returnValue->multifieldValue->contents[1].value = theSlot->constraints->maxFields->value;
1286
+ }
1287
+ else
1288
+ {
1289
+ returnValue->multifieldValue->contents[0].integerValue = SymbolData(theEnv)->Zero;
1290
+ returnValue->multifieldValue->contents[1].lexemeValue = SymbolData(theEnv)->PositiveInfinity;
1291
+ }
1292
+
1293
+ return true;
1294
+ }
1295
+
1296
+ /************************************************************/
1297
+ /* DeftemplateSlotAllowedValuesFunction: H/L access routine */
1298
+ /* for the deftemplate-slot-allowed-values function. */
1299
+ /************************************************************/
1300
+ void DeftemplateSlotAllowedValuesFunction(
1301
+ Environment *theEnv,
1302
+ UDFContext *context,
1303
+ UDFValue *returnValue)
1304
+ {
1305
+ Deftemplate *theDeftemplate;
1306
+ CLIPSLexeme *slotName;
1307
+ CLIPSValue result;
1308
+
1309
+ /*===================================================*/
1310
+ /* Retrieve the deftemplate and slot name arguments. */
1311
+ /*===================================================*/
1312
+
1313
+ slotName = CheckDeftemplateAndSlotArguments(context,&theDeftemplate);
1314
+ if (slotName == NULL)
1315
+ {
1316
+ SetMultifieldErrorValue(theEnv,returnValue);
1317
+ return;
1318
+ }
1319
+
1320
+ /*==========================================*/
1321
+ /* Get the deftemplate slot allowed values. */
1322
+ /*==========================================*/
1323
+
1324
+ DeftemplateSlotAllowedValues(theDeftemplate,slotName->contents,&result);
1325
+ CLIPSToUDFValue(&result,returnValue);
1326
+ }
1327
+
1328
+ /*******************************************************/
1329
+ /* DeftemplateSlotAllowedValues: C access routine */
1330
+ /* for the deftemplate-slot-allowed-values function. */
1331
+ /*******************************************************/
1332
+ bool DeftemplateSlotAllowedValues(
1333
+ Deftemplate *theDeftemplate,
1334
+ const char *slotName,
1335
+ CLIPSValue *returnValue)
1336
+ {
1337
+ struct templateSlot *theSlot;
1338
+ int i;
1339
+ Expression *theExp;
1340
+ Environment *theEnv = theDeftemplate->header.env;
1341
+
1342
+ /*===============================================*/
1343
+ /* If we're dealing with an implied deftemplate, */
1344
+ /* then the only slot names is "implied." */
1345
+ /*===============================================*/
1346
+
1347
+ if (theDeftemplate->implied)
1348
+ {
1349
+ if (strcmp(slotName,"implied") == 0)
1350
+ {
1351
+ returnValue->value = FalseSymbol(theEnv);
1352
+ return true;
1353
+ }
1354
+ else
1355
+ {
1356
+ returnValue->multifieldValue = CreateMultifield(theEnv,0L);
1357
+ SetEvaluationError(theEnv,true);
1358
+ InvalidDeftemplateSlotMessage(theEnv,slotName,
1359
+ theDeftemplate->header.name->contents,false);
1360
+ return false;
1361
+ }
1362
+ }
1363
+
1364
+ /*============================================*/
1365
+ /* Otherwise search for the slot name in the */
1366
+ /* list of slots defined for the deftemplate. */
1367
+ /*============================================*/
1368
+
1369
+ else if ((theSlot = FindSlot(theDeftemplate,CreateSymbol(theEnv,slotName),NULL)) == NULL)
1370
+ {
1371
+ returnValue->multifieldValue = CreateMultifield(theEnv,0L);
1372
+ SetEvaluationError(theEnv,true);
1373
+ InvalidDeftemplateSlotMessage(theEnv,slotName,
1374
+ theDeftemplate->header.name->contents,false);
1375
+ return false;
1376
+ }
1377
+
1378
+ /*========================================*/
1379
+ /* Return the allowed values of the slot. */
1380
+ /*========================================*/
1381
+
1382
+ if ((theSlot->constraints != NULL) ? (theSlot->constraints->restrictionList == NULL) : true)
1383
+ {
1384
+ returnValue->value = FalseSymbol(theEnv);
1385
+ return true;
1386
+ }
1387
+
1388
+ returnValue->value = CreateMultifield(theEnv,ExpressionSize(theSlot->constraints->restrictionList));
1389
+ i = 0;
1390
+
1391
+ theExp = theSlot->constraints->restrictionList;
1392
+ while (theExp != NULL)
1393
+ {
1394
+ returnValue->multifieldValue->contents[i].value = theExp->value;
1395
+ theExp = theExp->nextArg;
1396
+ i++;
1397
+ }
1398
+
1399
+ return true;
1400
+ }
1401
+
1402
+ /****************************************************/
1403
+ /* DeftemplateSlotRangeFunction: H/L access routine */
1404
+ /* for the deftemplate-slot-range function. */
1405
+ /****************************************************/
1406
+ void DeftemplateSlotRangeFunction(
1407
+ Environment *theEnv,
1408
+ UDFContext *context,
1409
+ UDFValue *returnValue)
1410
+ {
1411
+ Deftemplate *theDeftemplate;
1412
+ CLIPSLexeme *slotName;
1413
+ CLIPSValue cv;
1414
+
1415
+ /*===================================================*/
1416
+ /* Retrieve the deftemplate and slot name arguments. */
1417
+ /*===================================================*/
1418
+
1419
+ slotName = CheckDeftemplateAndSlotArguments(context,&theDeftemplate);
1420
+ if (slotName == NULL)
1421
+ {
1422
+ SetMultifieldErrorValue(theEnv,returnValue);
1423
+ return;
1424
+ }
1425
+
1426
+ /*=================================*/
1427
+ /* Get the deftemplate slot range. */
1428
+ /*=================================*/
1429
+
1430
+ DeftemplateSlotRange(theDeftemplate,slotName->contents,&cv);
1431
+ CLIPSToUDFValue(&cv,returnValue);
1432
+ }
1433
+
1434
+ /**********************************************/
1435
+ /* DeftemplateSlotRange: C access routine for */
1436
+ /* the deftemplate-slot-range function. */
1437
+ /**********************************************/
1438
+ bool DeftemplateSlotRange(
1439
+ Deftemplate *theDeftemplate,
1440
+ const char *slotName,
1441
+ CLIPSValue *returnValue)
1442
+ {
1443
+ struct templateSlot *theSlot;
1444
+ Environment *theEnv = theDeftemplate->header.env;
1445
+
1446
+ /*===============================================*/
1447
+ /* If we're dealing with an implied deftemplate, */
1448
+ /* then the only slot names is "implied." */
1449
+ /*===============================================*/
1450
+
1451
+ if (theDeftemplate->implied)
1452
+ {
1453
+ if (strcmp(slotName,"implied") == 0)
1454
+ {
1455
+ returnValue->value = CreateMultifield(theEnv,2L);
1456
+ returnValue->multifieldValue->contents[0].lexemeValue =
1457
+ SymbolData(theEnv)->NegativeInfinity;
1458
+ returnValue->multifieldValue->contents[1].lexemeValue =
1459
+ SymbolData(theEnv)->PositiveInfinity;
1460
+ return true;
1461
+ }
1462
+ else
1463
+ {
1464
+ returnValue->multifieldValue = CreateMultifield(theEnv,0L);
1465
+ SetEvaluationError(theEnv,true);
1466
+ InvalidDeftemplateSlotMessage(theEnv,slotName,
1467
+ theDeftemplate->header.name->contents,false);
1468
+ return false;
1469
+ }
1470
+ }
1471
+
1472
+ /*============================================*/
1473
+ /* Otherwise search for the slot name in the */
1474
+ /* list of slots defined for the deftemplate. */
1475
+ /*============================================*/
1476
+
1477
+ else if ((theSlot = FindSlot(theDeftemplate,CreateSymbol(theEnv,slotName),NULL)) == NULL)
1478
+ {
1479
+ returnValue->multifieldValue = CreateMultifield(theEnv,0L);
1480
+ SetEvaluationError(theEnv,true);
1481
+ InvalidDeftemplateSlotMessage(theEnv,slotName,
1482
+ theDeftemplate->header.name->contents,false);
1483
+ return false;
1484
+ }
1485
+
1486
+ /*===============================*/
1487
+ /* Return the range of the slot. */
1488
+ /*===============================*/
1489
+
1490
+ if ((theSlot->constraints == NULL) ? false :
1491
+ (theSlot->constraints->anyAllowed || theSlot->constraints->floatsAllowed ||
1492
+ theSlot->constraints->integersAllowed))
1493
+ {
1494
+ returnValue->value = CreateMultifield(theEnv,2L);
1495
+ returnValue->multifieldValue->contents[0].value = theSlot->constraints->minValue->value;
1496
+ returnValue->multifieldValue->contents[1].value = theSlot->constraints->maxValue->value;
1497
+ }
1498
+ else
1499
+ { returnValue->value = FalseSymbol(theEnv); }
1500
+
1501
+ return true;
1502
+ }
1503
+
1504
+ /****************************************************/
1505
+ /* DeftemplateSlotTypesFunction: H/L access routine */
1506
+ /* for the deftemplate-slot-types function. */
1507
+ /****************************************************/
1508
+ void DeftemplateSlotTypesFunction(
1509
+ Environment *theEnv,
1510
+ UDFContext *context,
1511
+ UDFValue *returnValue)
1512
+ {
1513
+ Deftemplate *theDeftemplate;
1514
+ CLIPSLexeme *slotName;
1515
+ CLIPSValue cv;
1516
+
1517
+ /*===================================================*/
1518
+ /* Retrieve the deftemplate and slot name arguments. */
1519
+ /*===================================================*/
1520
+
1521
+ slotName = CheckDeftemplateAndSlotArguments(context,&theDeftemplate);
1522
+ if (slotName == NULL)
1523
+ {
1524
+ SetMultifieldErrorValue(theEnv,returnValue);
1525
+ return;
1526
+ }
1527
+
1528
+ /*=================================*/
1529
+ /* Get the deftemplate slot types. */
1530
+ /*=================================*/
1531
+
1532
+ DeftemplateSlotTypes(theDeftemplate,slotName->contents,&cv);
1533
+ CLIPSToUDFValue(&cv,returnValue);
1534
+ }
1535
+
1536
+ /**********************************************/
1537
+ /* DeftemplateSlotTypes: C access routine for */
1538
+ /* the deftemplate-slot-types function. */
1539
+ /**********************************************/
1540
+ bool DeftemplateSlotTypes(
1541
+ Deftemplate *theDeftemplate,
1542
+ const char *slotName,
1543
+ CLIPSValue *returnValue)
1544
+ {
1545
+ struct templateSlot *theSlot = NULL;
1546
+ unsigned int numTypes, i;
1547
+ bool allTypes = false;
1548
+ Environment *theEnv = theDeftemplate->header.env;
1549
+
1550
+ /*===============================================*/
1551
+ /* If we're dealing with an implied deftemplate, */
1552
+ /* then the only slot name is "implied." */
1553
+ /*===============================================*/
1554
+
1555
+ if (theDeftemplate->implied)
1556
+ {
1557
+ if (strcmp(slotName,"implied") != 0)
1558
+ {
1559
+ returnValue->multifieldValue = CreateMultifield(theEnv,0L);
1560
+ SetEvaluationError(theEnv,true);
1561
+ InvalidDeftemplateSlotMessage(theEnv,slotName,
1562
+ theDeftemplate->header.name->contents,false);
1563
+ return false;
1564
+ }
1565
+ }
1566
+
1567
+ /*============================================*/
1568
+ /* Otherwise search for the slot name in the */
1569
+ /* list of slots defined for the deftemplate. */
1570
+ /*============================================*/
1571
+
1572
+ else if ((theSlot = FindSlot(theDeftemplate,CreateSymbol(theEnv,slotName),NULL)) == NULL)
1573
+ {
1574
+ returnValue->multifieldValue = CreateMultifield(theEnv,0L);
1575
+ SetEvaluationError(theEnv,true);
1576
+ InvalidDeftemplateSlotMessage(theEnv,slotName,
1577
+ theDeftemplate->header.name->contents,false);
1578
+ return false;
1579
+ }
1580
+
1581
+ /*==============================================*/
1582
+ /* If the slot has no constraint information or */
1583
+ /* there is no type restriction, then all types */
1584
+ /* are allowed for the slot. */
1585
+ /*==============================================*/
1586
+
1587
+ if ((theDeftemplate->implied) ||
1588
+ ((theSlot->constraints != NULL) ? theSlot->constraints->anyAllowed : true))
1589
+ {
1590
+ #if OBJECT_SYSTEM
1591
+ numTypes = 8;
1592
+ #else
1593
+ numTypes = 6;
1594
+ #endif
1595
+ allTypes = true;
1596
+ }
1597
+
1598
+ /*==============================================*/
1599
+ /* Otherwise count the number of types allowed. */
1600
+ /*==============================================*/
1601
+
1602
+ else
1603
+ {
1604
+ numTypes = theSlot->constraints->symbolsAllowed +
1605
+ theSlot->constraints->stringsAllowed +
1606
+ theSlot->constraints->floatsAllowed +
1607
+ theSlot->constraints->integersAllowed +
1608
+ theSlot->constraints->instanceNamesAllowed +
1609
+ theSlot->constraints->instanceAddressesAllowed +
1610
+ theSlot->constraints->externalAddressesAllowed +
1611
+ theSlot->constraints->factAddressesAllowed;
1612
+ }
1613
+
1614
+ /*========================================*/
1615
+ /* Return the allowed types for the slot. */
1616
+ /*========================================*/
1617
+
1618
+ returnValue->value = CreateMultifield(theEnv,numTypes);
1619
+
1620
+ i = 0;
1621
+
1622
+ if (allTypes || theSlot->constraints->floatsAllowed)
1623
+ {
1624
+ returnValue->multifieldValue->contents[i++].lexemeValue = CreateSymbol(theEnv,"FLOAT");
1625
+ }
1626
+
1627
+ if (allTypes || theSlot->constraints->integersAllowed)
1628
+ {
1629
+ returnValue->multifieldValue->contents[i++].lexemeValue = CreateSymbol(theEnv,"INTEGER");
1630
+ }
1631
+
1632
+ if (allTypes || theSlot->constraints->symbolsAllowed)
1633
+ {
1634
+ returnValue->multifieldValue->contents[i++].lexemeValue = CreateSymbol(theEnv,"SYMBOL");
1635
+ }
1636
+
1637
+ if (allTypes || theSlot->constraints->stringsAllowed)
1638
+ {
1639
+ returnValue->multifieldValue->contents[i++].lexemeValue = CreateSymbol(theEnv,"STRING");
1640
+ }
1641
+
1642
+ if (allTypes || theSlot->constraints->externalAddressesAllowed)
1643
+ {
1644
+ returnValue->multifieldValue->contents[i++].lexemeValue = CreateSymbol(theEnv,"EXTERNAL-ADDRESS");
1645
+ }
1646
+
1647
+ if (allTypes || theSlot->constraints->factAddressesAllowed)
1648
+ {
1649
+ returnValue->multifieldValue->contents[i++].lexemeValue = CreateSymbol(theEnv,"FACT-ADDRESS");
1650
+ }
1651
+
1652
+ #if OBJECT_SYSTEM
1653
+ if (allTypes || theSlot->constraints->instanceAddressesAllowed)
1654
+ {
1655
+ returnValue->multifieldValue->contents[i++].lexemeValue = CreateSymbol(theEnv,"INSTANCE-ADDRESS");
1656
+ }
1657
+
1658
+ if (allTypes || theSlot->constraints->instanceNamesAllowed)
1659
+ {
1660
+ returnValue->multifieldValue->contents[i++].lexemeValue = CreateSymbol(theEnv,"INSTANCE-NAME");
1661
+ }
1662
+ #endif
1663
+
1664
+ return true;
1665
+ }
1666
+
1667
+ /*****************************************************/
1668
+ /* DeftemplateSlotMultiPFunction: H/L access routine */
1669
+ /* for the deftemplate-slot-multip function. */
1670
+ /*****************************************************/
1671
+ void DeftemplateSlotMultiPFunction(
1672
+ Environment *theEnv,
1673
+ UDFContext *context,
1674
+ UDFValue *returnValue)
1675
+ {
1676
+ Deftemplate *theDeftemplate;
1677
+ CLIPSLexeme *slotName;
1678
+
1679
+ /*===================================================*/
1680
+ /* Retrieve the deftemplate and slot name arguments. */
1681
+ /*===================================================*/
1682
+
1683
+ slotName = CheckDeftemplateAndSlotArguments(context,&theDeftemplate);
1684
+ if (slotName == NULL)
1685
+ {
1686
+ returnValue->lexemeValue = FalseSymbol(theEnv);
1687
+ return;
1688
+ }
1689
+
1690
+ /*================================*/
1691
+ /* Is the slot a multifield slot? */
1692
+ /*================================*/
1693
+
1694
+ returnValue->lexemeValue = CreateBoolean(theEnv,DeftemplateSlotMultiP(theDeftemplate,slotName->contents));
1695
+ }
1696
+
1697
+ /***********************************************/
1698
+ /* DeftemplateSlotMultiP: C access routine for */
1699
+ /* the deftemplate-slot-multip function. */
1700
+ /***********************************************/
1701
+ bool DeftemplateSlotMultiP(
1702
+ Deftemplate *theDeftemplate,
1703
+ const char *slotName)
1704
+ {
1705
+ struct templateSlot *theSlot;
1706
+ Environment *theEnv = theDeftemplate->header.env;
1707
+
1708
+ /*===============================================*/
1709
+ /* If we're dealing with an implied deftemplate, */
1710
+ /* then the only slot names is "implied." */
1711
+ /*===============================================*/
1712
+
1713
+ if (theDeftemplate->implied)
1714
+ {
1715
+ if (strcmp(slotName,"implied") == 0)
1716
+ { return true; }
1717
+ else
1718
+ {
1719
+ SetEvaluationError(theEnv,true);
1720
+ InvalidDeftemplateSlotMessage(theEnv,slotName,
1721
+ theDeftemplate->header.name->contents,false);
1722
+ return false;
1723
+ }
1724
+ }
1725
+
1726
+ /*============================================*/
1727
+ /* Otherwise search for the slot name in the */
1728
+ /* list of slots defined for the deftemplate. */
1729
+ /*============================================*/
1730
+
1731
+ else if ((theSlot = FindSlot(theDeftemplate,CreateSymbol(theEnv,slotName),NULL)) == NULL)
1732
+ {
1733
+ SetEvaluationError(theEnv,true);
1734
+ InvalidDeftemplateSlotMessage(theEnv,slotName,
1735
+ theDeftemplate->header.name->contents,false);
1736
+ return false;
1737
+ }
1738
+
1739
+ /*================================*/
1740
+ /* Is the slot a multifield slot? */
1741
+ /*================================*/
1742
+
1743
+ return(theSlot->multislot);
1744
+ }
1745
+
1746
+ /******************************************************/
1747
+ /* DeftemplateSlotSinglePFunction: H/L access routine */
1748
+ /* for the deftemplate-slot-singlep function. */
1749
+ /******************************************************/
1750
+ void DeftemplateSlotSinglePFunction(
1751
+ Environment *theEnv,
1752
+ UDFContext *context,
1753
+ UDFValue *returnValue)
1754
+ {
1755
+ Deftemplate *theDeftemplate;
1756
+ CLIPSLexeme *slotName;
1757
+
1758
+ /*===================================================*/
1759
+ /* Retrieve the deftemplate and slot name arguments. */
1760
+ /*===================================================*/
1761
+
1762
+ slotName = CheckDeftemplateAndSlotArguments(context,&theDeftemplate);
1763
+ if (slotName == NULL)
1764
+ {
1765
+ returnValue->lexemeValue = FalseSymbol(theEnv);
1766
+ return;
1767
+ }
1768
+
1769
+ /*==================================*/
1770
+ /* Is the slot a single field slot? */
1771
+ /*==================================*/
1772
+
1773
+ returnValue->lexemeValue = CreateBoolean(theEnv,DeftemplateSlotSingleP(theDeftemplate,slotName->contents));
1774
+ }
1775
+
1776
+ /************************************************/
1777
+ /* DeftemplateSlotSingleP: C access routine for */
1778
+ /* the deftemplate-slot-singlep function. */
1779
+ /************************************************/
1780
+ bool DeftemplateSlotSingleP(
1781
+ Deftemplate *theDeftemplate,
1782
+ const char *slotName)
1783
+ {
1784
+ struct templateSlot *theSlot;
1785
+ Environment *theEnv = theDeftemplate->header.env;
1786
+
1787
+ /*===============================================*/
1788
+ /* If we're dealing with an implied deftemplate, */
1789
+ /* then the only slot names is "implied." */
1790
+ /*===============================================*/
1791
+
1792
+ if (theDeftemplate->implied)
1793
+ {
1794
+ if (strcmp(slotName,"implied") == 0)
1795
+ { return false; }
1796
+ else
1797
+ {
1798
+ SetEvaluationError(theEnv,true);
1799
+ InvalidDeftemplateSlotMessage(theEnv,slotName,
1800
+ theDeftemplate->header.name->contents,false);
1801
+ return false;
1802
+ }
1803
+ }
1804
+
1805
+ /*============================================*/
1806
+ /* Otherwise search for the slot name in the */
1807
+ /* list of slots defined for the deftemplate. */
1808
+ /*============================================*/
1809
+
1810
+ else if ((theSlot = FindSlot(theDeftemplate,CreateSymbol(theEnv,slotName),NULL)) == NULL)
1811
+ {
1812
+ SetEvaluationError(theEnv,true);
1813
+ InvalidDeftemplateSlotMessage(theEnv,slotName,
1814
+ theDeftemplate->header.name->contents,false);
1815
+ return false;
1816
+ }
1817
+
1818
+ /*==================================*/
1819
+ /* Is the slot a single field slot? */
1820
+ /*==================================*/
1821
+
1822
+ return(! theSlot->multislot);
1823
+ }
1824
+
1825
+ /*****************************************************/
1826
+ /* DeftemplateSlotExistPFunction: H/L access routine */
1827
+ /* for the deftemplate-slot-existp function. */
1828
+ /*****************************************************/
1829
+ void DeftemplateSlotExistPFunction(
1830
+ Environment *theEnv,
1831
+ UDFContext *context,
1832
+ UDFValue *returnValue)
1833
+ {
1834
+ Deftemplate *theDeftemplate;
1835
+ CLIPSLexeme *slotName;
1836
+
1837
+ /*===================================================*/
1838
+ /* Retrieve the deftemplate and slot name arguments. */
1839
+ /*===================================================*/
1840
+
1841
+ slotName = CheckDeftemplateAndSlotArguments(context,&theDeftemplate);
1842
+ if (slotName == NULL)
1843
+ {
1844
+ returnValue->lexemeValue = FalseSymbol(theEnv);
1845
+ return;
1846
+ }
1847
+
1848
+ /*======================*/
1849
+ /* Does the slot exist? */
1850
+ /*======================*/
1851
+
1852
+ returnValue->lexemeValue = CreateBoolean(theEnv,DeftemplateSlotExistP(theDeftemplate,slotName->contents));
1853
+ }
1854
+
1855
+ /***********************************************/
1856
+ /* DeftemplateSlotExistP: C access routine for */
1857
+ /* the deftemplate-slot-existp function. */
1858
+ /***********************************************/
1859
+ bool DeftemplateSlotExistP(
1860
+ Deftemplate *theDeftemplate,
1861
+ const char *slotName)
1862
+ {
1863
+ Environment *theEnv = theDeftemplate->header.env;
1864
+
1865
+ /*===============================================*/
1866
+ /* If we're dealing with an implied deftemplate, */
1867
+ /* then the only slot names is "implied." */
1868
+ /*===============================================*/
1869
+
1870
+ if (theDeftemplate->implied)
1871
+ {
1872
+ if (strcmp(slotName,"implied") == 0)
1873
+ { return true; }
1874
+ else
1875
+ { return false; }
1876
+ }
1877
+
1878
+ /*============================================*/
1879
+ /* Otherwise search for the slot name in the */
1880
+ /* list of slots defined for the deftemplate. */
1881
+ /*============================================*/
1882
+
1883
+ else if (FindSlot(theDeftemplate,CreateSymbol(theEnv,slotName),NULL) == NULL)
1884
+ { return false; }
1885
+
1886
+ /*==================*/
1887
+ /* The slot exists. */
1888
+ /*==================*/
1889
+
1890
+ return true;
1891
+ }
1892
+
1893
+ /**********************************************************/
1894
+ /* DeftemplateSlotFacetExistPFunction: H/L access routine */
1895
+ /* for the deftemplate-slot-facet-existp function. */
1896
+ /**********************************************************/
1897
+ void DeftemplateSlotFacetExistPFunction(
1898
+ Environment *theEnv,
1899
+ UDFContext *context,
1900
+ UDFValue *returnValue)
1901
+ {
1902
+ Deftemplate *theDeftemplate;
1903
+ CLIPSLexeme *slotName;
1904
+ UDFValue facetName;
1905
+
1906
+ /*===================================================*/
1907
+ /* Retrieve the deftemplate and slot name arguments. */
1908
+ /*===================================================*/
1909
+
1910
+ slotName = CheckDeftemplateAndSlotArguments(context,&theDeftemplate);
1911
+ if (slotName == NULL)
1912
+ {
1913
+ returnValue->lexemeValue = FalseSymbol(theEnv);
1914
+ return;
1915
+ }
1916
+
1917
+ /*============================*/
1918
+ /* Get the name of the facet. */
1919
+ /*============================*/
1920
+
1921
+ if (! UDFNextArgument(context,SYMBOL_BIT,&facetName))
1922
+ {
1923
+ returnValue->lexemeValue = FalseSymbol(theEnv);
1924
+ return;
1925
+ }
1926
+
1927
+ /*======================*/
1928
+ /* Does the slot exist? */
1929
+ /*======================*/
1930
+
1931
+ returnValue->lexemeValue = CreateBoolean(theEnv,DeftemplateSlotFacetExistP(theEnv,theDeftemplate,slotName->contents,facetName.lexemeValue->contents));
1932
+ }
1933
+
1934
+ /****************************************************/
1935
+ /* DeftemplateSlotFacetExistP: C access routine for */
1936
+ /* the deftemplate-slot-facet-existp function. */
1937
+ /****************************************************/
1938
+ bool DeftemplateSlotFacetExistP(
1939
+ Environment *theEnv,
1940
+ Deftemplate *theDeftemplate,
1941
+ const char *slotName,
1942
+ const char *facetName)
1943
+ {
1944
+ struct templateSlot *theSlot;
1945
+ CLIPSLexeme *facetHN;
1946
+ struct expr *tempFacet;
1947
+
1948
+ /*=================================================*/
1949
+ /* An implied deftemplate doesn't have any facets. */
1950
+ /*=================================================*/
1951
+
1952
+ if (theDeftemplate->implied)
1953
+ { return false; }
1954
+
1955
+ /*============================================*/
1956
+ /* Otherwise search for the slot name in the */
1957
+ /* list of slots defined for the deftemplate. */
1958
+ /*============================================*/
1959
+
1960
+ else if ((theSlot = FindSlot(theDeftemplate,CreateSymbol(theEnv,slotName),NULL)) == NULL)
1961
+ { return false; }
1962
+
1963
+ /*=======================*/
1964
+ /* Search for the facet. */
1965
+ /*=======================*/
1966
+
1967
+ facetHN = FindSymbolHN(theEnv,facetName,SYMBOL_BIT);
1968
+ for (tempFacet = theSlot->facetList;
1969
+ tempFacet != NULL;
1970
+ tempFacet = tempFacet->nextArg)
1971
+ {
1972
+ if (tempFacet->value == facetHN)
1973
+ { return true; }
1974
+ }
1975
+
1976
+ /*===========================*/
1977
+ /* The facet does not exist. */
1978
+ /*===========================*/
1979
+
1980
+ return false;
1981
+ }
1982
+
1983
+ /*********************************************************/
1984
+ /* DeftemplateSlotFacetValueFunction: H/L access routine */
1985
+ /* for the deftemplate-slot-facet-value function. */
1986
+ /*********************************************************/
1987
+ void DeftemplateSlotFacetValueFunction(
1988
+ Environment *theEnv,
1989
+ UDFContext *context,
1990
+ UDFValue *returnValue)
1991
+ {
1992
+ Deftemplate *theDeftemplate;
1993
+ CLIPSLexeme *slotName;
1994
+ UDFValue facetName;
1995
+
1996
+ /*=============================================*/
1997
+ /* Set up the default return value for errors. */
1998
+ /*=============================================*/
1999
+
2000
+ returnValue->lexemeValue = FalseSymbol(theEnv);
2001
+
2002
+ /*===================================================*/
2003
+ /* Retrieve the deftemplate and slot name arguments. */
2004
+ /*===================================================*/
2005
+
2006
+ slotName = CheckDeftemplateAndSlotArguments(context,&theDeftemplate);
2007
+ if (slotName == NULL)
2008
+ { return; }
2009
+
2010
+ /*============================*/
2011
+ /* Get the name of the facet. */
2012
+ /*============================*/
2013
+
2014
+ if (! UDFNthArgument(context,3,SYMBOL_BIT,&facetName))
2015
+ { return; }
2016
+
2017
+ /*===========================*/
2018
+ /* Retrieve the facet value. */
2019
+ /*===========================*/
2020
+
2021
+ DeftemplateSlotFacetValue(theEnv,theDeftemplate,slotName->contents,facetName.lexemeValue->contents,returnValue);
2022
+ }
2023
+
2024
+ /****************************************************/
2025
+ /* DeftemplateSlotFacetValue: C access routine */
2026
+ /* for the deftemplate-slot-facet-value function. */
2027
+ /****************************************************/
2028
+ bool DeftemplateSlotFacetValue(
2029
+ Environment *theEnv,
2030
+ Deftemplate *theDeftemplate,
2031
+ const char *slotName,
2032
+ const char *facetName,
2033
+ UDFValue *rv)
2034
+ {
2035
+ struct templateSlot *theSlot;
2036
+ CLIPSLexeme *facetHN;
2037
+ struct expr *tempFacet;
2038
+
2039
+ /*=================================================*/
2040
+ /* An implied deftemplate doesn't have any facets. */
2041
+ /*=================================================*/
2042
+
2043
+ if (theDeftemplate->implied)
2044
+ { return false; }
2045
+
2046
+ /*============================================*/
2047
+ /* Otherwise search for the slot name in the */
2048
+ /* list of slots defined for the deftemplate. */
2049
+ /*============================================*/
2050
+
2051
+ else if ((theSlot = FindSlot(theDeftemplate,CreateSymbol(theEnv,slotName),NULL)) == NULL)
2052
+ { return false; }
2053
+
2054
+ /*=======================*/
2055
+ /* Search for the facet. */
2056
+ /*=======================*/
2057
+
2058
+ facetHN = FindSymbolHN(theEnv,facetName,SYMBOL_BIT);
2059
+ for (tempFacet = theSlot->facetList;
2060
+ tempFacet != NULL;
2061
+ tempFacet = tempFacet->nextArg)
2062
+ {
2063
+ if (tempFacet->value == facetHN)
2064
+ {
2065
+ EvaluateExpression(theEnv,tempFacet->argList,rv);
2066
+ return true;
2067
+ }
2068
+ }
2069
+
2070
+ /*===========================*/
2071
+ /* The facet does not exist. */
2072
+ /*===========================*/
2073
+
2074
+ return false;
2075
+ }
2076
+
2077
+ /************************************************************/
2078
+ /* CheckDeftemplateAndSlotArguments: Checks the deftemplate */
2079
+ /* and slot arguments for various functions. */
2080
+ /************************************************************/
2081
+ static CLIPSLexeme *CheckDeftemplateAndSlotArguments(
2082
+ UDFContext *context,
2083
+ Deftemplate **theDeftemplate)
2084
+ {
2085
+ UDFValue theArg;
2086
+ const char *deftemplateName;
2087
+ Environment *theEnv = context->environment;
2088
+
2089
+ /*=======================================*/
2090
+ /* Get the reference to the deftemplate. */
2091
+ /*=======================================*/
2092
+
2093
+ if (! UDFFirstArgument(context,SYMBOL_BIT,&theArg))
2094
+ { return NULL; }
2095
+
2096
+ deftemplateName = theArg.lexemeValue->contents;
2097
+
2098
+ *theDeftemplate = FindDeftemplate(theEnv,deftemplateName);
2099
+ if (*theDeftemplate == NULL)
2100
+ {
2101
+ CantFindItemErrorMessage(theEnv,"deftemplate",deftemplateName,true);
2102
+ return NULL;
2103
+ }
2104
+
2105
+ /*===========================*/
2106
+ /* Get the name of the slot. */
2107
+ /*===========================*/
2108
+
2109
+ if (! UDFNextArgument(context,SYMBOL_BIT,&theArg))
2110
+ { return NULL; }
2111
+
2112
+ return theArg.lexemeValue;
2113
+ }
2114
+
2115
+ #if (! RUN_TIME) && (! BLOAD_ONLY)
2116
+
2117
+ /***************************************************************/
2118
+ /* UpdateModifyDuplicate: Changes the modify/duplicate command */
2119
+ /* found on the RHS of a rule such that the positions of the */
2120
+ /* slots for replacement are stored rather than the slot */
2121
+ /* name which allows quicker replacement of slots. This */
2122
+ /* substitution can only take place when the deftemplate */
2123
+ /* type is known (i.e. if a fact-index is used you don't */
2124
+ /* know which type of deftemplate is going to be replaced */
2125
+ /* until you actually do the replacement of slots). */
2126
+ /***************************************************************/
2127
+ bool UpdateModifyDuplicate(
2128
+ Environment *theEnv,
2129
+ struct expr *top,
2130
+ const char *name,
2131
+ void *vTheLHS)
2132
+ {
2133
+ struct expr *functionArgs, *tempArg;
2134
+ CLIPSLexeme *templateName;
2135
+ Deftemplate *theDeftemplate;
2136
+ struct templateSlot *slotPtr;
2137
+
2138
+ /*========================================*/
2139
+ /* Determine the fact-address or index to */
2140
+ /* be retracted by the modify command. */
2141
+ /*========================================*/
2142
+
2143
+ functionArgs = top->argList;
2144
+ if (functionArgs->type == SF_VARIABLE)
2145
+ {
2146
+ if (SearchParsedBindNames(theEnv,functionArgs->lexemeValue) != 0)
2147
+ { return true; }
2148
+ templateName = FindTemplateForFactAddress(functionArgs->lexemeValue,
2149
+ (struct lhsParseNode *) vTheLHS);
2150
+ if (templateName == NULL) return true;
2151
+ }
2152
+ else
2153
+ { return true; }
2154
+
2155
+ /*========================================*/
2156
+ /* Make sure that the fact being modified */
2157
+ /* has a corresponding deftemplate. */
2158
+ /*========================================*/
2159
+
2160
+ theDeftemplate = (Deftemplate *)
2161
+ LookupConstruct(theEnv,DeftemplateData(theEnv)->DeftemplateConstruct,
2162
+ templateName->contents,
2163
+ false);
2164
+
2165
+ if (theDeftemplate == NULL) return true;
2166
+
2167
+ if (theDeftemplate->implied) return true;
2168
+
2169
+ /*=============================================================*/
2170
+ /* Make sure all the slot names are valid for the deftemplate. */
2171
+ /*=============================================================*/
2172
+
2173
+ tempArg = functionArgs->nextArg;
2174
+ while (tempArg != NULL)
2175
+ {
2176
+ /*======================*/
2177
+ /* Does the slot exist? */
2178
+ /*======================*/
2179
+
2180
+ if ((slotPtr = FindSlot(theDeftemplate,tempArg->lexemeValue,NULL)) == NULL)
2181
+ {
2182
+ InvalidDeftemplateSlotMessage(theEnv,tempArg->lexemeValue->contents,
2183
+ theDeftemplate->header.name->contents,true);
2184
+ return false;
2185
+ }
2186
+
2187
+ /*=========================================================*/
2188
+ /* Is a multifield value being put in a single field slot? */
2189
+ /*=========================================================*/
2190
+
2191
+ if (slotPtr->multislot == false)
2192
+ {
2193
+ if (tempArg->argList == NULL)
2194
+ {
2195
+ SingleFieldSlotCardinalityError(theEnv,slotPtr->slotName->contents);
2196
+ return false;
2197
+ }
2198
+ else if (tempArg->argList->nextArg != NULL)
2199
+ {
2200
+ SingleFieldSlotCardinalityError(theEnv,slotPtr->slotName->contents);
2201
+ return false;
2202
+ }
2203
+ else if (tempArg->argList->type == FCALL)
2204
+ {
2205
+ if ((ExpressionUnknownFunctionType(tempArg->argList) & SINGLEFIELD_BITS) == 0)
2206
+ {
2207
+ SingleFieldSlotCardinalityError(theEnv,slotPtr->slotName->contents);
2208
+ return false;
2209
+ }
2210
+ }
2211
+ else if (tempArg->argList->type == MF_VARIABLE)
2212
+ {
2213
+ SingleFieldSlotCardinalityError(theEnv,slotPtr->slotName->contents);
2214
+ return false;
2215
+ }
2216
+ }
2217
+
2218
+ /*======================================*/
2219
+ /* Are the slot restrictions satisfied? */
2220
+ /*======================================*/
2221
+
2222
+ if (CheckRHSSlotTypes(theEnv,tempArg->argList,slotPtr,name) == 0)
2223
+ return false;
2224
+
2225
+ /*=============================================*/
2226
+ /* Replace the slot with the integer position. */
2227
+ /*=============================================*/
2228
+
2229
+ tempArg->type = INTEGER_TYPE;
2230
+ tempArg->value = CreateInteger(theEnv,(long long) (FindSlotPosition(theDeftemplate,tempArg->lexemeValue) - 1));
2231
+
2232
+ tempArg = tempArg->nextArg;
2233
+ }
2234
+
2235
+ return true;
2236
+ }
2237
+
2238
+ /**************************************************/
2239
+ /* FindTemplateForFactAddress: Searches for the */
2240
+ /* deftemplate name associated with the pattern */
2241
+ /* to which a fact address has been bound. */
2242
+ /**************************************************/
2243
+ static CLIPSLexeme *FindTemplateForFactAddress(
2244
+ CLIPSLexeme *factAddress,
2245
+ struct lhsParseNode *theLHS)
2246
+ {
2247
+ struct lhsParseNode *thePattern = NULL;
2248
+
2249
+ /*===============================================*/
2250
+ /* Look through the LHS patterns for the pattern */
2251
+ /* which is bound to the fact address used by */
2252
+ /* the modify/duplicate function. */
2253
+ /*===============================================*/
2254
+
2255
+ while (theLHS != NULL)
2256
+ {
2257
+ if (theLHS->value == (void *) factAddress)
2258
+ {
2259
+ thePattern = theLHS;
2260
+ theLHS = NULL;
2261
+ }
2262
+ else
2263
+ { theLHS = theLHS->bottom; }
2264
+ }
2265
+
2266
+ if (thePattern == NULL) return NULL;
2267
+
2268
+ /*=====================================*/
2269
+ /* Verify that just a symbol is stored */
2270
+ /* as the first field of the pattern. */
2271
+ /*=====================================*/
2272
+
2273
+ thePattern = thePattern->right;
2274
+ if ((thePattern->pnType != SF_WILDCARD_NODE) || (thePattern->bottom == NULL))
2275
+ { return NULL; }
2276
+
2277
+ thePattern = thePattern->bottom;
2278
+ if ((thePattern->pnType != SYMBOL_NODE) ||
2279
+ (thePattern->right != NULL) ||
2280
+ (thePattern->bottom != NULL))
2281
+ { return NULL; }
2282
+
2283
+ /*==============================*/
2284
+ /* Return the deftemplate name. */
2285
+ /*==============================*/
2286
+
2287
+ return thePattern->lexemeValue;
2288
+ }
2289
+ #endif
2290
+
2291
+ /*******************************************/
2292
+ /* ModifyParse: Parses the modify command. */
2293
+ /*******************************************/
2294
+ struct expr *ModifyParse(
2295
+ Environment *theEnv,
2296
+ struct expr *top,
2297
+ const char *logicalName)
2298
+ {
2299
+ return ModAndDupParse(theEnv,top,logicalName,"modify");
2300
+ }
2301
+
2302
+ /*************************************************/
2303
+ /* DuplicateParse: Parses the duplicate command. */
2304
+ /*************************************************/
2305
+ struct expr *DuplicateParse(
2306
+ Environment *theEnv,
2307
+ struct expr *top,
2308
+ const char *logicalName)
2309
+ {
2310
+ return ModAndDupParse(theEnv,top,logicalName,"duplicate");
2311
+ }
2312
+
2313
+ /*************************************************************/
2314
+ /* ModAndDupParse: Parses the modify and duplicate commands. */
2315
+ /*************************************************************/
2316
+ static struct expr *ModAndDupParse(
2317
+ Environment *theEnv,
2318
+ struct expr *top,
2319
+ const char *logicalName,
2320
+ const char *name)
2321
+ {
2322
+ bool error = false;
2323
+ struct token theToken;
2324
+ struct expr *nextOne, *tempSlot;
2325
+ struct expr *newField, *firstField, *lastField;
2326
+ bool printError;
2327
+ bool done;
2328
+
2329
+ /*==================================================================*/
2330
+ /* Parse the fact-address or index to the modify/duplicate command. */
2331
+ /*==================================================================*/
2332
+
2333
+ SavePPBuffer(theEnv," ");
2334
+ GetToken(theEnv,logicalName,&theToken);
2335
+
2336
+ if ((theToken.tknType == SF_VARIABLE_TOKEN) || (theToken.tknType == GBL_VARIABLE_TOKEN))
2337
+ { nextOne = GenConstant(theEnv,TokenTypeToType(theToken.tknType),theToken.value); }
2338
+ else if (theToken.tknType == INTEGER_TOKEN)
2339
+ { nextOne = GenConstant(theEnv,INTEGER_TYPE,theToken.value); }
2340
+ else if (theToken.tknType == LEFT_PARENTHESIS_TOKEN)
2341
+ {
2342
+ nextOne = Function1Parse(theEnv,logicalName);
2343
+ if (nextOne == NULL)
2344
+ {
2345
+ ReturnExpression(theEnv,top);
2346
+ return NULL;
2347
+ }
2348
+ }
2349
+ else
2350
+ {
2351
+ ExpectedTypeError2(theEnv,name,1);
2352
+ ReturnExpression(theEnv,top);
2353
+ return NULL;
2354
+ }
2355
+
2356
+ top->argList = nextOne;
2357
+ nextOne = top->argList;
2358
+
2359
+ /*=======================================================*/
2360
+ /* Parse the remaining modify/duplicate slot specifiers. */
2361
+ /*=======================================================*/
2362
+
2363
+ GetToken(theEnv,logicalName,&theToken);
2364
+ while (theToken.tknType != RIGHT_PARENTHESIS_TOKEN)
2365
+ {
2366
+ PPBackup(theEnv);
2367
+ SavePPBuffer(theEnv," ");
2368
+ SavePPBuffer(theEnv,theToken.printForm);
2369
+
2370
+ /*=================================================*/
2371
+ /* Slot definition begins with a left parenthesis. */
2372
+ /*=================================================*/
2373
+
2374
+ if (theToken.tknType != LEFT_PARENTHESIS_TOKEN)
2375
+ {
2376
+ SyntaxErrorMessage(theEnv,"duplicate/modify function");
2377
+ ReturnExpression(theEnv,top);
2378
+ return NULL;
2379
+ }
2380
+
2381
+ /*=================================*/
2382
+ /* The slot name must be a symbol. */
2383
+ /*=================================*/
2384
+
2385
+ GetToken(theEnv,logicalName,&theToken);
2386
+ if (theToken.tknType != SYMBOL_TOKEN)
2387
+ {
2388
+ SyntaxErrorMessage(theEnv,"duplicate/modify function");
2389
+ ReturnExpression(theEnv,top);
2390
+ return NULL;
2391
+ }
2392
+
2393
+ /*=================================*/
2394
+ /* Check for duplicate slot names. */
2395
+ /*=================================*/
2396
+
2397
+ for (tempSlot = top->argList->nextArg;
2398
+ tempSlot != NULL;
2399
+ tempSlot = tempSlot->nextArg)
2400
+ {
2401
+ if (tempSlot->value == theToken.value)
2402
+ {
2403
+ AlreadyParsedErrorMessage(theEnv,"slot ",theToken.lexemeValue->contents);
2404
+ ReturnExpression(theEnv,top);
2405
+ return NULL;
2406
+ }
2407
+ }
2408
+
2409
+ /*=========================================*/
2410
+ /* Add the slot name to the list of slots. */
2411
+ /*=========================================*/
2412
+
2413
+ nextOne->nextArg = GenConstant(theEnv,SYMBOL_TYPE,theToken.value);
2414
+ nextOne = nextOne->nextArg;
2415
+
2416
+ /*====================================================*/
2417
+ /* Get the values to be stored in the specified slot. */
2418
+ /*====================================================*/
2419
+
2420
+ firstField = NULL;
2421
+ lastField = NULL;
2422
+ done = false;
2423
+ while (! done)
2424
+ {
2425
+ SavePPBuffer(theEnv," ");
2426
+ newField = GetAssertArgument(theEnv,logicalName,&theToken,&error,
2427
+ RIGHT_PARENTHESIS_TOKEN,false,&printError);
2428
+
2429
+ if (error)
2430
+ {
2431
+ if (printError) SyntaxErrorMessage(theEnv,"deftemplate pattern");
2432
+ ReturnExpression(theEnv,top);
2433
+ return NULL;
2434
+ }
2435
+
2436
+ if (newField == NULL)
2437
+ { done = true; }
2438
+
2439
+ if (lastField == NULL)
2440
+ { firstField = newField; }
2441
+ else
2442
+ { lastField->nextArg = newField; }
2443
+ lastField = newField;
2444
+ }
2445
+
2446
+ /*================================================*/
2447
+ /* Slot definition ends with a right parenthesis. */
2448
+ /*================================================*/
2449
+
2450
+ if (theToken.tknType != RIGHT_PARENTHESIS_TOKEN)
2451
+ {
2452
+ SyntaxErrorMessage(theEnv,"duplicate/modify function");
2453
+ ReturnExpression(theEnv,top);
2454
+ ReturnExpression(theEnv,firstField);
2455
+ return NULL;
2456
+ }
2457
+ else
2458
+ {
2459
+ PPBackup(theEnv);
2460
+ PPBackup(theEnv);
2461
+ SavePPBuffer(theEnv,")");
2462
+ }
2463
+
2464
+ nextOne->argList = firstField;
2465
+
2466
+ GetToken(theEnv,logicalName,&theToken);
2467
+ }
2468
+
2469
+ /*================================================*/
2470
+ /* Return the parsed modify/duplicate expression. */
2471
+ /*================================================*/
2472
+
2473
+ return top;
2474
+ }
2475
+
2476
+ #endif /* DEFTEMPLATE_CONSTRUCT */
2477
+