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,1176 @@
1
+ /*******************************************************/
2
+ /* "C" Language Integrated Production System */
3
+ /* */
4
+ /* CLIPS Version 6.40 10/18/16 */
5
+ /* */
6
+ /* CONSTRAINT OPERATIONS MODULE */
7
+ /*******************************************************/
8
+
9
+ /*************************************************************/
10
+ /* Purpose: Provides functions for performing operations on */
11
+ /* constraint records including computing the intersection */
12
+ /* and union of constraint records. */
13
+ /* */
14
+ /* Principal Programmer(s): */
15
+ /* Gary D. Riley */
16
+ /* */
17
+ /* Contributing Programmer(s): */
18
+ /* */
19
+ /* Revision History: */
20
+ /* */
21
+ /* 6.24: Added allowed-classes slot facet. */
22
+ /* */
23
+ /* 6.40: Pragma once and other inclusion changes. */
24
+ /* */
25
+ /* Added support for booleans with <stdbool.h>. */
26
+ /* */
27
+ /* Removed use of void pointers for specific */
28
+ /* data structures. */
29
+ /* */
30
+ /* Eval support for run time and bload only. */
31
+ /* */
32
+ /*************************************************************/
33
+
34
+ #include "setup.h"
35
+
36
+ #include <stdio.h>
37
+ #include <stdlib.h>
38
+
39
+ #include "constant.h"
40
+ #include "constrnt.h"
41
+ #include "cstrnchk.h"
42
+ #include "cstrnutl.h"
43
+ #include "envrnmnt.h"
44
+ #include "extnfunc.h"
45
+ #include "memalloc.h"
46
+ #include "multifld.h"
47
+ #include "router.h"
48
+ #include "scanner.h"
49
+
50
+ #include "cstrnops.h"
51
+
52
+ /***************************************/
53
+ /* LOCAL INTERNAL FUNCTION DEFINITIONS */
54
+ /***************************************/
55
+
56
+ static void IntersectNumericExpressions(Environment *,
57
+ CONSTRAINT_RECORD *,
58
+ CONSTRAINT_RECORD *,
59
+ CONSTRAINT_RECORD *,bool);
60
+ static void IntersectAllowedValueExpressions(Environment *,
61
+ CONSTRAINT_RECORD *,
62
+ CONSTRAINT_RECORD *,
63
+ CONSTRAINT_RECORD *);
64
+ static void IntersectAllowedClassExpressions(Environment *,
65
+ CONSTRAINT_RECORD *,
66
+ CONSTRAINT_RECORD *,
67
+ CONSTRAINT_RECORD *);
68
+ static bool FindItemInExpression(int,void *,bool,struct expr *);
69
+ static void UpdateRestrictionFlags(CONSTRAINT_RECORD *);
70
+ static void UnionRangeMinMaxValueWithList(Environment *,
71
+ struct expr *,
72
+ struct expr *,
73
+ struct expr **,
74
+ struct expr **);
75
+ static void UnionNumericExpressions(Environment *,
76
+ CONSTRAINT_RECORD *,
77
+ CONSTRAINT_RECORD *,
78
+ CONSTRAINT_RECORD *,bool);
79
+ static struct expr *AddToUnionList(Environment *,
80
+ struct expr *,struct expr *,
81
+ CONSTRAINT_RECORD *);
82
+ static void UnionAllowedValueExpressions(Environment *,
83
+ CONSTRAINT_RECORD *,
84
+ CONSTRAINT_RECORD *,
85
+ CONSTRAINT_RECORD *);
86
+ static void UnionAllowedClassExpressions(Environment *,
87
+ CONSTRAINT_RECORD *,
88
+ CONSTRAINT_RECORD *,
89
+ CONSTRAINT_RECORD *);
90
+ static bool RestrictionOnType(int,CONSTRAINT_RECORD *);
91
+
92
+ /**************************************************************/
93
+ /* IntersectConstraints: Creates a new constraint record that */
94
+ /* is the intersection of two other constraint records. */
95
+ /**************************************************************/
96
+ struct constraintRecord *IntersectConstraints(
97
+ Environment *theEnv,
98
+ CONSTRAINT_RECORD *c1,
99
+ CONSTRAINT_RECORD *c2)
100
+ {
101
+ struct constraintRecord *rv;
102
+ bool c1Changed = false, c2Changed = false;
103
+
104
+ /*=================================================*/
105
+ /* If both constraint records are NULL,then create */
106
+ /* a constraint record that allows any value. */
107
+ /*=================================================*/
108
+
109
+ if ((c1 == NULL) && (c2 == NULL))
110
+ {
111
+ rv = GetConstraintRecord(theEnv);
112
+ rv->multifieldsAllowed = true;
113
+ return(rv);
114
+ }
115
+
116
+ /*=================================================*/
117
+ /* If one of the constraint records is NULL, then */
118
+ /* the intersection is the other constraint record */
119
+ /* (a NULL value means no constraints). */
120
+ /*=================================================*/
121
+
122
+ if (c1 == NULL) return(CopyConstraintRecord(theEnv,c2));
123
+
124
+ if (c2 == NULL) return(CopyConstraintRecord(theEnv,c1));
125
+
126
+ /*=================================*/
127
+ /* Create a new constraint record. */
128
+ /*=================================*/
129
+
130
+ rv = GetConstraintRecord(theEnv);
131
+
132
+ /*==============================*/
133
+ /* Intersect the allowed types. */
134
+ /*==============================*/
135
+
136
+ if ((c1->multifieldsAllowed != c2->multifieldsAllowed) &&
137
+ (c1->singlefieldsAllowed != c2->singlefieldsAllowed))
138
+ {
139
+ rv->anyAllowed = false;
140
+ return(rv);
141
+ }
142
+
143
+ if (c1->multifieldsAllowed && c2->multifieldsAllowed)
144
+ { rv->multifieldsAllowed = true; }
145
+ else
146
+ { rv->multifieldsAllowed = false; }
147
+
148
+ if (c1->singlefieldsAllowed && c2->singlefieldsAllowed)
149
+ { rv->singlefieldsAllowed = true; }
150
+ else
151
+ { rv->singlefieldsAllowed = false; }
152
+
153
+ if (c1->anyAllowed && c2->anyAllowed) rv->anyAllowed = true;
154
+ else
155
+ {
156
+ if (c1->anyAllowed)
157
+ {
158
+ c1Changed = true;
159
+ SetAnyAllowedFlags(c1,false);
160
+ }
161
+ else if (c2->anyAllowed)
162
+ {
163
+ c2Changed = true;
164
+ SetAnyAllowedFlags(c2,false);
165
+ }
166
+
167
+ rv->anyAllowed = false;
168
+ rv->symbolsAllowed = (c1->symbolsAllowed && c2->symbolsAllowed);
169
+ rv->stringsAllowed = (c1->stringsAllowed && c2->stringsAllowed);
170
+ rv->floatsAllowed = (c1->floatsAllowed && c2->floatsAllowed);
171
+ rv->integersAllowed = (c1->integersAllowed && c2->integersAllowed);
172
+ rv->instanceNamesAllowed = (c1->instanceNamesAllowed && c2->instanceNamesAllowed);
173
+ rv->instanceAddressesAllowed = (c1->instanceAddressesAllowed && c2->instanceAddressesAllowed);
174
+ rv->externalAddressesAllowed = (c1->externalAddressesAllowed && c2->externalAddressesAllowed);
175
+ rv->voidAllowed = (c1->voidAllowed && c2->voidAllowed);
176
+ rv->multifieldsAllowed = (c1->multifieldsAllowed && c2->multifieldsAllowed);
177
+ rv->factAddressesAllowed = (c1->factAddressesAllowed && c2->factAddressesAllowed);
178
+
179
+ if (c1Changed) SetAnyAllowedFlags(c1,true);
180
+ if (c2Changed) SetAnyAllowedFlags(c2,true);
181
+ }
182
+
183
+ /*=====================================*/
184
+ /* Intersect the allowed-values flags. */
185
+ /*=====================================*/
186
+
187
+ if (c1->anyRestriction || c2->anyRestriction) rv->anyRestriction = true;
188
+ else
189
+ {
190
+ rv->anyRestriction = false;
191
+ rv->symbolRestriction = (c1->symbolRestriction || c2->symbolRestriction);
192
+ rv->stringRestriction = (c1->stringRestriction || c2->stringRestriction);
193
+ rv->floatRestriction = (c1->floatRestriction || c2->floatRestriction);
194
+ rv->integerRestriction = (c1->integerRestriction || c2->integerRestriction);
195
+ rv->classRestriction = (c1->classRestriction || c2->classRestriction);
196
+ rv->instanceNameRestriction = (c1->instanceNameRestriction || c2->instanceNameRestriction);
197
+ }
198
+
199
+ /*==================================================*/
200
+ /* Intersect the allowed values list, allowed class */
201
+ /* list, min and max values, and the range values. */
202
+ /*==================================================*/
203
+
204
+ IntersectAllowedValueExpressions(theEnv,c1,c2,rv);
205
+ IntersectAllowedClassExpressions(theEnv,c1,c2,rv);
206
+ IntersectNumericExpressions(theEnv,c1,c2,rv,true);
207
+ IntersectNumericExpressions(theEnv,c1,c2,rv,false);
208
+
209
+ /*==========================================*/
210
+ /* Update the allowed-values flags based on */
211
+ /* the previous intersection for allowed, */
212
+ /* min and max, and range values. */
213
+ /*==========================================*/
214
+
215
+ UpdateRestrictionFlags(rv);
216
+
217
+ /*============================================*/
218
+ /* If multifields are allowed, then intersect */
219
+ /* the constraint record for them. */
220
+ /*============================================*/
221
+
222
+ if (rv->multifieldsAllowed)
223
+ {
224
+ rv->multifield = IntersectConstraints(theEnv,c1->multifield,c2->multifield);
225
+ if (UnmatchableConstraint(rv->multifield))
226
+ { rv->multifieldsAllowed = false; }
227
+ }
228
+
229
+ /*========================*/
230
+ /* Return the intersected */
231
+ /* constraint record. */
232
+ /*========================*/
233
+
234
+ return(rv);
235
+ }
236
+
237
+ /*************************************************/
238
+ /* IntersectAllowedValueExpressions: Creates the */
239
+ /* intersection of two allowed-values lists. */
240
+ /*************************************************/
241
+ static void IntersectAllowedValueExpressions(
242
+ Environment *theEnv,
243
+ CONSTRAINT_RECORD *constraint1,
244
+ CONSTRAINT_RECORD *constraint2,
245
+ CONSTRAINT_RECORD *newConstraint)
246
+ {
247
+ struct expr *theList1, *theList2;
248
+ struct expr *theHead = NULL, *tmpExpr;
249
+
250
+ /*===========================================*/
251
+ /* Loop through each value in allowed-values */
252
+ /* list of the first constraint record. Add */
253
+ /* each value to a list if it satisfies the */
254
+ /* restrictions for both constraint records. */
255
+ /*===========================================*/
256
+
257
+ for (theList1 = constraint1->restrictionList;
258
+ theList1 != NULL;
259
+ theList1 = theList1->nextArg)
260
+ {
261
+ if (CheckAllowedValuesConstraint(theList1->type,theList1->value,constraint1) &&
262
+ CheckAllowedValuesConstraint(theList1->type,theList1->value,constraint2))
263
+ {
264
+ tmpExpr = GenConstant(theEnv,theList1->type,theList1->value);
265
+ tmpExpr->nextArg = theHead;
266
+ theHead = tmpExpr;
267
+ }
268
+ }
269
+
270
+ /*===========================================*/
271
+ /* Loop through each value in allowed-values */
272
+ /* list of the second constraint record. Add */
273
+ /* each value to a list if it satisfies the */
274
+ /* restrictions for both constraint records. */
275
+ /*===========================================*/
276
+
277
+ for (theList2 = constraint2->restrictionList;
278
+ theList2 != NULL;
279
+ theList2 = theList2->nextArg)
280
+ {
281
+ if (FindItemInExpression(theList2->type,theList2->value,true,theHead))
282
+ { /* The value is already in the list--Do nothing */ }
283
+ else if (CheckAllowedValuesConstraint(theList2->type,theList2->value,constraint1) &&
284
+ CheckAllowedValuesConstraint(theList2->type,theList2->value,constraint2))
285
+ {
286
+ tmpExpr = GenConstant(theEnv,theList2->type,theList2->value);
287
+ tmpExpr->nextArg = theHead;
288
+ theHead = tmpExpr;
289
+ }
290
+ }
291
+
292
+ /*================================================*/
293
+ /* Set the allowed values list for the constraint */
294
+ /* record to the intersected values of the two */
295
+ /* other constraint records. */
296
+ /*================================================*/
297
+
298
+ newConstraint->restrictionList = theHead;
299
+ }
300
+
301
+ /*************************************************/
302
+ /* IntersectAllowedClassExpressions: Creates the */
303
+ /* intersection of two allowed-classes lists. */
304
+ /*************************************************/
305
+ static void IntersectAllowedClassExpressions(
306
+ Environment *theEnv,
307
+ CONSTRAINT_RECORD *constraint1,
308
+ CONSTRAINT_RECORD *constraint2,
309
+ CONSTRAINT_RECORD *newConstraint)
310
+ {
311
+ struct expr *theList1, *theList2;
312
+ struct expr *theHead = NULL, *tmpExpr;
313
+
314
+ /*============================================*/
315
+ /* Loop through each value in allowed-classes */
316
+ /* list of the first constraint record. Add */
317
+ /* each value to a list if it satisfies the */
318
+ /* restrictions for both constraint records. */
319
+ /*============================================*/
320
+
321
+ for (theList1 = constraint1->classList;
322
+ theList1 != NULL;
323
+ theList1 = theList1->nextArg)
324
+ {
325
+ if (CheckAllowedClassesConstraint(theEnv,theList1->type,theList1->value,constraint1) &&
326
+ CheckAllowedClassesConstraint(theEnv,theList1->type,theList1->value,constraint2))
327
+ {
328
+ tmpExpr = GenConstant(theEnv,theList1->type,theList1->value);
329
+ tmpExpr->nextArg = theHead;
330
+ theHead = tmpExpr;
331
+ }
332
+ }
333
+
334
+ /*============================================*/
335
+ /* Loop through each value in allowed-classes */
336
+ /* list of the second constraint record. Add */
337
+ /* each value to a list if it satisfies the */
338
+ /* restrictions for both constraint records. */
339
+ /*============================================*/
340
+
341
+ for (theList2 = constraint2->classList;
342
+ theList2 != NULL;
343
+ theList2 = theList2->nextArg)
344
+ {
345
+ if (FindItemInExpression(theList2->type,theList2->value,true,theHead))
346
+ { /* The value is already in the list--Do nothing */ }
347
+ else if (CheckAllowedClassesConstraint(theEnv,theList2->type,theList2->value,constraint1) &&
348
+ CheckAllowedClassesConstraint(theEnv,theList2->type,theList2->value,constraint2))
349
+ {
350
+ tmpExpr = GenConstant(theEnv,theList2->type,theList2->value);
351
+ tmpExpr->nextArg = theHead;
352
+ theHead = tmpExpr;
353
+ }
354
+ }
355
+
356
+ /*=================================================*/
357
+ /* Set the allowed classes list for the constraint */
358
+ /* record to the intersected values of the two */
359
+ /* other constraint records. */
360
+ /*=================================================*/
361
+
362
+ newConstraint->classList = theHead;
363
+ }
364
+
365
+ /*********************************************************/
366
+ /* IntersectNumericExpressions: Creates the intersection */
367
+ /* of two range or two min/max-fields constraints. */
368
+ /*********************************************************/
369
+ static void IntersectNumericExpressions(
370
+ Environment *theEnv,
371
+ CONSTRAINT_RECORD *constraint1,
372
+ CONSTRAINT_RECORD *constraint2,
373
+ CONSTRAINT_RECORD *newConstraint,
374
+ bool range)
375
+ {
376
+ struct expr *tmpmin1, *tmpmax1, *tmpmin2, *tmpmax2, *theMin, *theMax;
377
+ struct expr *theMinList, *theMaxList, *lastMin = NULL, *lastMax = NULL;
378
+ int cmaxmax, cminmin, cmaxmin, cminmax;
379
+
380
+ /*==========================================*/
381
+ /* Initialize the new range/min/max values */
382
+ /* for the intersection of the constraints. */
383
+ /*==========================================*/
384
+
385
+ theMinList = NULL;
386
+ theMaxList = NULL;
387
+
388
+ /*=================================*/
389
+ /* Determine the min/max values of */
390
+ /* the first constraint record. */
391
+ /*=================================*/
392
+
393
+ if (range)
394
+ {
395
+ tmpmin1 = constraint1->minValue;
396
+ tmpmax1 = constraint1->maxValue;
397
+ }
398
+ else
399
+ {
400
+ tmpmin1 = constraint1->minFields;
401
+ tmpmax1 = constraint1->maxFields;
402
+ }
403
+
404
+ /*===========================================*/
405
+ /* Loop through each of range/min/max values */
406
+ /* from the first constraint record. */
407
+ /*===========================================*/
408
+
409
+ for (;
410
+ tmpmin1 != NULL;
411
+ tmpmin1 = tmpmin1->nextArg, tmpmax1 = tmpmax1->nextArg)
412
+ {
413
+ /*============================================*/
414
+ /* Get the appropriate values from the second */
415
+ /* constraint record for comparison. */
416
+ /*============================================*/
417
+
418
+ if (range)
419
+ {
420
+ tmpmin2 = constraint2->minValue;
421
+ tmpmax2 = constraint2->maxValue;
422
+ }
423
+ else
424
+ {
425
+ tmpmin2 = constraint2->minFields;
426
+ tmpmax2 = constraint2->maxFields;
427
+ }
428
+
429
+ /*================================================*/
430
+ /* Loop through each of range/min/max values from */
431
+ /* the second constraint record comparing it to */
432
+ /* the values from the first constraint record. */
433
+ /*================================================*/
434
+
435
+ for (;
436
+ tmpmin2 != NULL;
437
+ tmpmin2 = tmpmin2->nextArg, tmpmax2 = tmpmax2->nextArg)
438
+ {
439
+ /*==============================================*/
440
+ /* Determine the relationship between the four */
441
+ /* combinations of min/max values (>, <, or =). */
442
+ /*==============================================*/
443
+
444
+ cmaxmax = CompareNumbers(theEnv,tmpmax1->type,tmpmax1->value,
445
+ tmpmax2->type,tmpmax2->value);
446
+
447
+ cminmin = CompareNumbers(theEnv,tmpmin1->type,tmpmin1->value,
448
+ tmpmin2->type,tmpmin2->value);
449
+
450
+ cmaxmin = CompareNumbers(theEnv,tmpmax1->type,tmpmax1->value,
451
+ tmpmin2->type,tmpmin2->value);
452
+
453
+ cminmax = CompareNumbers(theEnv,tmpmin1->type,tmpmin1->value,
454
+ tmpmax2->type,tmpmax2->value);
455
+
456
+ /*============================================*/
457
+ /* If the range/min/max values don't overlap, */
458
+ /* then proceed to the next pair of numbers */
459
+ /* to see if they overlap. */
460
+ /*============================================*/
461
+
462
+ if ((cmaxmin == LESS_THAN) || (cminmax == GREATER_THAN))
463
+ { continue; }
464
+
465
+ /*=======================================*/
466
+ /* Compute the new minimum value for the */
467
+ /* intersected range/min/max values. */
468
+ /*=======================================*/
469
+
470
+ if (cminmin == GREATER_THAN)
471
+ { theMin = GenConstant(theEnv,tmpmin1->type,tmpmin1->value); }
472
+ else
473
+ { theMin = GenConstant(theEnv,tmpmin2->type,tmpmin2->value); }
474
+
475
+ /*=======================================*/
476
+ /* Compute the new maximum value for the */
477
+ /* intersected range/min/max values. */
478
+ /*=======================================*/
479
+
480
+ if (cmaxmax == LESS_THAN)
481
+ { theMax = GenConstant(theEnv,tmpmax1->type,tmpmax1->value); }
482
+ else
483
+ { theMax = GenConstant(theEnv,tmpmax2->type,tmpmax2->value); }
484
+
485
+ /*==================================*/
486
+ /* Add the new range/min/max values */
487
+ /* to the intersection list. */
488
+ /*==================================*/
489
+
490
+ if (lastMin == NULL)
491
+ {
492
+ theMinList = theMin;
493
+ theMaxList = theMax;
494
+ }
495
+ else
496
+ {
497
+ lastMin->nextArg = theMin;
498
+ lastMax->nextArg = theMax;
499
+ }
500
+
501
+ lastMin = theMin;
502
+ lastMax = theMax;
503
+ }
504
+ }
505
+
506
+ /*============================================================*/
507
+ /* If the intersection produced a pair of valid range/min/max */
508
+ /* values, then replace the previous values of the constraint */
509
+ /* record to the new intersected values. */
510
+ /*============================================================*/
511
+
512
+ if (theMinList != NULL)
513
+ {
514
+ if (range)
515
+ {
516
+ ReturnExpression(theEnv,newConstraint->minValue);
517
+ ReturnExpression(theEnv,newConstraint->maxValue);
518
+ newConstraint->minValue = theMinList;
519
+ newConstraint->maxValue = theMaxList;
520
+ }
521
+ else
522
+ {
523
+ ReturnExpression(theEnv,newConstraint->minFields);
524
+ ReturnExpression(theEnv,newConstraint->maxFields);
525
+ newConstraint->minFields = theMinList;
526
+ newConstraint->maxFields = theMaxList;
527
+ }
528
+ }
529
+
530
+ /*===============================================================*/
531
+ /* Otherwise, the intersection produced no valid range/min/max */
532
+ /* values. For the range attribute, this means that no numbers */
533
+ /* can satisfy the constraint. For the min/max fields attribute, */
534
+ /* it means that no value can satisfy the constraint. */
535
+ /*===============================================================*/
536
+
537
+ else
538
+ {
539
+ if (range)
540
+ {
541
+ if (newConstraint->anyAllowed) SetAnyAllowedFlags(newConstraint,false);
542
+ newConstraint->integersAllowed = false;
543
+ newConstraint->floatsAllowed = false;
544
+ }
545
+ else
546
+ {
547
+ SetAnyAllowedFlags(newConstraint,true);
548
+ newConstraint->singlefieldsAllowed = false;
549
+ newConstraint->multifieldsAllowed = false;
550
+ newConstraint->anyAllowed = false;
551
+ }
552
+ }
553
+ }
554
+
555
+ /************************************************************/
556
+ /* UpdateRestrictionFlags: Updates the types allowed flags */
557
+ /* based on the allowed values in a constraint record. */
558
+ /* Intended to be called after the allowed values list */
559
+ /* has been changed (for example after intersecting the */
560
+ /* allowed-values list there may no be any values of a */
561
+ /* particular type left even though the type is allowed). */
562
+ /************************************************************/
563
+ static void UpdateRestrictionFlags(
564
+ CONSTRAINT_RECORD *rv)
565
+ {
566
+ if ((rv->anyRestriction) && (rv->restrictionList == NULL))
567
+ {
568
+ SetAnyAllowedFlags(rv,true);
569
+ rv->anyAllowed = false;
570
+ }
571
+
572
+ if ((rv->symbolRestriction) && (rv->symbolsAllowed))
573
+ { rv->symbolsAllowed = FindItemInExpression(SYMBOL_TYPE,NULL,false,rv->restrictionList); }
574
+
575
+ if ((rv->stringRestriction) && (rv->stringsAllowed))
576
+ { rv->stringsAllowed = FindItemInExpression(STRING_TYPE,NULL,false,rv->restrictionList); }
577
+
578
+ if ((rv->floatRestriction) && (rv->floatsAllowed))
579
+ { rv->floatsAllowed = FindItemInExpression(FLOAT_TYPE,NULL,false,rv->restrictionList); }
580
+
581
+ if ((rv->integerRestriction) && (rv->integersAllowed))
582
+ { rv->integersAllowed = FindItemInExpression(INTEGER_TYPE,NULL,false,rv->restrictionList); }
583
+
584
+ if ((rv->instanceNameRestriction) && (rv->instanceNamesAllowed))
585
+ { rv->instanceNamesAllowed = FindItemInExpression(INSTANCE_NAME_TYPE,NULL,false,rv->restrictionList); }
586
+ }
587
+
588
+ /*************************************************************/
589
+ /* FindItemInExpression: Determines if a particular constant */
590
+ /* (such as 27) or a class of constants (such as integers) */
591
+ /* can be found in a list of constants. Returns true if */
592
+ /* such a constant can be found, otherwise false. */
593
+ /*************************************************************/
594
+ static bool FindItemInExpression(
595
+ int theType,
596
+ void *theValue,
597
+ bool useValue,
598
+ struct expr *theList)
599
+ {
600
+ while (theList != NULL)
601
+ {
602
+ if (theList->type == theType)
603
+ {
604
+ if (! useValue) return true;
605
+ else if (theList->value == theValue) return true;
606
+ }
607
+
608
+ theList = theList->nextArg;
609
+ }
610
+
611
+ return false;
612
+ }
613
+
614
+ /**************************************************/
615
+ /* RestrictionOnType: Determines if a restriction */
616
+ /* is present for a specific type. Returns true */
617
+ /* if there is, otherwise false. */
618
+ /**************************************************/
619
+ static bool RestrictionOnType(
620
+ int theType,
621
+ CONSTRAINT_RECORD *theConstraint)
622
+ {
623
+ if (theConstraint == NULL) return false;
624
+
625
+ if ((theConstraint->anyRestriction) ||
626
+ (theConstraint->symbolRestriction && (theType == SYMBOL_TYPE)) ||
627
+ (theConstraint->stringRestriction && (theType == STRING_TYPE)) ||
628
+ (theConstraint->floatRestriction && (theType == FLOAT_TYPE)) ||
629
+ (theConstraint->integerRestriction && (theType == INTEGER_TYPE)) ||
630
+ (theConstraint->classRestriction && ((theType == INSTANCE_ADDRESS_TYPE) ||
631
+ (theType == INSTANCE_NAME_TYPE))) ||
632
+ (theConstraint->instanceNameRestriction && (theType == INSTANCE_NAME_TYPE)))
633
+ { return true; }
634
+
635
+ return false;
636
+ }
637
+
638
+ /**********************************************************/
639
+ /* UnionConstraints: Creates a new constraint record that */
640
+ /* is the union of two other constraint records. */
641
+ /**********************************************************/
642
+ struct constraintRecord *UnionConstraints(
643
+ Environment *theEnv,
644
+ CONSTRAINT_RECORD *c1,
645
+ CONSTRAINT_RECORD *c2)
646
+ {
647
+ struct constraintRecord *rv;
648
+ bool c1Changed = false, c2Changed = false;
649
+
650
+ /*=================================================*/
651
+ /* If both constraint records are NULL,then create */
652
+ /* a constraint record that allows any value. */
653
+ /*=================================================*/
654
+
655
+ if ((c1 == NULL) && (c2 == NULL)) return(GetConstraintRecord(theEnv));
656
+
657
+ /*=====================================================*/
658
+ /* If one of the constraint records is NULL, then the */
659
+ /* union is the other constraint record. Note that */
660
+ /* this is different from the way that intersections */
661
+ /* were handled (a NULL constraint record implied that */
662
+ /* any value was legal which in turn would imply that */
663
+ /* the union would allow any value as well). */
664
+ /*=====================================================*/
665
+
666
+ if (c1 == NULL) return(CopyConstraintRecord(theEnv,c2));
667
+
668
+ if (c2 == NULL) return(CopyConstraintRecord(theEnv,c1));
669
+
670
+ /*=================================*/
671
+ /* Create a new constraint record. */
672
+ /*=================================*/
673
+
674
+ rv = GetConstraintRecord(theEnv);
675
+
676
+ /*==========================*/
677
+ /* Union the allowed types. */
678
+ /*==========================*/
679
+
680
+ if (c1->multifieldsAllowed || c2->multifieldsAllowed)
681
+ { rv->multifieldsAllowed = true; }
682
+
683
+ if (c1->singlefieldsAllowed || c2->singlefieldsAllowed)
684
+ { rv->singlefieldsAllowed = true; }
685
+
686
+ if (c1->anyAllowed || c2->anyAllowed) rv->anyAllowed = true;
687
+ else
688
+ {
689
+ rv->anyAllowed = false;
690
+ rv->symbolsAllowed = (c1->symbolsAllowed || c2->symbolsAllowed);
691
+ rv->stringsAllowed = (c1->stringsAllowed || c2->stringsAllowed);
692
+ rv->floatsAllowed = (c1->floatsAllowed || c2->floatsAllowed);
693
+ rv->integersAllowed = (c1->integersAllowed || c2->integersAllowed);
694
+ rv->instanceNamesAllowed = (c1->instanceNamesAllowed || c2->instanceNamesAllowed);
695
+ rv->instanceAddressesAllowed = (c1->instanceAddressesAllowed || c2->instanceAddressesAllowed);
696
+ rv->externalAddressesAllowed = (c1->externalAddressesAllowed || c2->externalAddressesAllowed);
697
+ rv->voidAllowed = (c1->voidAllowed || c2->voidAllowed);
698
+ rv->factAddressesAllowed = (c1->factAddressesAllowed || c2->factAddressesAllowed);
699
+ }
700
+
701
+ /*=================================*/
702
+ /* Union the allowed-values flags. */
703
+ /*=================================*/
704
+
705
+ if (c1->anyRestriction && c2->anyRestriction) rv->anyRestriction = true;
706
+ else
707
+ {
708
+ if (c1->anyRestriction)
709
+ {
710
+ c1Changed = true;
711
+ SetAnyRestrictionFlags(c1,false);
712
+ }
713
+ else if (c2->anyRestriction)
714
+ {
715
+ c2Changed = true;
716
+ SetAnyRestrictionFlags(c2,false);
717
+ }
718
+
719
+ rv->anyRestriction = false;
720
+ rv->symbolRestriction = (c1->symbolRestriction && c2->symbolRestriction);
721
+ rv->stringRestriction = (c1->stringRestriction && c2->stringRestriction);
722
+ rv->floatRestriction = (c1->floatRestriction && c2->floatRestriction);
723
+ rv->integerRestriction = (c1->integerRestriction && c2->integerRestriction);
724
+ rv->classRestriction = (c1->classRestriction && c2->classRestriction);
725
+ rv->instanceNameRestriction = (c1->instanceNameRestriction && c2->instanceNameRestriction);
726
+
727
+ if (c1Changed) SetAnyRestrictionFlags(c1,false);
728
+ else if (c2Changed) SetAnyRestrictionFlags(c2,false);
729
+ }
730
+
731
+ /*========================================*/
732
+ /* Union the allowed values list, the min */
733
+ /* and max values, and the range values. */
734
+ /*========================================*/
735
+
736
+ UnionAllowedValueExpressions(theEnv,c1,c2,rv);
737
+ UnionAllowedClassExpressions(theEnv,c1,c2,rv);
738
+ UnionNumericExpressions(theEnv,c1,c2,rv,true);
739
+ UnionNumericExpressions(theEnv,c1,c2,rv,false);
740
+
741
+ /*========================================*/
742
+ /* If multifields are allowed, then union */
743
+ /* the constraint record for them. */
744
+ /*========================================*/
745
+
746
+ if (rv->multifieldsAllowed)
747
+ { rv->multifield = UnionConstraints(theEnv,c1->multifield,c2->multifield); }
748
+
749
+ /*====================*/
750
+ /* Return the unioned */
751
+ /* constraint record. */
752
+ /*====================*/
753
+
754
+ return(rv);
755
+ }
756
+
757
+ /**************************************************/
758
+ /* UnionNumericExpressions: Creates the union of */
759
+ /* two range or two min/max-fields constraints. */
760
+ /**************************************************/
761
+ static void UnionNumericExpressions(
762
+ Environment *theEnv,
763
+ CONSTRAINT_RECORD *constraint1,
764
+ CONSTRAINT_RECORD *constraint2,
765
+ CONSTRAINT_RECORD *newConstraint,
766
+ bool range)
767
+ {
768
+ struct expr *tmpmin, *tmpmax;
769
+ struct expr *theMinList, *theMaxList;
770
+
771
+ /*=========================================*/
772
+ /* Initialize the new range/min/max values */
773
+ /* for the union of the constraints. */
774
+ /*=========================================*/
775
+
776
+ theMinList = NULL;
777
+ theMaxList = NULL;
778
+
779
+ /*=================================*/
780
+ /* Determine the min/max values of */
781
+ /* the first constraint record. */
782
+ /*=================================*/
783
+
784
+ if (range)
785
+ {
786
+ tmpmin = constraint1->minValue;
787
+ tmpmax = constraint1->maxValue;
788
+ }
789
+ else
790
+ {
791
+ tmpmin = constraint1->minFields;
792
+ tmpmax = constraint1->maxFields;
793
+ }
794
+
795
+ /*============================================*/
796
+ /* Add each range/min/max pair from the first */
797
+ /* constraint record to the union list. */
798
+ /*============================================*/
799
+
800
+ for (;
801
+ tmpmin != NULL;
802
+ tmpmin = tmpmin->nextArg,tmpmax = tmpmax->nextArg)
803
+ { UnionRangeMinMaxValueWithList(theEnv,tmpmin,tmpmax,&theMinList,&theMaxList); }
804
+
805
+ /*=================================*/
806
+ /* Determine the min/max values of */
807
+ /* the second constraint record. */
808
+ /*=================================*/
809
+
810
+ if (range)
811
+ {
812
+ tmpmin = constraint2->minValue;
813
+ tmpmax = constraint2->maxValue;
814
+ }
815
+ else
816
+ {
817
+ tmpmin = constraint2->minFields;
818
+ tmpmax = constraint2->maxFields;
819
+ }
820
+
821
+ /*=============================================*/
822
+ /* Add each range/min/max pair from the second */
823
+ /* constraint record to the union list. */
824
+ /*=============================================*/
825
+
826
+ for (;
827
+ tmpmin != NULL;
828
+ tmpmin = tmpmin->nextArg,tmpmax = tmpmax->nextArg)
829
+ { UnionRangeMinMaxValueWithList(theEnv,tmpmin,tmpmax,&theMinList,&theMaxList); }
830
+
831
+ /*=====================================================*/
832
+ /* If the union produced a pair of valid range/min/max */
833
+ /* values, then replace the previous values of the */
834
+ /* constraint record to the new unioned values. */
835
+ /*=====================================================*/
836
+
837
+ if (theMinList != NULL)
838
+ {
839
+ if (range)
840
+ {
841
+ ReturnExpression(theEnv,newConstraint->minValue);
842
+ ReturnExpression(theEnv,newConstraint->maxValue);
843
+ newConstraint->minValue = theMinList;
844
+ newConstraint->maxValue = theMaxList;
845
+ }
846
+ else
847
+ {
848
+ ReturnExpression(theEnv,newConstraint->minFields);
849
+ ReturnExpression(theEnv,newConstraint->maxFields);
850
+ newConstraint->minFields = theMinList;
851
+ newConstraint->maxFields = theMaxList;
852
+ }
853
+ }
854
+
855
+ /*==============================================================*/
856
+ /* Otherwise, the union produced no valid range/min/max values. */
857
+ /* For the range attribute, this means that no numbers can */
858
+ /* satisfy the constraint. For the min/max fields attribute, it */
859
+ /* means that no value can satisfy the constraint. */
860
+ /*==============================================================*/
861
+
862
+ else
863
+ {
864
+ if (range)
865
+ {
866
+ if (newConstraint->anyAllowed) SetAnyAllowedFlags(newConstraint,false);
867
+ newConstraint->integersAllowed = false;
868
+ newConstraint->floatsAllowed = false;
869
+ }
870
+ else
871
+ {
872
+ SetAnyAllowedFlags(newConstraint,true);
873
+ newConstraint->anyAllowed = true;
874
+ }
875
+ }
876
+ }
877
+
878
+ /*********************************************************/
879
+ /* UnionRangeMinMaxValueWithList: Unions a range/min/max */
880
+ /* pair of values with a list of such values. */
881
+ /*********************************************************/
882
+ static void UnionRangeMinMaxValueWithList(
883
+ Environment *theEnv,
884
+ struct expr *addmin,
885
+ struct expr *addmax,
886
+ struct expr **theMinList,
887
+ struct expr **theMaxList)
888
+ {
889
+ struct expr *tmpmin, *tmpmax, *lastmin, *lastmax;
890
+ struct expr *themin, *themax, *nextmin, *nextmax;
891
+ int cmaxmin, cmaxmax, cminmin, cminmax;
892
+
893
+ /*=========================================================*/
894
+ /* If no values are on the lists, then use the new values. */
895
+ /*=========================================================*/
896
+
897
+ if (*theMinList == NULL)
898
+ {
899
+ *theMinList = GenConstant(theEnv,addmin->type,addmin->value);
900
+ *theMaxList = GenConstant(theEnv,addmax->type,addmax->value);
901
+ return;
902
+ }
903
+
904
+ lastmin = NULL;
905
+ lastmax = NULL;
906
+ tmpmin = (*theMinList);
907
+ tmpmax = (*theMaxList);
908
+
909
+ while (tmpmin != NULL)
910
+ {
911
+ cmaxmax = CompareNumbers(theEnv,addmax->type,addmax->value,
912
+ tmpmax->type,tmpmax->value);
913
+
914
+ cminmin = CompareNumbers(theEnv,addmin->type,addmin->value,
915
+ tmpmin->type,tmpmin->value);
916
+
917
+ cmaxmin = CompareNumbers(theEnv,addmax->type,addmax->value,
918
+ tmpmin->type,tmpmin->value);
919
+
920
+ cminmax = CompareNumbers(theEnv,addmin->type,addmin->value,
921
+ tmpmax->type,tmpmax->value);
922
+
923
+ /*=================================*/
924
+ /* Check to see if the range is */
925
+ /* contained within another range. */
926
+ /*=================================*/
927
+
928
+ if (((cmaxmax == LESS_THAN) || (cmaxmax == EQUAL)) &&
929
+ ((cminmin == GREATER_THAN) || (cminmin == EQUAL)))
930
+ { return; }
931
+
932
+ /*================================*/
933
+ /* Extend the greater than range. */
934
+ /*================================*/
935
+
936
+ if ((cmaxmax == GREATER_THAN) &&
937
+ ((cminmax == LESS_THAN) || (cminmax == EQUAL)))
938
+ {
939
+ tmpmax->type = addmax->type;
940
+ tmpmax->value = addmax->value;
941
+ }
942
+
943
+ /*=============================*/
944
+ /* Extend the less than range. */
945
+ /*=============================*/
946
+
947
+ if ((cminmin == LESS_THAN) &&
948
+ ((cmaxmin == GREATER_THAN) || (cmaxmin == EQUAL)))
949
+ {
950
+ tmpmin->type = addmin->type;
951
+ tmpmin->value = addmin->value;
952
+ }
953
+
954
+ /*====================*/
955
+ /* Handle insertions. */
956
+ /*====================*/
957
+
958
+ if (cmaxmin == LESS_THAN)
959
+ {
960
+ if (lastmax == NULL)
961
+ {
962
+ themin = GenConstant(theEnv,addmin->type,addmin->value);
963
+ themax = GenConstant(theEnv,addmax->type,addmax->value);
964
+ themin->nextArg = *theMinList;
965
+ themax->nextArg = *theMaxList;
966
+ *theMinList = themin;
967
+ *theMaxList = themax;
968
+ return;
969
+ }
970
+
971
+ if (CompareNumbers(theEnv,addmin->type,addmin->value,
972
+ lastmax->type,lastmax->value) == GREATER_THAN)
973
+ {
974
+ themin = GenConstant(theEnv,addmin->type,addmin->value);
975
+ themax = GenConstant(theEnv,addmax->type,addmax->value);
976
+
977
+ themin->nextArg = lastmin->nextArg;
978
+ themax->nextArg = lastmax->nextArg;
979
+
980
+ lastmin->nextArg = themin;
981
+ lastmax->nextArg = themax;
982
+ return;
983
+ }
984
+ }
985
+
986
+ /*==========================*/
987
+ /* Move on to the next one. */
988
+ /*==========================*/
989
+
990
+ tmpmin = tmpmin->nextArg;
991
+ tmpmax = tmpmax->nextArg;
992
+ }
993
+
994
+ /*===========================*/
995
+ /* Merge overlapping ranges. */
996
+ /*===========================*/
997
+
998
+ tmpmin = (*theMinList);
999
+ tmpmax = (*theMaxList);
1000
+
1001
+ while (tmpmin != NULL)
1002
+ {
1003
+ nextmin = tmpmin->nextArg;
1004
+ nextmax = tmpmax->nextArg;
1005
+ if (nextmin != NULL)
1006
+ {
1007
+ cmaxmin = CompareNumbers(theEnv,tmpmax->type,tmpmax->value,
1008
+ nextmin->type,nextmin->value);
1009
+ if ((cmaxmin == GREATER_THAN) || (cmaxmin == EQUAL))
1010
+ {
1011
+ tmpmax->type = nextmax->type;
1012
+ tmpmax->value = nextmax->value;
1013
+ tmpmax->nextArg = nextmax->nextArg;
1014
+ tmpmin->nextArg = nextmin->nextArg;
1015
+
1016
+ rtn_struct(theEnv,expr,nextmin);
1017
+ rtn_struct(theEnv,expr,nextmax);
1018
+ }
1019
+ else
1020
+ {
1021
+ tmpmin = tmpmin->nextArg;
1022
+ tmpmax = tmpmax->nextArg;
1023
+ }
1024
+ }
1025
+ else
1026
+ {
1027
+ tmpmin = nextmin;
1028
+ tmpmax = nextmax;
1029
+ }
1030
+ }
1031
+ }
1032
+
1033
+ /***************************************************/
1034
+ /* UnionAllowedClassExpressions: Creates the union */
1035
+ /* of two sets of allowed-classes expressions. */
1036
+ /***************************************************/
1037
+ static void UnionAllowedClassExpressions(
1038
+ Environment *theEnv,
1039
+ CONSTRAINT_RECORD *constraint1,
1040
+ CONSTRAINT_RECORD *constraint2,
1041
+ CONSTRAINT_RECORD *newConstraint)
1042
+ {
1043
+ struct expr *theHead = NULL;
1044
+
1045
+ theHead = AddToUnionList(theEnv,constraint1->classList,theHead,newConstraint);
1046
+ theHead = AddToUnionList(theEnv,constraint2->classList,theHead,newConstraint);
1047
+
1048
+ newConstraint->classList = theHead;
1049
+ }
1050
+
1051
+ /***************************************************/
1052
+ /* UnionAllowedValueExpressions: Creates the union */
1053
+ /* of two sets of allowed value expressions. */
1054
+ /***************************************************/
1055
+ static void UnionAllowedValueExpressions(
1056
+ Environment *theEnv,
1057
+ CONSTRAINT_RECORD *constraint1,
1058
+ CONSTRAINT_RECORD *constraint2,
1059
+ CONSTRAINT_RECORD *newConstraint)
1060
+ {
1061
+ struct expr *theHead = NULL;
1062
+
1063
+ theHead = AddToUnionList(theEnv,constraint1->restrictionList,theHead,newConstraint);
1064
+ theHead = AddToUnionList(theEnv,constraint2->restrictionList,theHead,newConstraint);
1065
+
1066
+ newConstraint->restrictionList = theHead;
1067
+ }
1068
+
1069
+ /************************************************************/
1070
+ /* AddToUnionList: Adds a list of values to a unioned list */
1071
+ /* making sure that duplicates are not added and that any */
1072
+ /* value added satisfies the constraints for the list. */
1073
+ /************************************************************/
1074
+ static struct expr *AddToUnionList(
1075
+ Environment *theEnv,
1076
+ struct expr *theList1,
1077
+ struct expr *theHead,
1078
+ CONSTRAINT_RECORD *theConstraint)
1079
+ {
1080
+ struct expr *theList2;
1081
+ bool flag;
1082
+
1083
+ /*======================================*/
1084
+ /* Loop through each value in the list */
1085
+ /* being added to the unioned set. */
1086
+ /*======================================*/
1087
+
1088
+ for (;theList1 != NULL; theList1 = theList1->nextArg)
1089
+ {
1090
+ /*===================================*/
1091
+ /* Determine if the value is already */
1092
+ /* in the unioned list. */
1093
+ /*===================================*/
1094
+
1095
+ flag = true;
1096
+ for (theList2 = theHead;
1097
+ theList2 != NULL;
1098
+ theList2 = theList2->nextArg)
1099
+ {
1100
+ if ((theList1->type == theList2->type) &&
1101
+ (theList1->value == theList2->value))
1102
+ {
1103
+ flag = false;
1104
+ break;
1105
+ }
1106
+ }
1107
+
1108
+ /*=====================================================*/
1109
+ /* If the value wasn't in the unioned list and doesn't */
1110
+ /* violate any of the unioned list's constraints, then */
1111
+ /* add it to the list. */
1112
+ /*=====================================================*/
1113
+
1114
+ if (flag)
1115
+ {
1116
+ if (RestrictionOnType(theList1->type,theConstraint))
1117
+ {
1118
+ theList2 = GenConstant(theEnv,theList1->type,theList1->value);
1119
+ theList2->nextArg = theHead;
1120
+ theHead = theList2;
1121
+ }
1122
+ }
1123
+ }
1124
+
1125
+ /*==============================*/
1126
+ /* Return the new unioned list. */
1127
+ /*==============================*/
1128
+
1129
+ return(theHead);
1130
+ }
1131
+
1132
+ #if (! BLOAD_ONLY)
1133
+
1134
+ /****************************************************/
1135
+ /* RemoveConstantFromConstraint: Removes a constant */
1136
+ /* value (including any duplicates) from the */
1137
+ /* restriction list of a constraint record. */
1138
+ /****************************************************/
1139
+ void RemoveConstantFromConstraint(
1140
+ Environment *theEnv,
1141
+ int theType,
1142
+ void *theValue,
1143
+ CONSTRAINT_RECORD *theConstraint)
1144
+ {
1145
+ struct expr *theList, *lastOne = NULL, *tmpList;
1146
+
1147
+ if (theConstraint == NULL) return;
1148
+
1149
+ theList = theConstraint->restrictionList;
1150
+ theConstraint->restrictionList = NULL;
1151
+
1152
+ while (theList != NULL)
1153
+ {
1154
+ if ((theList->type != theType) || (theList->value != theValue))
1155
+ {
1156
+ if (lastOne == NULL)
1157
+ { theConstraint->restrictionList = theList; }
1158
+ else
1159
+ { lastOne->nextArg = theList; }
1160
+ lastOne = theList;
1161
+ theList = theList->nextArg;
1162
+ lastOne->nextArg = NULL;
1163
+ }
1164
+ else
1165
+ {
1166
+ tmpList = theList;
1167
+ theList = theList->nextArg;
1168
+ tmpList->nextArg = NULL;
1169
+ ReturnExpression(theEnv,tmpList);
1170
+ }
1171
+ }
1172
+
1173
+ UpdateRestrictionFlags(theConstraint);
1174
+ }
1175
+
1176
+ #endif /* (! BLOAD_ONLY) */