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,1594 @@
1
+ /*******************************************************/
2
+ /* "C" Language Integrated Production System */
3
+ /* */
4
+ /* CLIPS Version 6.40 02/03/21 */
5
+ /* */
6
+ /* UTILITY MODULE */
7
+ /*******************************************************/
8
+
9
+ /*************************************************************/
10
+ /* Purpose: Provides a set of utility functions useful to */
11
+ /* other modules. Primarily these are the functions for */
12
+ /* handling periodic garbage collection and appending */
13
+ /* string data. */
14
+ /* */
15
+ /* Principal Programmer(s): */
16
+ /* Gary D. Riley */
17
+ /* */
18
+ /* Contributing Programmer(s): */
19
+ /* Brian Dantes */
20
+ /* Jeff Bezanson */
21
+ /* www.cprogramming.com/tutorial/unicode.html */
22
+ /* */
23
+ /* Revision History: */
24
+ /* */
25
+ /* 6.24: Renamed BOOLEAN macro type to intBool. */
26
+ /* */
27
+ /* 6.30: Changed integer type/precision. */
28
+ /* */
29
+ /* Changed garbage collection algorithm. */
30
+ /* */
31
+ /* Added CopyString, DeleteString, */
32
+ /* InsertInString,and EnlargeString functions. */
33
+ /* */
34
+ /* Used genstrncpy function instead of strncpy */
35
+ /* function. */
36
+ /* */
37
+ /* Support for typed EXTERNAL_ADDRESS. */
38
+ /* */
39
+ /* Support for tracked memory (allows memory to */
40
+ /* be freed if CLIPS is exited while executing). */
41
+ /* */
42
+ /* Added UTF-8 routines. */
43
+ /* */
44
+ /* Added const qualifiers to remove C++ */
45
+ /* deprecation warnings. */
46
+ /* */
47
+ /* Converted API macros to function calls. */
48
+ /* */
49
+ /* 6.31: Added debugging code for checking the garbage */
50
+ /* frame. */
51
+ /* */
52
+ /* 6.40: Fix for memory used discrepancy. */
53
+ /* */
54
+ /* Pragma once and other inclusion changes. */
55
+ /* */
56
+ /* Added support for booleans with <stdbool.h>. */
57
+ /* */
58
+ /* Removed use of void pointers for specific */
59
+ /* data structures. */
60
+ /* */
61
+ /* ALLOW_ENVIRONMENT_GLOBALS no longer supported. */
62
+ /* */
63
+ /* Callbacks must be environment aware. */
64
+ /* */
65
+ /* UDF redesign. */
66
+ /* */
67
+ /* Added GCBlockStart and GCBlockEnd functions */
68
+ /* for garbage collection blocks. */
69
+ /* */
70
+ /* Added StringBuilder functions. */
71
+ /* */
72
+ /* Moved BufferedRead and FreeReadBuffer from */
73
+ /* insfile.c to utility.c */
74
+ /* */
75
+ /*************************************************************/
76
+
77
+ #include "setup.h"
78
+
79
+ #include <ctype.h>
80
+ #include <stdlib.h>
81
+ #include <stdio.h>
82
+ #include <string.h>
83
+
84
+ #include "commline.h"
85
+ #include "envrnmnt.h"
86
+ #include "evaluatn.h"
87
+ #include "factmngr.h"
88
+ #include "facthsh.h"
89
+ #include "memalloc.h"
90
+ #include "multifld.h"
91
+ #include "prntutil.h"
92
+ #include "router.h"
93
+ #include "symbol.h"
94
+ #include "sysdep.h"
95
+
96
+ #include "utility.h"
97
+
98
+ #define MAX_EPHEMERAL_COUNT 1000L
99
+ #define MAX_EPHEMERAL_SIZE 10240L
100
+ #define COUNT_INCREMENT 1000L
101
+ #define SIZE_INCREMENT 10240L
102
+
103
+ #define MAX_BLOCK_SIZE 10240
104
+
105
+ /***************************************/
106
+ /* LOCAL INTERNAL FUNCTION DEFINITIONS */
107
+ /***************************************/
108
+
109
+ static void DeallocateUtilityData(Environment *);
110
+
111
+ /************************************************/
112
+ /* InitializeUtilityData: Allocates environment */
113
+ /* data for utility routines. */
114
+ /************************************************/
115
+ void InitializeUtilityData(
116
+ Environment *theEnv)
117
+ {
118
+ AllocateEnvironmentData(theEnv,UTILITY_DATA,sizeof(struct utilityData),DeallocateUtilityData);
119
+
120
+ UtilityData(theEnv)->CurrentGarbageFrame = &UtilityData(theEnv)->MasterGarbageFrame;
121
+
122
+ UtilityData(theEnv)->PeriodicFunctionsEnabled = true;
123
+ UtilityData(theEnv)->YieldFunctionEnabled = true;
124
+ }
125
+
126
+ /**************************************************/
127
+ /* DeallocateUtilityData: Deallocates environment */
128
+ /* data for utility routines. */
129
+ /**************************************************/
130
+ static void DeallocateUtilityData(
131
+ Environment *theEnv)
132
+ {
133
+ struct trackedMemory *tmpTM, *nextTM;
134
+ struct garbageFrame *theGarbageFrame;
135
+ struct ephemeron *edPtr, *nextEDPtr;
136
+ Multifield *tmpMFPtr, *nextMFPtr;
137
+
138
+ /*======================*/
139
+ /* Free tracked memory. */
140
+ /*======================*/
141
+
142
+ tmpTM = UtilityData(theEnv)->trackList;
143
+ while (tmpTM != NULL)
144
+ {
145
+ nextTM = tmpTM->next;
146
+ genfree(theEnv,tmpTM->theMemory,tmpTM->memSize);
147
+ rtn_struct(theEnv,trackedMemory,tmpTM);
148
+ tmpTM = nextTM;
149
+ }
150
+
151
+ /*==========================*/
152
+ /* Free callback functions. */
153
+ /*==========================*/
154
+
155
+ DeallocateVoidCallList(theEnv,UtilityData(theEnv)->ListOfPeriodicFunctions);
156
+ DeallocateVoidCallList(theEnv,UtilityData(theEnv)->ListOfCleanupFunctions);
157
+
158
+ /*=========================================*/
159
+ /* Free the ephemerons tracking data which */
160
+ /* needs to be garbage collected. */
161
+ /*=========================================*/
162
+
163
+ while (UtilityData(theEnv)->CurrentGarbageFrame != NULL)
164
+ {
165
+ theGarbageFrame = UtilityData(theEnv)->CurrentGarbageFrame;
166
+
167
+ edPtr = theGarbageFrame->ephemeralSymbolList;
168
+
169
+ while (edPtr != NULL)
170
+ {
171
+ nextEDPtr = edPtr->next;
172
+ rtn_struct(theEnv,ephemeron,edPtr);
173
+ edPtr = nextEDPtr;
174
+ }
175
+
176
+ edPtr = theGarbageFrame->ephemeralFloatList;
177
+
178
+ while (edPtr != NULL)
179
+ {
180
+ nextEDPtr = edPtr->next;
181
+ rtn_struct(theEnv,ephemeron,edPtr);
182
+ edPtr = nextEDPtr;
183
+ }
184
+
185
+ edPtr = theGarbageFrame->ephemeralIntegerList;
186
+
187
+ while (edPtr != NULL)
188
+ {
189
+ nextEDPtr = edPtr->next;
190
+ rtn_struct(theEnv,ephemeron,edPtr);
191
+ edPtr = nextEDPtr;
192
+ }
193
+
194
+ edPtr = theGarbageFrame->ephemeralBitMapList;
195
+
196
+ while (edPtr != NULL)
197
+ {
198
+ nextEDPtr = edPtr->next;
199
+ rtn_struct(theEnv,ephemeron,edPtr);
200
+ edPtr = nextEDPtr;
201
+ }
202
+
203
+ edPtr = theGarbageFrame->ephemeralExternalAddressList;
204
+
205
+ while (edPtr != NULL)
206
+ {
207
+ nextEDPtr = edPtr->next;
208
+ rtn_struct(theEnv,ephemeron,edPtr);
209
+ edPtr = nextEDPtr;
210
+ }
211
+
212
+ /*==========================*/
213
+ /* Free up multifield data. */
214
+ /*==========================*/
215
+
216
+ tmpMFPtr = theGarbageFrame->ListOfMultifields;
217
+ while (tmpMFPtr != NULL)
218
+ {
219
+ nextMFPtr = tmpMFPtr->next;
220
+ ReturnMultifield(theEnv,tmpMFPtr);
221
+ tmpMFPtr = nextMFPtr;
222
+ }
223
+
224
+ UtilityData(theEnv)->CurrentGarbageFrame = UtilityData(theEnv)->CurrentGarbageFrame->priorFrame;
225
+ }
226
+ }
227
+
228
+ /*****************************/
229
+ /* CleanCurrentGarbageFrame: */
230
+ /*****************************/
231
+ void CleanCurrentGarbageFrame(
232
+ Environment *theEnv,
233
+ UDFValue *returnValue)
234
+ {
235
+ struct garbageFrame *currentGarbageFrame;
236
+
237
+ currentGarbageFrame = UtilityData(theEnv)->CurrentGarbageFrame;
238
+
239
+ if (! currentGarbageFrame->dirty) return;
240
+
241
+ if (returnValue != NULL)
242
+ { RetainUDFV(theEnv,returnValue); }
243
+
244
+ CallCleanupFunctions(theEnv);
245
+ RemoveEphemeralAtoms(theEnv);
246
+ FlushMultifields(theEnv);
247
+
248
+ if (returnValue != NULL)
249
+ { ReleaseUDFV(theEnv,returnValue); }
250
+
251
+ if ((currentGarbageFrame->ephemeralFloatList == NULL) &&
252
+ (currentGarbageFrame->ephemeralIntegerList == NULL) &&
253
+ (currentGarbageFrame->ephemeralSymbolList == NULL) &&
254
+ (currentGarbageFrame->ephemeralBitMapList == NULL) &&
255
+ (currentGarbageFrame->ephemeralExternalAddressList == NULL) &&
256
+ (currentGarbageFrame->LastMultifield == NULL))
257
+ { currentGarbageFrame->dirty = false; }
258
+ }
259
+
260
+ /*****************************/
261
+ /* RestorePriorGarbageFrame: */
262
+ /*****************************/
263
+ void RestorePriorGarbageFrame(
264
+ Environment *theEnv,
265
+ struct garbageFrame *newGarbageFrame,
266
+ struct garbageFrame *oldGarbageFrame,
267
+ UDFValue *returnValue)
268
+ {
269
+ if (newGarbageFrame->dirty)
270
+ {
271
+ if (returnValue != NULL) RetainUDFV(theEnv,returnValue);
272
+ CallCleanupFunctions(theEnv);
273
+ RemoveEphemeralAtoms(theEnv);
274
+ FlushMultifields(theEnv);
275
+ }
276
+
277
+ UtilityData(theEnv)->CurrentGarbageFrame = oldGarbageFrame;
278
+
279
+ if (newGarbageFrame->dirty)
280
+ {
281
+ if (newGarbageFrame->ListOfMultifields != NULL)
282
+ {
283
+ if (oldGarbageFrame->ListOfMultifields == NULL)
284
+ { oldGarbageFrame->ListOfMultifields = newGarbageFrame->ListOfMultifields; }
285
+ else
286
+ { oldGarbageFrame->LastMultifield->next = newGarbageFrame->ListOfMultifields; }
287
+
288
+ oldGarbageFrame->LastMultifield = newGarbageFrame->LastMultifield;
289
+ oldGarbageFrame->dirty = true;
290
+ }
291
+
292
+ if (returnValue != NULL) ReleaseUDFV(theEnv,returnValue);
293
+ }
294
+
295
+ if (returnValue != NULL)
296
+ { EphemerateValue(theEnv,returnValue->value); }
297
+ }
298
+
299
+ /*****************/
300
+ /* GCBlockStart: */
301
+ /*****************/
302
+ void GCBlockStart(
303
+ Environment *theEnv,
304
+ GCBlock *theBlock)
305
+ {
306
+ theBlock->oldGarbageFrame = UtilityData(theEnv)->CurrentGarbageFrame;
307
+ memset(&theBlock->newGarbageFrame,0,sizeof(struct garbageFrame));
308
+ theBlock->newGarbageFrame.priorFrame = theBlock->oldGarbageFrame;
309
+ UtilityData(theEnv)->CurrentGarbageFrame = &theBlock->newGarbageFrame;
310
+ }
311
+
312
+ /***************/
313
+ /* GCBlockEnd: */
314
+ /***************/
315
+ void GCBlockEnd(
316
+ Environment *theEnv,
317
+ GCBlock *theBlock)
318
+ {
319
+ RestorePriorGarbageFrame(theEnv,&theBlock->newGarbageFrame,theBlock->oldGarbageFrame,NULL);
320
+ }
321
+
322
+ /******************/
323
+ /* GCBlockEndUDF: */
324
+ /******************/
325
+ void GCBlockEndUDF(
326
+ Environment *theEnv,
327
+ GCBlock *theBlock,
328
+ UDFValue *rv)
329
+ {
330
+ RestorePriorGarbageFrame(theEnv,&theBlock->newGarbageFrame,theBlock->oldGarbageFrame,rv);
331
+ }
332
+
333
+ /*******************************/
334
+ /* CurrentGarbageFrameIsDirty: */
335
+ /*******************************/
336
+ bool CurrentGarbageFrameIsDirty(
337
+ Environment *theEnv)
338
+ {
339
+ struct garbageFrame *cgf;
340
+
341
+ cgf = UtilityData(theEnv)->CurrentGarbageFrame;
342
+
343
+ if (cgf->dirty)
344
+ { return true; }
345
+ else
346
+ { return false; }
347
+ }
348
+
349
+ /*************************/
350
+ /* CallCleanupFunctions: */
351
+ /*************************/
352
+ void CallCleanupFunctions(
353
+ Environment *theEnv)
354
+ {
355
+ struct voidCallFunctionItem *cleanupPtr;
356
+
357
+ for (cleanupPtr = UtilityData(theEnv)->ListOfCleanupFunctions;
358
+ cleanupPtr != NULL;
359
+ cleanupPtr = cleanupPtr->next)
360
+ { (*cleanupPtr->func)(theEnv,cleanupPtr->context); }
361
+ }
362
+
363
+ /**************************************************/
364
+ /* CallPeriodicTasks: Calls the list of functions */
365
+ /* for handling periodic tasks. */
366
+ /**************************************************/
367
+ void CallPeriodicTasks(
368
+ Environment *theEnv)
369
+ {
370
+ struct voidCallFunctionItem *periodPtr;
371
+
372
+ if (UtilityData(theEnv)->PeriodicFunctionsEnabled)
373
+ {
374
+ for (periodPtr = UtilityData(theEnv)->ListOfPeriodicFunctions;
375
+ periodPtr != NULL;
376
+ periodPtr = periodPtr->next)
377
+ { (*periodPtr->func)(theEnv,periodPtr->context); }
378
+ }
379
+ }
380
+
381
+ /***************************************************/
382
+ /* AddCleanupFunction: Adds a function to the list */
383
+ /* of functions called to perform cleanup such */
384
+ /* as returning free memory to the memory pool. */
385
+ /***************************************************/
386
+ bool AddCleanupFunction(
387
+ Environment *theEnv,
388
+ const char *name,
389
+ VoidCallFunction *theFunction,
390
+ int priority,
391
+ void *context)
392
+ {
393
+ UtilityData(theEnv)->ListOfCleanupFunctions =
394
+ AddVoidFunctionToCallList(theEnv,name,priority,theFunction,
395
+ UtilityData(theEnv)->ListOfCleanupFunctions,context);
396
+ return true;
397
+ }
398
+
399
+ /****************************************************/
400
+ /* AddPeriodicFunction: Adds a function to the list */
401
+ /* of functions called to handle periodic tasks. */
402
+ /****************************************************/
403
+ bool AddPeriodicFunction(
404
+ Environment *theEnv,
405
+ const char *name,
406
+ VoidCallFunction *theFunction,
407
+ int priority,
408
+ void *context)
409
+ {
410
+ UtilityData(theEnv)->ListOfPeriodicFunctions =
411
+ AddVoidFunctionToCallList(theEnv,name,priority,theFunction,
412
+ UtilityData(theEnv)->ListOfPeriodicFunctions,context);
413
+ return true;
414
+ }
415
+
416
+ /***************************************************/
417
+ /* GetPeriodicFunctionContext: Returns the context */
418
+ /* associated with a periodic function. */
419
+ /***************************************************/
420
+ void *GetPeriodicFunctionContext(
421
+ Environment *theEnv,
422
+ const char *name)
423
+ {
424
+ struct voidCallFunctionItem *theItem;
425
+
426
+ theItem = GetVoidFunctionFromCallList(theEnv,name,
427
+ UtilityData(theEnv)->ListOfPeriodicFunctions);
428
+
429
+ if (theItem == NULL) return NULL;
430
+
431
+ return theItem->context;
432
+ }
433
+
434
+ /*******************************************************/
435
+ /* RemoveCleanupFunction: Removes a function from the */
436
+ /* list of functions called to perform cleanup such */
437
+ /* as returning free memory to the memory pool. */
438
+ /*******************************************************/
439
+ bool RemoveCleanupFunction(
440
+ Environment *theEnv,
441
+ const char *name)
442
+ {
443
+ bool found;
444
+
445
+ UtilityData(theEnv)->ListOfCleanupFunctions =
446
+ RemoveVoidFunctionFromCallList(theEnv,name,UtilityData(theEnv)->ListOfCleanupFunctions,&found);
447
+
448
+ return found;
449
+ }
450
+
451
+ /********************************************************/
452
+ /* RemovePeriodicFunction: Removes a function from the */
453
+ /* list of functions called to handle periodic tasks. */
454
+ /********************************************************/
455
+ bool RemovePeriodicFunction(
456
+ Environment *theEnv,
457
+ const char *name)
458
+ {
459
+ bool found;
460
+
461
+ UtilityData(theEnv)->ListOfPeriodicFunctions =
462
+ RemoveVoidFunctionFromCallList(theEnv,name,UtilityData(theEnv)->ListOfPeriodicFunctions,&found);
463
+
464
+ return found;
465
+ }
466
+
467
+ /*****************************************************/
468
+ /* StringPrintForm: Generates printed representation */
469
+ /* of a string. Replaces / with // and " with /". */
470
+ /*****************************************************/
471
+ const char *StringPrintForm(
472
+ Environment *theEnv,
473
+ const char *str)
474
+ {
475
+ int i = 0;
476
+ size_t pos = 0;
477
+ size_t max = 0;
478
+ char *theString = NULL;
479
+ CLIPSLexeme *thePtr;
480
+
481
+ theString = ExpandStringWithChar(theEnv,'"',theString,&pos,&max,max+80);
482
+ while (str[i] != EOS)
483
+ {
484
+ if ((str[i] == '"') || (str[i] == '\\'))
485
+ {
486
+ theString = ExpandStringWithChar(theEnv,'\\',theString,&pos,&max,max+80);
487
+ theString = ExpandStringWithChar(theEnv,str[i],theString,&pos,&max,max+80);
488
+ }
489
+ else
490
+ { theString = ExpandStringWithChar(theEnv,str[i],theString,&pos,&max,max+80); }
491
+ i++;
492
+ }
493
+
494
+ theString = ExpandStringWithChar(theEnv,'"',theString,&pos,&max,max+80);
495
+
496
+ thePtr = CreateString(theEnv,theString);
497
+ rm(theEnv,theString,max);
498
+
499
+ return thePtr->contents;
500
+ }
501
+
502
+ /**************************************************************/
503
+ /* CopyString: Copies a string using CLIPS memory management. */
504
+ /**************************************************************/
505
+ char *CopyString(
506
+ Environment *theEnv,
507
+ const char *theString)
508
+ {
509
+ char *stringCopy = NULL;
510
+
511
+ if (theString != NULL)
512
+ {
513
+ stringCopy = (char *) genalloc(theEnv,strlen(theString) + 1);
514
+ genstrcpy(stringCopy,theString);
515
+ }
516
+
517
+ return stringCopy;
518
+ }
519
+
520
+ /*****************************************************************/
521
+ /* DeleteString: Deletes a string using CLIPS memory management. */
522
+ /*****************************************************************/
523
+ void DeleteString(
524
+ Environment *theEnv,
525
+ const char *theString)
526
+ {
527
+ if (theString != NULL)
528
+ { genfree(theEnv,(void *) theString,strlen(theString) + 1); }
529
+ }
530
+
531
+ /***********************************************************/
532
+ /* AppendStrings: Appends two strings together. The string */
533
+ /* created is added to the SymbolTable, so it is not */
534
+ /* necessary to deallocate the string returned. */
535
+ /***********************************************************/
536
+ const char *AppendStrings(
537
+ Environment *theEnv,
538
+ const char *str1,
539
+ const char *str2)
540
+ {
541
+ size_t pos = 0;
542
+ size_t max = 0;
543
+ char *theString = NULL;
544
+ CLIPSLexeme *thePtr;
545
+
546
+ theString = AppendToString(theEnv,str1,theString,&pos,&max);
547
+ theString = AppendToString(theEnv,str2,theString,&pos,&max);
548
+
549
+ thePtr = CreateString(theEnv,theString);
550
+ rm(theEnv,theString,max);
551
+ return thePtr->contents;
552
+ }
553
+
554
+ /******************************************************/
555
+ /* AppendToString: Appends a string to another string */
556
+ /* (expanding the other string if necessary). */
557
+ /******************************************************/
558
+ char *AppendToString(
559
+ Environment *theEnv,
560
+ const char *appendStr,
561
+ char *oldStr,
562
+ size_t *oldPos,
563
+ size_t *oldMax)
564
+ {
565
+ size_t length;
566
+
567
+ /*=========================================*/
568
+ /* Expand the old string so it can contain */
569
+ /* the new string (if necessary). */
570
+ /*=========================================*/
571
+
572
+ length = strlen(appendStr);
573
+
574
+ /*==============================================================*/
575
+ /* Return NULL if the old string was not successfully expanded. */
576
+ /*==============================================================*/
577
+
578
+ if ((oldStr = EnlargeString(theEnv,length,oldStr,oldPos,oldMax)) == NULL) { return NULL; }
579
+
580
+ /*===============================================*/
581
+ /* Append the new string to the expanded string. */
582
+ /*===============================================*/
583
+
584
+ genstrcpy(&oldStr[*oldPos],appendStr);
585
+ *oldPos += length;
586
+
587
+ /*============================================================*/
588
+ /* Return the expanded string containing the appended string. */
589
+ /*============================================================*/
590
+
591
+ return oldStr;
592
+ }
593
+
594
+ /**********************************************************/
595
+ /* InsertInString: Inserts a string within another string */
596
+ /* (expanding the other string if necessary). */
597
+ /**********************************************************/
598
+ char *InsertInString(
599
+ Environment *theEnv,
600
+ const char *insertStr,
601
+ size_t position,
602
+ char *oldStr,
603
+ size_t *oldPos,
604
+ size_t *oldMax)
605
+ {
606
+ size_t length;
607
+
608
+ /*=========================================*/
609
+ /* Expand the old string so it can contain */
610
+ /* the new string (if necessary). */
611
+ /*=========================================*/
612
+
613
+ length = strlen(insertStr);
614
+
615
+ /*==============================================================*/
616
+ /* Return NULL if the old string was not successfully expanded. */
617
+ /*==============================================================*/
618
+
619
+ if ((oldStr = EnlargeString(theEnv,length,oldStr,oldPos,oldMax)) == NULL) { return NULL; }
620
+
621
+ /*================================================================*/
622
+ /* Shift the contents to the right of insertion point so that the */
623
+ /* new text does not overwrite what is currently in the string. */
624
+ /*================================================================*/
625
+
626
+ memmove(&oldStr[position],&oldStr[position+length],*oldPos - position);
627
+
628
+ /*===============================================*/
629
+ /* Insert the new string in the expanded string. */
630
+ /*===============================================*/
631
+
632
+ genstrncpy(&oldStr[*oldPos],insertStr,length);
633
+ *oldPos += length;
634
+
635
+ /*============================================================*/
636
+ /* Return the expanded string containing the appended string. */
637
+ /*============================================================*/
638
+
639
+ return(oldStr);
640
+ }
641
+
642
+ /*******************************************************************/
643
+ /* EnlargeString: Enlarges a string by the specified amount. */
644
+ /*******************************************************************/
645
+ char *EnlargeString(
646
+ Environment *theEnv,
647
+ size_t length,
648
+ char *oldStr,
649
+ size_t *oldPos,
650
+ size_t *oldMax)
651
+ {
652
+ size_t newMax;
653
+
654
+ /*=========================================*/
655
+ /* Expand the old string so it can contain */
656
+ /* the new string (if necessary). */
657
+ /*=========================================*/
658
+
659
+ if (length + *oldPos + 1 > *oldMax)
660
+ {
661
+ newMax = length + *oldPos + 1;
662
+ if (newMax < sizeof(char *))
663
+ { newMax = sizeof(char *); }
664
+
665
+ oldStr = (char *) genrealloc(theEnv,oldStr,*oldMax,newMax);
666
+
667
+ *oldMax = newMax;
668
+ }
669
+
670
+ /*==============================================================*/
671
+ /* Return NULL if the old string was not successfully expanded. */
672
+ /*==============================================================*/
673
+
674
+ if (oldStr == NULL) { return NULL; }
675
+
676
+ return(oldStr);
677
+ }
678
+
679
+ /*******************************************************/
680
+ /* AppendNToString: Appends a string to another string */
681
+ /* (expanding the other string if necessary). Only a */
682
+ /* specified number of characters are appended from */
683
+ /* the string. */
684
+ /*******************************************************/
685
+ char *AppendNToString(
686
+ Environment *theEnv,
687
+ const char *appendStr,
688
+ char *oldStr,
689
+ size_t length,
690
+ size_t *oldPos,
691
+ size_t *oldMax)
692
+ {
693
+ size_t lengthWithEOS;
694
+ size_t newSize;
695
+
696
+ /*====================================*/
697
+ /* Determine the number of characters */
698
+ /* to be appended from the string. */
699
+ /*====================================*/
700
+
701
+ if (appendStr[length-1] != '\0') lengthWithEOS = length + 1;
702
+ else lengthWithEOS = length;
703
+
704
+ /*=========================================*/
705
+ /* Expand the old string so it can contain */
706
+ /* the new string (if necessary). */
707
+ /*=========================================*/
708
+
709
+ if (lengthWithEOS + *oldPos > *oldMax)
710
+ {
711
+ newSize = *oldPos + lengthWithEOS;
712
+ if (newSize < sizeof(char *))
713
+ { newSize = sizeof(char *); }
714
+
715
+ oldStr = (char *) genrealloc(theEnv,oldStr,*oldMax,newSize);
716
+ *oldMax = newSize;
717
+ }
718
+
719
+ /*==============================================================*/
720
+ /* Return NULL if the old string was not successfully expanded. */
721
+ /*==============================================================*/
722
+
723
+ if (oldStr == NULL) { return NULL; }
724
+
725
+ /*==================================*/
726
+ /* Append N characters from the new */
727
+ /* string to the expanded string. */
728
+ /*==================================*/
729
+
730
+ genstrncpy(&oldStr[*oldPos],appendStr,length);
731
+ *oldPos += (lengthWithEOS - 1);
732
+ oldStr[*oldPos] = '\0';
733
+
734
+ /*============================================================*/
735
+ /* Return the expanded string containing the appended string. */
736
+ /*============================================================*/
737
+
738
+ return(oldStr);
739
+ }
740
+
741
+ /*******************************************************/
742
+ /* ExpandStringWithChar: Adds a character to a string, */
743
+ /* reallocating space for the string if it needs to */
744
+ /* be enlarged. The backspace character causes the */
745
+ /* size of the string to reduced if it is "added" to */
746
+ /* the string. */
747
+ /*******************************************************/
748
+ char *ExpandStringWithChar(
749
+ Environment *theEnv,
750
+ int inchar,
751
+ char *str,
752
+ size_t *pos,
753
+ size_t *max,
754
+ size_t newSize)
755
+ {
756
+ if ((*pos + 1) >= *max)
757
+ {
758
+ if (newSize < sizeof(char *))
759
+ { newSize = sizeof(char *); }
760
+ str = (char *) genrealloc(theEnv,str,*max,newSize);
761
+ *max = newSize;
762
+ }
763
+
764
+ if (inchar != '\b')
765
+ {
766
+ str[*pos] = (char) inchar;
767
+ (*pos)++;
768
+ str[*pos] = '\0';
769
+ }
770
+ else
771
+ {
772
+ /*===========================================================*/
773
+ /* First delete any UTF-8 multibyte continuation characters. */
774
+ /*===========================================================*/
775
+
776
+ while ((*pos > 1) && IsUTF8MultiByteContinuation(str[*pos - 1]))
777
+ { (*pos)--; }
778
+
779
+ /*===================================================*/
780
+ /* Now delete the first byte of the UTF-8 character. */
781
+ /*===================================================*/
782
+
783
+ if (*pos > 0) (*pos)--;
784
+ str[*pos] = '\0';
785
+ }
786
+
787
+ return(str);
788
+ }
789
+
790
+ /**********************************************************/
791
+ /* AddVoidFunctionToCallList: Adds a function to a list */
792
+ /* of functions which are called to perform certain */
793
+ /* operations (e.g. clear, reset, and bload functions). */
794
+ /**********************************************************/
795
+ struct voidCallFunctionItem *AddVoidFunctionToCallList(
796
+ Environment *theEnv,
797
+ const char *name,
798
+ int priority,
799
+ VoidCallFunction *func,
800
+ struct voidCallFunctionItem *head,
801
+ void *context)
802
+ {
803
+ struct voidCallFunctionItem *newPtr, *currentPtr, *lastPtr = NULL;
804
+ char *nameCopy;
805
+
806
+ newPtr = get_struct(theEnv,voidCallFunctionItem);
807
+
808
+ nameCopy = (char *) genalloc(theEnv,strlen(name) + 1);
809
+ genstrcpy(nameCopy,name);
810
+ newPtr->name = nameCopy;
811
+
812
+ newPtr->func = func;
813
+ newPtr->priority = priority;
814
+ newPtr->context = context;
815
+
816
+ if (head == NULL)
817
+ {
818
+ newPtr->next = NULL;
819
+ return(newPtr);
820
+ }
821
+
822
+ currentPtr = head;
823
+ while ((currentPtr != NULL) ? (priority < currentPtr->priority) : false)
824
+ {
825
+ lastPtr = currentPtr;
826
+ currentPtr = currentPtr->next;
827
+ }
828
+
829
+ if (lastPtr == NULL)
830
+ {
831
+ newPtr->next = head;
832
+ head = newPtr;
833
+ }
834
+ else
835
+ {
836
+ newPtr->next = currentPtr;
837
+ lastPtr->next = newPtr;
838
+ }
839
+
840
+ return(head);
841
+ }
842
+
843
+ /**********************************************************/
844
+ /* AddBoolFunctionToCallList: Adds a function to a list */
845
+ /* of functions which are called to perform certain */
846
+ /* operations (e.g. clear, reset, and bload functions). */
847
+ /**********************************************************/
848
+ BoolCallFunctionItem *AddBoolFunctionToCallList(
849
+ Environment *theEnv,
850
+ const char *name,
851
+ int priority,
852
+ BoolCallFunction *func,
853
+ BoolCallFunctionItem *head,
854
+ void *context)
855
+ {
856
+ struct boolCallFunctionItem *newPtr, *currentPtr, *lastPtr = NULL;
857
+ char *nameCopy;
858
+
859
+ newPtr = get_struct(theEnv,boolCallFunctionItem);
860
+
861
+ nameCopy = (char *) genalloc(theEnv,strlen(name) + 1);
862
+ genstrcpy(nameCopy,name);
863
+ newPtr->name = nameCopy;
864
+
865
+ newPtr->func = func;
866
+ newPtr->priority = priority;
867
+ newPtr->context = context;
868
+
869
+ if (head == NULL)
870
+ {
871
+ newPtr->next = NULL;
872
+ return(newPtr);
873
+ }
874
+
875
+ currentPtr = head;
876
+ while ((currentPtr != NULL) ? (priority < currentPtr->priority) : false)
877
+ {
878
+ lastPtr = currentPtr;
879
+ currentPtr = currentPtr->next;
880
+ }
881
+
882
+ if (lastPtr == NULL)
883
+ {
884
+ newPtr->next = head;
885
+ head = newPtr;
886
+ }
887
+ else
888
+ {
889
+ newPtr->next = currentPtr;
890
+ lastPtr->next = newPtr;
891
+ }
892
+
893
+ return(head);
894
+ }
895
+
896
+ /****************************************************************/
897
+ /* GetVoidFunctionFromCallList: Retrieves a function from a list of */
898
+ /* functions which are called to perform certain operations */
899
+ /* (e.g. clear, reset, and bload functions). */
900
+ /****************************************************************/
901
+ struct voidCallFunctionItem *GetVoidFunctionFromCallList(
902
+ Environment *theEnv,
903
+ const char *name,
904
+ struct voidCallFunctionItem *head)
905
+ {
906
+ struct voidCallFunctionItem *currentPtr;
907
+
908
+ for (currentPtr = head; currentPtr != NULL; currentPtr = currentPtr->next)
909
+ {
910
+ if (strcmp(name,currentPtr->name) == 0)
911
+ { return currentPtr; }
912
+ }
913
+
914
+ return NULL;
915
+ }
916
+
917
+ /****************************************************************/
918
+ /* GetBoolFunctionFromCallList: Retrieves a function from a list of */
919
+ /* functions which are called to perform certain operations */
920
+ /* (e.g. clear, reset, and bload functions). */
921
+ /****************************************************************/
922
+ struct boolCallFunctionItem *GetBoolFunctionFromCallList(
923
+ Environment *theEnv,
924
+ const char *name,
925
+ struct boolCallFunctionItem *head)
926
+ {
927
+ struct boolCallFunctionItem *currentPtr;
928
+
929
+ for (currentPtr = head; currentPtr != NULL; currentPtr = currentPtr->next)
930
+ {
931
+ if (strcmp(name,currentPtr->name) == 0)
932
+ { return currentPtr; }
933
+ }
934
+
935
+ return NULL;
936
+ }
937
+
938
+ /******************************************************************/
939
+ /* RemoveVoidFunctionFromCallList: Removes a function from a list */
940
+ /* of functions which are called to perform certain operations */
941
+ /* (e.g. clear, reset, and bload functions). */
942
+ /******************************************************************/
943
+ struct voidCallFunctionItem *RemoveVoidFunctionFromCallList(
944
+ Environment *theEnv,
945
+ const char *name,
946
+ struct voidCallFunctionItem *head,
947
+ bool *found)
948
+ {
949
+ struct voidCallFunctionItem *currentPtr, *lastPtr;
950
+
951
+ *found = false;
952
+ lastPtr = NULL;
953
+ currentPtr = head;
954
+
955
+ while (currentPtr != NULL)
956
+ {
957
+ if (strcmp(name,currentPtr->name) == 0)
958
+ {
959
+ *found = true;
960
+ if (lastPtr == NULL)
961
+ { head = currentPtr->next; }
962
+ else
963
+ { lastPtr->next = currentPtr->next; }
964
+
965
+ genfree(theEnv,(void *) currentPtr->name,strlen(currentPtr->name) + 1);
966
+ rtn_struct(theEnv,voidCallFunctionItem,currentPtr);
967
+ return head;
968
+ }
969
+
970
+ lastPtr = currentPtr;
971
+ currentPtr = currentPtr->next;
972
+ }
973
+
974
+ return head;
975
+ }
976
+
977
+ /******************************************************************/
978
+ /* RemoveBoolFunctionFromCallList: Removes a function from a list */
979
+ /* of functions which are called to perform certain operations */
980
+ /* (e.g. clear, reset, and bload functions). */
981
+ /******************************************************************/
982
+ struct boolCallFunctionItem *RemoveBoolFunctionFromCallList(
983
+ Environment *theEnv,
984
+ const char *name,
985
+ struct boolCallFunctionItem *head,
986
+ bool *found)
987
+ {
988
+ struct boolCallFunctionItem *currentPtr, *lastPtr;
989
+
990
+ *found = false;
991
+ lastPtr = NULL;
992
+ currentPtr = head;
993
+
994
+ while (currentPtr != NULL)
995
+ {
996
+ if (strcmp(name,currentPtr->name) == 0)
997
+ {
998
+ *found = true;
999
+ if (lastPtr == NULL)
1000
+ { head = currentPtr->next; }
1001
+ else
1002
+ { lastPtr->next = currentPtr->next; }
1003
+
1004
+ genfree(theEnv,(void *) currentPtr->name,strlen(currentPtr->name) + 1);
1005
+ rtn_struct(theEnv,boolCallFunctionItem,currentPtr);
1006
+ return head;
1007
+ }
1008
+
1009
+ lastPtr = currentPtr;
1010
+ currentPtr = currentPtr->next;
1011
+ }
1012
+
1013
+ return head;
1014
+ }
1015
+
1016
+ /*************************************************************/
1017
+ /* DeallocateVoidCallList: Removes all functions from a list */
1018
+ /* of functions which are called to perform certain */
1019
+ /* operations (e.g. clear, reset, and bload functions). */
1020
+ /*************************************************************/
1021
+ void DeallocateVoidCallList(
1022
+ Environment *theEnv,
1023
+ struct voidCallFunctionItem *theList)
1024
+ {
1025
+ struct voidCallFunctionItem *tmpPtr, *nextPtr;
1026
+
1027
+ tmpPtr = theList;
1028
+ while (tmpPtr != NULL)
1029
+ {
1030
+ nextPtr = tmpPtr->next;
1031
+ genfree(theEnv,(void *) tmpPtr->name,strlen(tmpPtr->name) + 1);
1032
+ rtn_struct(theEnv,voidCallFunctionItem,tmpPtr);
1033
+ tmpPtr = nextPtr;
1034
+ }
1035
+ }
1036
+
1037
+ /*************************************************************/
1038
+ /* DeallocateBoolCallList: Removes all functions from a list */
1039
+ /* of functions which are called to perform certain */
1040
+ /* operations (e.g. clear, reset, and bload functions). */
1041
+ /*************************************************************/
1042
+ void DeallocateBoolCallList(
1043
+ Environment *theEnv,
1044
+ struct boolCallFunctionItem *theList)
1045
+ {
1046
+ struct boolCallFunctionItem *tmpPtr, *nextPtr;
1047
+
1048
+ tmpPtr = theList;
1049
+ while (tmpPtr != NULL)
1050
+ {
1051
+ nextPtr = tmpPtr->next;
1052
+ genfree(theEnv,(void *) tmpPtr->name,strlen(tmpPtr->name) + 1);
1053
+ rtn_struct(theEnv,boolCallFunctionItem,tmpPtr);
1054
+ tmpPtr = nextPtr;
1055
+ }
1056
+ }
1057
+
1058
+ /***********************************************************/
1059
+ /* AddFunctionToCallListWithArg: Adds a function to a list */
1060
+ /* of functions which are called to perform certain */
1061
+ /* operations (e.g. clear, reset, and bload functions). */
1062
+ /***********************************************************/
1063
+ struct callFunctionItemWithArg *AddFunctionToCallListWithArg(
1064
+ Environment *theEnv,
1065
+ const char *name,
1066
+ int priority,
1067
+ VoidCallFunctionWithArg *func,
1068
+ struct callFunctionItemWithArg *head,
1069
+ void *context)
1070
+ {
1071
+ struct callFunctionItemWithArg *newPtr, *currentPtr, *lastPtr = NULL;
1072
+
1073
+ newPtr = get_struct(theEnv,callFunctionItemWithArg);
1074
+
1075
+ newPtr->name = name;
1076
+ newPtr->func = func;
1077
+ newPtr->priority = priority;
1078
+ newPtr->context = context;
1079
+
1080
+ if (head == NULL)
1081
+ {
1082
+ newPtr->next = NULL;
1083
+ return(newPtr);
1084
+ }
1085
+
1086
+ currentPtr = head;
1087
+ while ((currentPtr != NULL) ? (priority < currentPtr->priority) : false)
1088
+ {
1089
+ lastPtr = currentPtr;
1090
+ currentPtr = currentPtr->next;
1091
+ }
1092
+
1093
+ if (lastPtr == NULL)
1094
+ {
1095
+ newPtr->next = head;
1096
+ head = newPtr;
1097
+ }
1098
+ else
1099
+ {
1100
+ newPtr->next = currentPtr;
1101
+ lastPtr->next = newPtr;
1102
+ }
1103
+
1104
+ return(head);
1105
+ }
1106
+
1107
+ /**************************************************************/
1108
+ /* RemoveFunctionFromCallListWithArg: Removes a function from */
1109
+ /* a list of functions which are called to perform certain */
1110
+ /* operations (e.g. clear, reset, and bload functions). */
1111
+ /**************************************************************/
1112
+ struct callFunctionItemWithArg *RemoveFunctionFromCallListWithArg(
1113
+ Environment *theEnv,
1114
+ const char *name,
1115
+ struct callFunctionItemWithArg *head,
1116
+ bool *found)
1117
+ {
1118
+ struct callFunctionItemWithArg *currentPtr, *lastPtr;
1119
+
1120
+ *found = false;
1121
+ lastPtr = NULL;
1122
+ currentPtr = head;
1123
+
1124
+ while (currentPtr != NULL)
1125
+ {
1126
+ if (strcmp(name,currentPtr->name) == 0)
1127
+ {
1128
+ *found = true;
1129
+ if (lastPtr == NULL)
1130
+ { head = currentPtr->next; }
1131
+ else
1132
+ { lastPtr->next = currentPtr->next; }
1133
+
1134
+ rtn_struct(theEnv,callFunctionItemWithArg,currentPtr);
1135
+ return(head);
1136
+ }
1137
+
1138
+ lastPtr = currentPtr;
1139
+ currentPtr = currentPtr->next;
1140
+ }
1141
+
1142
+ return(head);
1143
+ }
1144
+
1145
+ /****************************************************************/
1146
+ /* DeallocateCallListWithArg: Removes all functions from a list */
1147
+ /* of functions which are called to perform certain */
1148
+ /* operations (e.g. clear, reset, and bload functions). */
1149
+ /****************************************************************/
1150
+ void DeallocateCallListWithArg(
1151
+ Environment *theEnv,
1152
+ struct callFunctionItemWithArg *theList)
1153
+ {
1154
+ struct callFunctionItemWithArg *tmpPtr, *nextPtr;
1155
+
1156
+ tmpPtr = theList;
1157
+ while (tmpPtr != NULL)
1158
+ {
1159
+ nextPtr = tmpPtr->next;
1160
+ rtn_struct(theEnv,callFunctionItemWithArg,tmpPtr);
1161
+ tmpPtr = nextPtr;
1162
+ }
1163
+ }
1164
+
1165
+ /*****************************************/
1166
+ /* ItemHashValue: Returns the hash value */
1167
+ /* for the specified value. */
1168
+ /*****************************************/
1169
+ size_t ItemHashValue(
1170
+ Environment *theEnv,
1171
+ unsigned short theType,
1172
+ void *theValue,
1173
+ size_t theRange)
1174
+ {
1175
+ #if OBJECT_SYSTEM
1176
+ union
1177
+ {
1178
+ void *vv;
1179
+ unsigned uv;
1180
+ } fis;
1181
+ #endif
1182
+
1183
+ switch(theType)
1184
+ {
1185
+ case FLOAT_TYPE:
1186
+ return HashFloat(((CLIPSFloat *) theValue)->contents,theRange);
1187
+
1188
+ case INTEGER_TYPE:
1189
+ return HashInteger(((CLIPSInteger *) theValue)->contents,theRange);
1190
+
1191
+ case SYMBOL_TYPE:
1192
+ case STRING_TYPE:
1193
+ #if OBJECT_SYSTEM
1194
+ case INSTANCE_NAME_TYPE:
1195
+ #endif
1196
+ return HashSymbol(((CLIPSLexeme *) theValue)->contents,theRange);
1197
+
1198
+ case MULTIFIELD_TYPE:
1199
+ return HashMultifield((Multifield *) theValue,theRange);
1200
+
1201
+ #if DEFTEMPLATE_CONSTRUCT
1202
+ case FACT_ADDRESS_TYPE:
1203
+ return (((Fact *) theValue)->hashValue % theRange);
1204
+ #endif
1205
+
1206
+ case EXTERNAL_ADDRESS_TYPE:
1207
+ return HashExternalAddress(((CLIPSExternalAddress *) theValue)->contents,theRange);
1208
+
1209
+ #if OBJECT_SYSTEM
1210
+ case INSTANCE_ADDRESS_TYPE:
1211
+ fis.uv = 0;
1212
+ fis.vv = theValue;
1213
+ return (fis.uv % theRange);
1214
+ #endif
1215
+ }
1216
+
1217
+ SystemError(theEnv,"UTILITY",1);
1218
+ return 0;
1219
+ }
1220
+
1221
+ /********************************************/
1222
+ /* YieldTime: Yields time to a user-defined */
1223
+ /* function. Intended to allow foreground */
1224
+ /* application responsiveness when CLIPS */
1225
+ /* is running in the background. */
1226
+ /********************************************/
1227
+ void YieldTime(
1228
+ Environment *theEnv)
1229
+ {
1230
+ if ((UtilityData(theEnv)->YieldTimeFunction != NULL) && UtilityData(theEnv)->YieldFunctionEnabled)
1231
+ { (*UtilityData(theEnv)->YieldTimeFunction)(); }
1232
+ }
1233
+
1234
+ /****************************/
1235
+ /* EnablePeriodicFunctions: */
1236
+ /****************************/
1237
+ bool EnablePeriodicFunctions(
1238
+ Environment *theEnv,
1239
+ bool value)
1240
+ {
1241
+ bool oldValue;
1242
+
1243
+ oldValue = UtilityData(theEnv)->PeriodicFunctionsEnabled;
1244
+
1245
+ UtilityData(theEnv)->PeriodicFunctionsEnabled = value;
1246
+
1247
+ return oldValue;
1248
+ }
1249
+
1250
+ /************************/
1251
+ /* EnableYieldFunction: */
1252
+ /************************/
1253
+ bool EnableYieldFunction(
1254
+ Environment *theEnv,
1255
+ bool value)
1256
+ {
1257
+ bool oldValue;
1258
+
1259
+ oldValue = UtilityData(theEnv)->YieldFunctionEnabled;
1260
+
1261
+ UtilityData(theEnv)->YieldFunctionEnabled = value;
1262
+
1263
+ return oldValue;
1264
+ }
1265
+
1266
+ /*************************************************************************/
1267
+ /* AddTrackedMemory: Tracked memory is memory allocated by CLIPS that's */
1268
+ /* referenced by a variable on the stack, but not by any environment */
1269
+ /* data structure. An example would be the storage for local variables */
1270
+ /* allocated when a deffunction is executed. Tracking this memory */
1271
+ /* allows it to be removed later when using longjmp as the code that */
1272
+ /* would normally deallocate the memory would be bypassed. */
1273
+ /*************************************************************************/
1274
+ struct trackedMemory *AddTrackedMemory(
1275
+ Environment *theEnv,
1276
+ void *theMemory,
1277
+ size_t theSize)
1278
+ {
1279
+ struct trackedMemory *newPtr;
1280
+
1281
+ newPtr = get_struct(theEnv,trackedMemory);
1282
+
1283
+ newPtr->prev = NULL;
1284
+ newPtr->theMemory = theMemory;
1285
+ newPtr->memSize = theSize;
1286
+ newPtr->next = UtilityData(theEnv)->trackList;
1287
+ UtilityData(theEnv)->trackList = newPtr;
1288
+
1289
+ return newPtr;
1290
+ }
1291
+
1292
+ /************************/
1293
+ /* RemoveTrackedMemory: */
1294
+ /************************/
1295
+ void RemoveTrackedMemory(
1296
+ Environment *theEnv,
1297
+ struct trackedMemory *theTracker)
1298
+ {
1299
+ if (theTracker->prev == NULL)
1300
+ { UtilityData(theEnv)->trackList = theTracker->next; }
1301
+ else
1302
+ { theTracker->prev->next = theTracker->next; }
1303
+
1304
+ if (theTracker->next != NULL)
1305
+ { theTracker->next->prev = theTracker->prev; }
1306
+
1307
+ rtn_struct(theEnv,trackedMemory,theTracker);
1308
+ }
1309
+
1310
+ /******************************************/
1311
+ /* UTF8Length: Returns the logical number */
1312
+ /* of characters in a UTF8 string. */
1313
+ /******************************************/
1314
+ size_t UTF8Length(
1315
+ const char *s)
1316
+ {
1317
+ size_t i = 0, length = 0;
1318
+
1319
+ while (s[i] != '\0')
1320
+ {
1321
+ UTF8Increment(s,&i);
1322
+ length++;
1323
+ }
1324
+
1325
+ return(length);
1326
+ }
1327
+
1328
+ /*********************************************/
1329
+ /* UTF8Increment: Finds the beginning of the */
1330
+ /* next character in a UTF8 string. */
1331
+ /*********************************************/
1332
+ void UTF8Increment(
1333
+ const char *s,
1334
+ size_t *i)
1335
+ {
1336
+ (void) (IsUTF8Start(s[++(*i)]) ||
1337
+ IsUTF8Start(s[++(*i)]) ||
1338
+ IsUTF8Start(s[++(*i)]) ||
1339
+ ++(*i));
1340
+ }
1341
+
1342
+ /****************************************************/
1343
+ /* UTF8Offset: Converts the logical character index */
1344
+ /* in a UTF8 string to the actual byte offset. */
1345
+ /****************************************************/
1346
+ size_t UTF8Offset(
1347
+ const char *str,
1348
+ size_t charnum)
1349
+ {
1350
+ size_t offs = 0;
1351
+
1352
+ while ((charnum > 0) && (str[offs]))
1353
+ {
1354
+ (void) (IsUTF8Start(str[++offs]) ||
1355
+ IsUTF8Start(str[++offs]) ||
1356
+ IsUTF8Start(str[++offs]) ||
1357
+ ++offs);
1358
+
1359
+ charnum--;
1360
+ }
1361
+
1362
+ return offs;
1363
+ }
1364
+
1365
+ /*************************************************/
1366
+ /* UTF8CharNum: Converts the UTF8 character byte */
1367
+ /* offset to the logical character index. */
1368
+ /*************************************************/
1369
+ size_t UTF8CharNum(
1370
+ const char *s,
1371
+ size_t offset)
1372
+ {
1373
+ size_t charnum = 0, offs=0;
1374
+
1375
+ while ((offs < offset) && (s[offs]))
1376
+ {
1377
+ (void) (IsUTF8Start(s[++offs]) ||
1378
+ IsUTF8Start(s[++offs]) ||
1379
+ IsUTF8Start(s[++offs]) ||
1380
+ ++offs);
1381
+
1382
+ charnum++;
1383
+ }
1384
+
1385
+ return charnum;
1386
+ }
1387
+
1388
+ /************************/
1389
+ /* CreateStringBuilder: */
1390
+ /************************/
1391
+ StringBuilder *CreateStringBuilder(
1392
+ Environment *theEnv,
1393
+ size_t theSize)
1394
+ {
1395
+ StringBuilder *theSB;
1396
+
1397
+ theSB = get_struct(theEnv,stringBuilder);
1398
+ if (theSB == NULL) return NULL;
1399
+
1400
+ theSize++;
1401
+ theSB->sbEnv = theEnv;
1402
+ theSB->bufferReset = theSize;
1403
+ theSB->bufferMaximum = theSize;
1404
+ theSB->length = 0;
1405
+ theSB->contents = (char *) gm2(theEnv,theSize);
1406
+ theSB->contents[0] = EOS;
1407
+
1408
+ return theSB;
1409
+ }
1410
+
1411
+ /*************/
1412
+ /* SBAppend: */
1413
+ /*************/
1414
+ void SBAppend(
1415
+ StringBuilder *theSB,
1416
+ const char *appendString)
1417
+ {
1418
+ theSB->contents = AppendToString(theSB->sbEnv,appendString,
1419
+ theSB->contents,&theSB->length,&theSB->bufferMaximum);
1420
+ }
1421
+
1422
+ /********************/
1423
+ /* SBAppendInteger: */
1424
+ /********************/
1425
+ void SBAppendInteger(
1426
+ StringBuilder *theSB,
1427
+ long long value)
1428
+ {
1429
+ const char *appendString;
1430
+
1431
+ appendString = LongIntegerToString(theSB->sbEnv,value);
1432
+
1433
+ theSB->contents = AppendToString(theSB->sbEnv,appendString,
1434
+ theSB->contents,&theSB->length,&theSB->bufferMaximum);
1435
+ }
1436
+
1437
+ /******************/
1438
+ /* SBAppendFloat: */
1439
+ /******************/
1440
+ void SBAppendFloat(
1441
+ StringBuilder *theSB,
1442
+ double value)
1443
+ {
1444
+ const char *appendString;
1445
+
1446
+ appendString = FloatToString(theSB->sbEnv,value);
1447
+
1448
+ theSB->contents = AppendToString(theSB->sbEnv,appendString,
1449
+ theSB->contents,&theSB->length,&theSB->bufferMaximum);
1450
+ }
1451
+
1452
+ /**************/
1453
+ /* SBAddChar: */
1454
+ /**************/
1455
+ void SBAddChar(
1456
+ StringBuilder *theSB,
1457
+ int theChar)
1458
+ {
1459
+ theSB->contents = ExpandStringWithChar(theSB->sbEnv,theChar,theSB->contents,
1460
+ &theSB->length,&theSB->bufferMaximum,
1461
+ theSB->bufferMaximum+80);
1462
+ }
1463
+
1464
+ /***********/
1465
+ /* SBReset */
1466
+ /***********/
1467
+ void SBReset(
1468
+ StringBuilder *theSB)
1469
+ {
1470
+ if (theSB->bufferReset != theSB->bufferMaximum)
1471
+ {
1472
+ rm(theSB->sbEnv,theSB->contents,theSB->bufferMaximum);
1473
+ theSB->contents = (char *) gm2(theSB->sbEnv,theSB->bufferReset);
1474
+ theSB->bufferMaximum = theSB->bufferReset;
1475
+ }
1476
+
1477
+ theSB->length = 0;
1478
+ theSB->contents[0] = EOS;
1479
+ }
1480
+
1481
+ /**********/
1482
+ /* SBCopy */
1483
+ /**********/
1484
+ char *SBCopy(
1485
+ StringBuilder *theSB)
1486
+ {
1487
+ char *stringCopy;
1488
+
1489
+ stringCopy = (char *) malloc(strlen(theSB->contents) + 1);
1490
+ strcpy(stringCopy,theSB->contents);
1491
+
1492
+ return stringCopy;
1493
+ }
1494
+
1495
+ /**************/
1496
+ /* SBDispose: */
1497
+ /**************/
1498
+ void SBDispose(
1499
+ StringBuilder *theSB)
1500
+ {
1501
+ Environment *theEnv = theSB->sbEnv;
1502
+ rm(theEnv,theSB->contents,theSB->bufferMaximum);
1503
+ rtn_struct(theEnv,stringBuilder,theSB);
1504
+ }
1505
+
1506
+ /***************************************************
1507
+ NAME : BufferedRead
1508
+ DESCRIPTION : Reads data from binary file
1509
+ (Larger blocks than requested size
1510
+ may be read and buffered)
1511
+ INPUTS : 1) The buffer
1512
+ 2) The buffer size
1513
+ RETURNS : Nothing useful
1514
+ SIDE EFFECTS : Data stored in buffer
1515
+ NOTES : None
1516
+ ***************************************************/
1517
+ void BufferedRead(
1518
+ Environment *theEnv,
1519
+ void *buf,
1520
+ size_t bufsz)
1521
+ {
1522
+ size_t i, amountLeftToRead;
1523
+
1524
+ if (UtilityData(theEnv)->CurrentReadBuffer != NULL)
1525
+ {
1526
+ amountLeftToRead = UtilityData(theEnv)->CurrentReadBufferSize - UtilityData(theEnv)->CurrentReadBufferOffset;
1527
+ if (bufsz <= amountLeftToRead)
1528
+ {
1529
+ for (i = 0L ; i < bufsz ; i++)
1530
+ ((char *) buf)[i] = UtilityData(theEnv)->CurrentReadBuffer[i + UtilityData(theEnv)->CurrentReadBufferOffset];
1531
+ UtilityData(theEnv)->CurrentReadBufferOffset += bufsz;
1532
+ if (UtilityData(theEnv)->CurrentReadBufferOffset == UtilityData(theEnv)->CurrentReadBufferSize)
1533
+ FreeReadBuffer(theEnv);
1534
+ }
1535
+ else
1536
+ {
1537
+ if (UtilityData(theEnv)->CurrentReadBufferOffset < UtilityData(theEnv)->CurrentReadBufferSize)
1538
+ {
1539
+ for (i = 0 ; i < amountLeftToRead ; i++)
1540
+ ((char *) buf)[i] = UtilityData(theEnv)->CurrentReadBuffer[i + UtilityData(theEnv)->CurrentReadBufferOffset];
1541
+ bufsz -= amountLeftToRead;
1542
+ buf = (void *) (((char *) buf) + amountLeftToRead);
1543
+ }
1544
+ FreeReadBuffer(theEnv);
1545
+ BufferedRead(theEnv,buf,bufsz);
1546
+ }
1547
+ }
1548
+ else
1549
+ {
1550
+ if (bufsz > MAX_BLOCK_SIZE)
1551
+ {
1552
+ UtilityData(theEnv)->CurrentReadBufferSize = bufsz;
1553
+ if (bufsz > (UtilityData(theEnv)->BinaryFileSize - UtilityData(theEnv)->BinaryFileOffset))
1554
+ {
1555
+ SystemError(theEnv,"INSFILE",2);
1556
+ ExitRouter(theEnv,EXIT_FAILURE);
1557
+ }
1558
+ }
1559
+ else if (MAX_BLOCK_SIZE >
1560
+ (UtilityData(theEnv)->BinaryFileSize - UtilityData(theEnv)->BinaryFileOffset))
1561
+ {
1562
+ UtilityData(theEnv)->CurrentReadBufferSize = UtilityData(theEnv)->BinaryFileSize - UtilityData(theEnv)->BinaryFileOffset;
1563
+ }
1564
+ else
1565
+ { UtilityData(theEnv)->CurrentReadBufferSize = (unsigned long) MAX_BLOCK_SIZE; }
1566
+
1567
+ UtilityData(theEnv)->CurrentReadBuffer = (char *) genalloc(theEnv,UtilityData(theEnv)->CurrentReadBufferSize);
1568
+ GenReadBinary(theEnv,UtilityData(theEnv)->CurrentReadBuffer,UtilityData(theEnv)->CurrentReadBufferSize);
1569
+ for (i = 0L ; i < bufsz ; i++)
1570
+ ((char *) buf)[i] = UtilityData(theEnv)->CurrentReadBuffer[i];
1571
+ UtilityData(theEnv)->CurrentReadBufferOffset = bufsz;
1572
+ UtilityData(theEnv)->BinaryFileOffset += UtilityData(theEnv)->CurrentReadBufferSize;
1573
+ }
1574
+ }
1575
+
1576
+ /*****************************************************
1577
+ NAME : FreeReadBuffer
1578
+ DESCRIPTION : Deallocates buffer for binary reads
1579
+ INPUTS : None
1580
+ RETURNS : Nothing usefu
1581
+ SIDE EFFECTS : Binary global read buffer deallocated
1582
+ NOTES : None
1583
+ *****************************************************/
1584
+ void FreeReadBuffer(
1585
+ Environment *theEnv)
1586
+ {
1587
+ if (UtilityData(theEnv)->CurrentReadBufferSize != 0L)
1588
+ {
1589
+ genfree(theEnv,UtilityData(theEnv)->CurrentReadBuffer,UtilityData(theEnv)->CurrentReadBufferSize);
1590
+ UtilityData(theEnv)->CurrentReadBuffer = NULL;
1591
+ UtilityData(theEnv)->CurrentReadBufferSize = 0L;
1592
+ UtilityData(theEnv)->CurrentReadBufferOffset = 0L; // TBD Added
1593
+ }
1594
+ }