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,850 @@
1
+ /*******************************************************/
2
+ /* "C" Language Integrated Production System */
3
+ /* */
4
+ /* CLIPS Version 6.40 07/30/16 */
5
+ /* */
6
+ /* MULTIPLE INHERITANCE PARSER MODULE */
7
+ /*******************************************************/
8
+
9
+ /*************************************************************/
10
+ /* Purpose: Parsing Routines for Multiple Inheritance */
11
+ /* */
12
+ /* Principal Programmer(s): */
13
+ /* Brian L. Dantes */
14
+ /* */
15
+ /* Contributing Programmer(s): */
16
+ /* */
17
+ /* Revision History: */
18
+ /* */
19
+ /* 6.30: Changed integer type/precision. */
20
+ /* */
21
+ /* Added const qualifiers to remove C++ */
22
+ /* deprecation warnings. */
23
+ /* */
24
+ /* 6.40: Pragma once and other inclusion changes. */
25
+ /* */
26
+ /* Added support for booleans with <stdbool.h>. */
27
+ /* */
28
+ /* Removed use of void pointers for specific */
29
+ /* data structures. */
30
+ /* */
31
+ /*************************************************************/
32
+
33
+ /* =========================================
34
+ *****************************************
35
+ EXTERNAL DEFINITIONS
36
+ =========================================
37
+ ***************************************** */
38
+ #include "setup.h"
39
+
40
+ #if OBJECT_SYSTEM && (! BLOAD_ONLY) && (! RUN_TIME)
41
+
42
+ #include "classcom.h"
43
+ #include "classfun.h"
44
+ #include "envrnmnt.h"
45
+ #include "memalloc.h"
46
+ #include "modulutl.h"
47
+ #include "pprint.h"
48
+ #include "prntutil.h"
49
+ #include "router.h"
50
+ #include "scanner.h"
51
+
52
+ #include "inherpsr.h"
53
+
54
+ /* =========================================
55
+ *****************************************
56
+ MACROS AND TYPES
57
+ =========================================
58
+ ***************************************** */
59
+ typedef struct partialOrder PARTIAL_ORDER;
60
+ typedef struct successor SUCCESSOR;
61
+
62
+ struct partialOrder
63
+ {
64
+ Defclass *cls;
65
+ unsigned pre;
66
+ SUCCESSOR *suc;
67
+ struct partialOrder *nxt;
68
+ };
69
+
70
+ struct successor
71
+ {
72
+ PARTIAL_ORDER *po;
73
+ struct successor *nxt;
74
+ };
75
+
76
+ /***************************************/
77
+ /* LOCAL INTERNAL FUNCTION DEFINITIONS */
78
+ /***************************************/
79
+
80
+ static PARTIAL_ORDER *InitializePartialOrderTable(Environment *,PARTIAL_ORDER *,PACKED_CLASS_LINKS *);
81
+ static void RecordPartialOrders(Environment *,PARTIAL_ORDER *,Defclass *,
82
+ PACKED_CLASS_LINKS *,unsigned long);
83
+ static PARTIAL_ORDER *FindPartialOrder(PARTIAL_ORDER *,Defclass *);
84
+ static void PrintPartialOrderLoop(Environment *,PARTIAL_ORDER *);
85
+ static void PrintClassLinks(Environment *,const char *,const char *,CLASS_LINK *);
86
+
87
+ /* =========================================
88
+ *****************************************
89
+ EXTERNALLY VISIBLE FUNCTIONS
90
+ =========================================
91
+ ***************************************** */
92
+
93
+ /**************************************************************
94
+ NAME : ParseSuperclasses
95
+ DESCRIPTION : Parses the (is-a <superclass>+) portion of
96
+ the (defclass ...) construct and returns
97
+ a list of direct superclasses. The
98
+ class "standard-class" is the precedence list
99
+ for classes with no direct superclasses.
100
+ The final precedence list (not calculated here)
101
+ will have the class in question first followed
102
+ by the merged precedence lists of its direct
103
+ superclasses.
104
+ INPUTS : 1) The logical name of the input source
105
+ 2) The symbolic name of the new class
106
+ RETURNS : The address of the superclass list
107
+ or NULL if there was an error
108
+ SIDE EFFECTS : None
109
+ NOTES : Assumes "(defclass <name> [<comment>] ("
110
+ has already been scanned.
111
+
112
+ All superclasses must be defined before
113
+ their subclasses. Duplicates in the (is-a
114
+ ...) list are are not allowed (a class may only
115
+ inherits from a superclass once).
116
+
117
+ This routine also checks the class-precedence
118
+ lists of each of the direct superclasses for
119
+ an occurrence of the new class - i.e. cycles!
120
+ This can only happen when a class is redefined
121
+ (a new class cannot have an unspecified
122
+ superclass).
123
+
124
+ This routine allocates the space for the list
125
+ ***************************************************************/
126
+ PACKED_CLASS_LINKS *ParseSuperclasses(
127
+ Environment *theEnv,
128
+ const char *readSource,
129
+ CLIPSLexeme *newClassName)
130
+ {
131
+ CLASS_LINK *clink = NULL,*cbot = NULL,*ctmp;
132
+ Defclass *sclass;
133
+ PACKED_CLASS_LINKS *plinks;
134
+
135
+ if (DefclassData(theEnv)->ObjectParseToken.tknType != LEFT_PARENTHESIS_TOKEN)
136
+ {
137
+ SyntaxErrorMessage(theEnv,"defclass inheritance");
138
+ return NULL;
139
+ }
140
+ GetToken(theEnv,readSource,&DefclassData(theEnv)->ObjectParseToken);
141
+ if ((DefclassData(theEnv)->ObjectParseToken.tknType != SYMBOL_TOKEN) ? true :
142
+ (DefclassData(theEnv)->ObjectParseToken.value != (void *) DefclassData(theEnv)->ISA_SYMBOL))
143
+ {
144
+ SyntaxErrorMessage(theEnv,"defclass inheritance");
145
+ return NULL;
146
+ }
147
+ SavePPBuffer(theEnv," ");
148
+ GetToken(theEnv,readSource,&DefclassData(theEnv)->ObjectParseToken);
149
+ while (DefclassData(theEnv)->ObjectParseToken.tknType != RIGHT_PARENTHESIS_TOKEN)
150
+ {
151
+ if (DefclassData(theEnv)->ObjectParseToken.tknType != SYMBOL_TOKEN)
152
+ {
153
+ SyntaxErrorMessage(theEnv,"defclass");
154
+ goto SuperclassParseError;
155
+ }
156
+ if (FindModuleSeparator(newClassName->contents))
157
+ {
158
+ IllegalModuleSpecifierMessage(theEnv);
159
+ goto SuperclassParseError;
160
+ }
161
+ if (DefclassData(theEnv)->ObjectParseToken.value == (void *) newClassName)
162
+ {
163
+ PrintErrorID(theEnv,"INHERPSR",1,false);
164
+ WriteString(theEnv,STDERR,"A class may not have itself as a superclass.\n");
165
+ goto SuperclassParseError;
166
+ }
167
+ for (ctmp = clink ; ctmp != NULL ; ctmp = ctmp->nxt)
168
+ {
169
+ if (DefclassData(theEnv)->ObjectParseToken.value == (void *) ctmp->cls->header.name)
170
+ {
171
+ PrintErrorID(theEnv,"INHERPSR",2,false);
172
+ WriteString(theEnv,STDERR,"A class may inherit from a superclass only once.\n");
173
+ goto SuperclassParseError;
174
+ }
175
+ }
176
+ sclass = LookupDefclassInScope(theEnv,DefclassData(theEnv)->ObjectParseToken.lexemeValue->contents);
177
+ if (sclass == NULL)
178
+ {
179
+ PrintErrorID(theEnv,"INHERPSR",3,false);
180
+ WriteString(theEnv,STDERR,"A class must be defined after all its superclasses.\n");
181
+ goto SuperclassParseError;
182
+ }
183
+ if ((sclass == DefclassData(theEnv)->PrimitiveClassMap[INSTANCE_NAME_TYPE]) ||
184
+ (sclass == DefclassData(theEnv)->PrimitiveClassMap[INSTANCE_ADDRESS_TYPE]) ||
185
+ (sclass == DefclassData(theEnv)->PrimitiveClassMap[INSTANCE_NAME_TYPE]->directSuperclasses.classArray[0]))
186
+ {
187
+ PrintErrorID(theEnv,"INHERPSR",6,false);
188
+ WriteString(theEnv,STDERR,"A user-defined class cannot be a subclass of '");
189
+ WriteString(theEnv,STDERR,DefclassName(sclass));
190
+ WriteString(theEnv,STDERR,"'.\n");
191
+ goto SuperclassParseError;
192
+ }
193
+ ctmp = get_struct(theEnv,classLink);
194
+ ctmp->cls = sclass;
195
+ if (clink == NULL)
196
+ clink = ctmp;
197
+ else
198
+ cbot->nxt = ctmp;
199
+ ctmp->nxt = NULL;
200
+ cbot = ctmp;
201
+
202
+ SavePPBuffer(theEnv," ");
203
+ GetToken(theEnv,readSource,&DefclassData(theEnv)->ObjectParseToken);
204
+ }
205
+ if (clink == NULL)
206
+ {
207
+ PrintErrorID(theEnv,"INHERPSR",4,false);
208
+ WriteString(theEnv,STDERR,"A class must have at least one superclass.\n");
209
+ return NULL;
210
+ }
211
+ PPBackup(theEnv);
212
+ PPBackup(theEnv);
213
+ SavePPBuffer(theEnv,")");
214
+ plinks = get_struct(theEnv,packedClassLinks);
215
+ PackClassLinks(theEnv,plinks,clink);
216
+ return(plinks);
217
+
218
+ SuperclassParseError:
219
+ DeleteClassLinks(theEnv,clink);
220
+ return NULL;
221
+ }
222
+
223
+ /***************************************************************************
224
+ NAME : FindPrecedenceList
225
+ DESCRIPTION : A complete class precedence list is obtained from the
226
+ list of direct superclasses as follows :
227
+
228
+ Each class and its direct superclasses are recursively
229
+ entered in order to a list called the partial order table.
230
+ A class is only entered once. The order reflects a pre-order
231
+ depth-first traversal of the classes, and this order will be
232
+ followed as closely as possible to preserve the "family"
233
+ heuristic when constructing the class precedence list.
234
+
235
+ Attached to each node is a count indicating the number of
236
+ classes which must precede this class and a list of classes
237
+ which must succeed this class (attached via the suc field and
238
+ linked via nxt fields). These predecessor counts
239
+ and successor lists indicate the partial orderings given
240
+ by the rules of multiple inheritance for the classes:
241
+ 1) a class must precede all its superclasses, and 2) a
242
+ class determines the precedence of its immediate superclasses.
243
+
244
+ For example, the following class definitions
245
+
246
+ (defclass A (is-a USER))
247
+ (defclass B (is-a USER))
248
+ (defclass C (is-a A B))
249
+
250
+ would give the following partial orders:
251
+
252
+ C < A by Rule 1
253
+ C < B by Rule 1
254
+ A < B by Rule 2
255
+ B < USER by Rule 1
256
+ A < USER by Rule 1
257
+ USER < OBJECT by Rule 1
258
+
259
+ In turn, these partial orders would be recorded in a
260
+ sequence table:
261
+
262
+ C A USER OBJECT B
263
+ Predecessor Count 0 1 2 1 2
264
+ Successor List A,B B,USER OBJECT <NIL> USER
265
+
266
+ To generate a precedence list for C, we pick the first
267
+ class with a predecessor count of 0, append it to the
268
+ precedence list, and decrement the counts of all its
269
+ successors. We continue scanning for a 0 from where
270
+ we left off. If we ever scan completely through the
271
+ table without finding a 0, then we know there is an
272
+ error.
273
+
274
+ Shown below is the table above after each class is
275
+ entered onto the precedence list:
276
+
277
+ Precedence list: C
278
+ A USER OBJECT B
279
+ Predecessor Count 0 2 1 1
280
+ Successor List B,USER OBJECT <NIL> USER
281
+
282
+ Precedence list: C A
283
+ USER OBJECT B
284
+ Predecessor Count 1 1 0
285
+ Successor List OBJECT <NIL> USER
286
+
287
+ Precedence list: C A B
288
+ USER OBJECT
289
+ Predecessor Count 0 1
290
+ Successor List OBJECT <NIL>
291
+
292
+ Precedence list: C A B USER
293
+ OBJECT
294
+ Predecessor Count 0
295
+ Successor List <NIL>
296
+
297
+ Precedence List: C A B USER OBJECT
298
+
299
+ And since the table is now empty we are done!
300
+ INPUTS : 1) The old class definition (NULL if it is new)
301
+ 2) The list of direct superclasses
302
+ RETURNS : The address of the precedence list if successful,
303
+ NULL otherwise
304
+ SIDE EFFECTS : Precedence list allocated
305
+ NOTES : WARNING!! - This routine assumes that there are no
306
+ cyclic dependencies in the given superclass list, i.e.
307
+ none of the superclasses inherit from the class for
308
+ which the precedence list is being defined. (This
309
+ is verified in ParseDefclasses() in CLASSCOM.C)
310
+
311
+ Every class-precedence list has the class itself on it
312
+ (implicitly) and a built-in system class on it explicitly
313
+ (except for the built-in classes).
314
+
315
+ The precedence determination algorithm is a variation on
316
+ the topological sorting algorithm given in The Art of
317
+ Computer Programming - Vol. I (Fundamental Algorithms) by
318
+ Donald Knuth.
319
+ ***************************************************************************/
320
+ PACKED_CLASS_LINKS *FindPrecedenceList(
321
+ Environment *theEnv,
322
+ Defclass *cls,
323
+ PACKED_CLASS_LINKS *supers)
324
+ {
325
+ PARTIAL_ORDER *po_table = NULL,*start,*pop,*poprv,*potmp;
326
+ SUCCESSOR *stmp;
327
+ CLASS_LINK *ptop,*pbot,*ptmp;
328
+ PACKED_CLASS_LINKS *plinks;
329
+ unsigned long i;
330
+
331
+ /* =====================================================================
332
+ Recursively add all superclasses in a pre-order depth-first traversal
333
+ to the partial order table. There should be only one node per class.
334
+ ===================================================================== */
335
+ po_table = InitializePartialOrderTable(theEnv,po_table,supers);
336
+
337
+ /* =============================================================
338
+ If the class already exists, record the rule 1 partial orders
339
+ with the new superclass lists. This is so that cyclic
340
+ dependencies can be detected.
341
+ ============================================================= */
342
+ if (cls != NULL)
343
+ {
344
+ pop = get_struct(theEnv,partialOrder);
345
+ pop->cls = cls;
346
+ pop->pre = 0;
347
+ pop->suc = NULL;
348
+ pop->nxt = po_table;
349
+ po_table = pop;
350
+ pop = po_table->nxt;
351
+ RecordPartialOrders(theEnv,po_table,cls,supers,0);
352
+ }
353
+ else
354
+ pop = po_table;
355
+
356
+ /* ==================================================================
357
+ Record the rule 1 and rule 2 partial orders given by the direct
358
+ superclass lists of the classes in the table. There is no need to
359
+ recurse since all possible classes have been entered already.
360
+
361
+ Be sure to skip the class itself if it was added to the front of
362
+ the table.
363
+ ================================================================== */
364
+ for ( ; pop != NULL ; pop = pop->nxt)
365
+ {
366
+ RecordPartialOrders(theEnv,po_table,pop->cls,&pop->cls->directSuperclasses,0);
367
+ for (i = 0 ; i < pop->cls->directSuperclasses.classCount ; i++)
368
+ RecordPartialOrders(theEnv,po_table,pop->cls->directSuperclasses.classArray[i],
369
+ &pop->cls->directSuperclasses,i+1);
370
+ }
371
+
372
+ /* =============================================================
373
+ Record the rule 2 partial orders given by the superclass list
374
+ ============================================================= */
375
+ for (i = 0 ; i < supers->classCount ; i++)
376
+ RecordPartialOrders(theEnv,po_table,supers->classArray[i],supers,i+1);
377
+
378
+ start = NULL;
379
+ poprv = NULL;
380
+ pop = po_table;
381
+ ptop = pbot = NULL;
382
+ while (pop != start)
383
+ {
384
+ /* ==============================================================
385
+ Allow wraparound - happens when the search for a 0 node begins
386
+ somewhere in the middle of the sequence table
387
+ ============================================================== */
388
+ if (pop == NULL)
389
+ {
390
+ poprv = NULL;
391
+ pop = po_table;
392
+ start = start->nxt;
393
+ }
394
+
395
+ /* =========================================================
396
+ Search for the first class with no remaining predecessors
397
+ ========================================================= */
398
+ if (pop->pre == 0)
399
+ {
400
+ /* =================================================
401
+ Decrement the predecessor count for all the
402
+ successors of this class and delete the list.
403
+
404
+ This is the variation on Knuth's algorithm which
405
+ allows us to preserve the "family" heuristic.
406
+ Since we will pick up scanning for 0's from
407
+ this point, we will be able to keep "family"
408
+ trees together, if possible. BuildPartialOrders()
409
+ entered the classes into the sequence table
410
+ in a pre-order depth traversal order.
411
+ ================================================= */
412
+ while (pop->suc != NULL)
413
+ {
414
+ stmp = pop->suc;
415
+ pop->suc = stmp->nxt;
416
+ stmp->po->pre--;
417
+ rtn_struct(theEnv,successor,stmp);
418
+ }
419
+
420
+ /* =============================================
421
+ Append the class to the precedence list and
422
+ remove its entry from the partial order table
423
+ ============================================= */
424
+ potmp = pop;
425
+ if (poprv == NULL)
426
+ po_table = pop->nxt;
427
+ else
428
+ poprv->nxt = pop->nxt;
429
+ pop = pop->nxt;
430
+ start = poprv;
431
+ ptmp = get_struct(theEnv,classLink);
432
+ ptmp->cls = potmp->cls;
433
+ ptmp->nxt = NULL;
434
+ rtn_struct(theEnv,partialOrder,potmp);
435
+ if (ptop == NULL)
436
+ ptop = ptmp;
437
+ else
438
+ pbot->nxt = ptmp;
439
+ pbot = ptmp;
440
+ }
441
+ else
442
+ {
443
+ poprv = pop;
444
+ pop = pop->nxt;
445
+ }
446
+ }
447
+
448
+ /* ======================================================================
449
+ If the table of partial orders is not empty and we were unable to find
450
+ a class with no predecessors, then there is no solution! Print out the
451
+ precedence loop in the partial orders. Delete the remaining partial
452
+ order table and the partial precedence list.
453
+ ====================================================================== */
454
+ if (po_table != NULL)
455
+ {
456
+ PrintErrorID(theEnv,"INHERPSR",5,false);
457
+ PrintClassLinks(theEnv,STDERR,"Partial precedence list formed:",ptop);
458
+ PrintPartialOrderLoop(theEnv,po_table);
459
+ while (po_table != NULL)
460
+ {
461
+ while (po_table->suc != NULL)
462
+ {
463
+ stmp = po_table->suc;
464
+ po_table->suc = stmp->nxt;
465
+ rtn_struct(theEnv,successor,stmp);
466
+ }
467
+ potmp = po_table;
468
+ po_table = po_table->nxt;
469
+ rtn_struct(theEnv,partialOrder,potmp);
470
+ }
471
+ DeleteClassLinks(theEnv,ptop);
472
+ return NULL;
473
+ }
474
+
475
+ /* =============================================================================
476
+ If the class already existed, be sure and remove it from its own precedence
477
+ list. Remember that we stuck it on the table artificially to catch cycles.
478
+ It was first in the table, and, since it started with a predecessor count
479
+ of zero (given that there were no loops), it is first in the precedence list.
480
+
481
+ We will leave the dummy node there so that functions which wish to iterate
482
+ over a class and its superclasses may easily do so.
483
+ ============================================================================= */
484
+ if (cls == NULL)
485
+ {
486
+ ptmp = get_struct(theEnv,classLink);
487
+ ptmp->nxt = ptop;
488
+ ptop = ptmp;
489
+ }
490
+
491
+ /* ============================================================
492
+ The class pointer will be filled in later by ParseDefclass()
493
+ ============================================================ */
494
+ ptop->cls = NULL;
495
+
496
+ plinks = get_struct(theEnv,packedClassLinks);
497
+ PackClassLinks(theEnv,plinks,ptop);
498
+ return(plinks);
499
+ }
500
+
501
+ /***************************************************
502
+ NAME : PackClassLinks
503
+ DESCRIPTION : Writes a list of class links into
504
+ a contiguous section of memory to
505
+ reduce overhead (the original list
506
+ is deleted)
507
+ INPUTS : 1) The packed list structure to use
508
+ 2) The top of the original list
509
+ RETURNS : Nothing useful
510
+ SIDE EFFECTS : Packed list allocated and old list
511
+ deleted
512
+ NOTES : None
513
+ ***************************************************/
514
+ void PackClassLinks(
515
+ Environment *theEnv,
516
+ PACKED_CLASS_LINKS *plinks,
517
+ CLASS_LINK *lptop)
518
+ {
519
+ unsigned count;
520
+ CLASS_LINK *lp;
521
+
522
+ for (count = 0 , lp = lptop ; lp != NULL ; lp = lp->nxt)
523
+ count++;
524
+ if (count > 0)
525
+ plinks->classArray = (Defclass **) gm2(theEnv,(sizeof(Defclass *) * count));
526
+ else
527
+ plinks->classArray = NULL;
528
+ for (count = 0 , lp = lptop ; lp != NULL ; lp = lp->nxt , count++)
529
+ plinks->classArray[count] = lp->cls;
530
+ DeleteClassLinks(theEnv,lptop);
531
+ plinks->classCount = count;
532
+ }
533
+
534
+ /* =========================================
535
+ *****************************************
536
+ INTERNALLY VISIBLE FUNCTIONS
537
+ =========================================
538
+ ***************************************** */
539
+
540
+ /**************************************************************************
541
+ NAME : InitializePartialOrderTable
542
+ DESCRIPTION : This function recursively enters the classes
543
+ that will be used in a precedence list
544
+ determination in depth-first pre-order traversal.
545
+ The predecessor counts and successor list are initialized.
546
+
547
+ INPUTS : 1) The partial order table
548
+ 2) A list of direct superclasses
549
+ 3) The class for which a precedence class is being
550
+ determined (NULL for new class)
551
+ 4) The class which superclass list is being processed
552
+ RETURNS : The top of partial order table
553
+ SIDE EFFECTS : The partial order table is initialized.
554
+ NOTES : None
555
+ **************************************************************************/
556
+ static PARTIAL_ORDER *InitializePartialOrderTable(
557
+ Environment *theEnv,
558
+ PARTIAL_ORDER *po_table,
559
+ PACKED_CLASS_LINKS *supers)
560
+ {
561
+ PARTIAL_ORDER *pop,*poprv;
562
+ unsigned long i;
563
+
564
+ for (i = 0 ; i < supers->classCount ; i++)
565
+ {
566
+ /* =================================================
567
+ Append this class at the end of the partial order
568
+ table only if it is not already present
569
+ ================================================= */
570
+ poprv = NULL;
571
+ for (pop = po_table ; pop != NULL ; pop = pop->nxt)
572
+ {
573
+ if (pop->cls == supers->classArray[i])
574
+ break;
575
+ poprv = pop;
576
+ }
577
+ if (pop == NULL)
578
+ {
579
+ pop = get_struct(theEnv,partialOrder);
580
+ pop->cls = supers->classArray[i];
581
+ pop->nxt = NULL;
582
+ pop->suc = NULL;
583
+ pop->pre = 0;
584
+ if (poprv == NULL)
585
+ po_table = pop;
586
+ else
587
+ poprv->nxt = pop;
588
+
589
+ /* =============================================================
590
+ Recursively append all its superclasses immediately after it.
591
+ This order will allow us to preserve the "family" heuristic
592
+ in the precedence list.
593
+ ============================================================= */
594
+ po_table = InitializePartialOrderTable(theEnv,po_table,
595
+ &supers->classArray[i]->directSuperclasses);
596
+ }
597
+ }
598
+ return(po_table);
599
+ }
600
+
601
+ /***********************************************************************************
602
+ NAME : RecordPartialOrders
603
+ DESCRIPTION : Given a predecessor class and a list of successor classes, this
604
+ function enters a number of partial orders into the table equaling
605
+ the number of successor classes.
606
+ INPUTS : 1) The partial order table
607
+ 2) The predecessor class
608
+ 3) An array of successor classes
609
+ 4) A starting index for the successor classes
610
+ RETURNS : The top of sequence table
611
+ SIDE EFFECTS : The sequence table is built, e.g.:
612
+
613
+ CLASS1 < CLASS2 , CLASS3
614
+
615
+ would be recorded as:
616
+
617
+ PO_TABLE -> NXT -> NXT -> NXT -> <NIL>
618
+ <CLASS1> <CLASS2> <CLASS3>
619
+ SUC SUC SUC
620
+ | | |
621
+ V V V
622
+ <CLASS2> <NIL> <NIL>
623
+ NXT
624
+ |
625
+ V
626
+ <CLASS3>
627
+ NXT
628
+ |
629
+ V
630
+ <NIL>
631
+
632
+ The predecessor counts would be 0, 1 and 1 for CLASS1, CLASS2
633
+ and CLASS3 respectively.
634
+ NOTES : None
635
+ ***********************************************************************************/
636
+ static void RecordPartialOrders(
637
+ Environment *theEnv,
638
+ PARTIAL_ORDER *po_table,
639
+ Defclass *cls,
640
+ PACKED_CLASS_LINKS *successors,
641
+ unsigned long starti)
642
+ {
643
+ PARTIAL_ORDER *clspo;
644
+ SUCCESSOR *stmp;
645
+
646
+ clspo = FindPartialOrder(po_table,cls);
647
+ while (starti < successors->classCount)
648
+ {
649
+ stmp = get_struct(theEnv,successor);
650
+ stmp->po = FindPartialOrder(po_table,successors->classArray[starti]);
651
+ stmp->nxt = clspo->suc;
652
+ clspo->suc = stmp;
653
+ stmp->po->pre++;
654
+ starti++;
655
+ }
656
+ }
657
+
658
+ /***************************************************
659
+ NAME : FindPartialOrder
660
+ DESCRIPTION : Finds a partial order node
661
+ INPUTS : 1) The partial order table
662
+ 2) The class to look up
663
+ RETURNS : The partial order node address
664
+ SIDE EFFECTS : None
665
+ NOTES : None
666
+ ***************************************************/
667
+ static PARTIAL_ORDER *FindPartialOrder(
668
+ PARTIAL_ORDER *po_table,
669
+ Defclass *cls)
670
+ {
671
+ while (po_table != NULL)
672
+ {
673
+ if (po_table->cls == cls)
674
+ break;
675
+ po_table = po_table->nxt;
676
+ }
677
+ return(po_table);
678
+ }
679
+
680
+ /**************************************************************************
681
+ NAME : PrintPartialOrderLoop
682
+ DESCRIPTION : This routine prints a conflicting loop (there may be more
683
+ than one) in the given sequence table of partial orders.
684
+
685
+ The algorithm works as follows:
686
+
687
+ Given the following class definitions,
688
+
689
+ (defclass A (is-a USER))
690
+ (defclass B (is-a USER))
691
+ (defclass C (is-a A B))
692
+ (defclass D (is-a B A))
693
+ (defclass E (is-a C D))
694
+
695
+ the partial order table will look as follows after as many
696
+ classes as possible have been entered onto the precedence
697
+ list:
698
+
699
+ A USER OBJECT B
700
+ Predecessor Count 1 2 1 1
701
+ Successor List B,USER OBJECT <NIL> A,USER
702
+
703
+ Construct a new table where each class is linked to one
704
+ of its predecessors. For the example above one would be:
705
+
706
+ Class: A USER OBJECT B
707
+ Predecessor: B A USER A
708
+
709
+ This table is actually implemnted using the original
710
+ partial order table (see the code below for specifics).
711
+ Now using this table, start with the first node, and visit
712
+ successive nodes by following the predecessor links. Mark
713
+ each node as "visited". When a previously visited node is
714
+ encountered, the loop has been found.
715
+
716
+ In the case above, we start with A, goto B and then goto A
717
+ again which we have already seen. So starting from where
718
+ we found the loop (A) we follow the links again, printing
719
+ the nodes as we go, until we're back where we started:
720
+ A B A. Notice that this loop reflects the Rule 2 conflicts
721
+ between Class C and Class D in Class E's precedence list.
722
+
723
+ INPUTS : The remaining partial order table of conflicting partial
724
+ orders
725
+ RETURNS : Nothing useful
726
+ SIDE EFFECTS : The predecessor counts and successor lists are modified to
727
+ implement the loop detection.
728
+ NOTES : This algorithm is adopted from one given in Donald
729
+ Knuth's The Art of Computer Programming - Vol. I
730
+ (Fundamental Algorithms).
731
+ **************************************************************************/
732
+ static void PrintPartialOrderLoop(
733
+ Environment *theEnv,
734
+ PARTIAL_ORDER *po_table)
735
+ {
736
+ PARTIAL_ORDER *pop1,*pop2;
737
+ SUCCESSOR *prc,*stmp;
738
+
739
+ /* ====================================================
740
+ Set the predecessor count of every node to 0 so that
741
+ this field can be used as a marker
742
+ ==================================================== */
743
+ for (pop1 = po_table ; pop1 != NULL ; pop1 = pop1->nxt)
744
+ pop1->pre = 0;
745
+
746
+ /* =======================================================
747
+ Mark each node in the partial order table with one of
748
+ its predecessors. If the class has already been marked
749
+ (predecessor count > 0), don't bother. This is
750
+ accomplished by adding a node to the front of its
751
+ successors' successor lists.
752
+
753
+ When the process is finished, all nodes will have one
754
+ predecessor chained to them by their 'suc' field.
755
+ (If any nodes had had no predecessors, they would not
756
+ still be in the table.)
757
+ ======================================================= */
758
+ for (pop1 = po_table ; pop1 != NULL ; pop1 = pop1->nxt)
759
+ {
760
+ if (pop1->pre == 0)
761
+ {
762
+ prc = pop1->suc;
763
+ pop1->suc = NULL;
764
+ }
765
+ else
766
+ {
767
+ prc = pop1->suc->nxt;
768
+ pop1->suc->nxt = NULL;
769
+ }
770
+ while (prc != NULL)
771
+ {
772
+ pop2 = FindPartialOrder(po_table,prc->po->cls);
773
+ if (pop2->pre == 0)
774
+ {
775
+ stmp = get_struct(theEnv,successor);
776
+ stmp->po = pop1;
777
+ stmp->nxt = pop2->suc;
778
+ pop2->suc = stmp;
779
+ pop2->pre = 1;
780
+ }
781
+ stmp = prc;
782
+ prc = prc->nxt;
783
+ rtn_struct(theEnv,successor,stmp);
784
+ }
785
+ }
786
+
787
+ /* =================================================
788
+ Set the predecessor count of every node back to 0
789
+ so that this field can be used as a marker again
790
+ ================================================= */
791
+ for (pop1 = po_table ; pop1 != NULL ; pop1 = pop1->nxt)
792
+ pop1->pre = 0;
793
+
794
+ /* =========================================================
795
+ Now start with the first node in the partial order table,
796
+ and follow the predecessor links, marking the
797
+ nodes as they are visited. When we reach a node
798
+ we have been before, we have found a loop!
799
+ Follow all the marked nodes again starting from the
800
+ CURRENT position to print the loop.
801
+ ========================================================= */
802
+ pop1 = po_table;
803
+ while (pop1->pre == 0)
804
+ {
805
+ pop1->pre = 1;
806
+ pop1 = pop1->suc->po;
807
+ }
808
+
809
+ WriteString(theEnv,STDERR,"Precedence loop in superclasses:");
810
+ while (pop1->pre == 1)
811
+ {
812
+ WriteString(theEnv,STDERR," ");
813
+ PrintClassName(theEnv,STDERR,pop1->cls,false,false);
814
+ pop1->pre = 0;
815
+ pop1 = pop1->suc->po;
816
+ }
817
+ WriteString(theEnv,STDERR," ");
818
+ PrintClassName(theEnv,STDERR,pop1->cls,false,true);
819
+ }
820
+
821
+ /***************************************************
822
+ NAME : PrintClassLinks
823
+ DESCRIPTION : Displays the names of classes in
824
+ a list with a title
825
+ INPUTS : 1) The logical name of the output
826
+ 2) Title string
827
+ 3) List of class links
828
+ RETURNS : Nothing useful
829
+ SIDE EFFECTS : None
830
+ NOTES : None
831
+ ***************************************************/
832
+ static void PrintClassLinks(
833
+ Environment *theEnv,
834
+ const char *logicalName,
835
+ const char *title,
836
+ CLASS_LINK *clink)
837
+ {
838
+ if (title != NULL)
839
+ WriteString(theEnv,logicalName,title);
840
+ while (clink != NULL)
841
+ {
842
+ WriteString(theEnv,logicalName," ");
843
+ PrintClassName(theEnv,logicalName,clink->cls,false,false);
844
+ clink = clink->nxt;
845
+ }
846
+ WriteString(theEnv,logicalName,"\n");
847
+ }
848
+
849
+ #endif
850
+