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,1173 @@
1
+ /*******************************************************/
2
+ /* "C" Language Integrated Production System */
3
+ /* */
4
+ /* CLIPS Version 6.41 12/04/22 */
5
+ /* */
6
+ /* STRING_TYPE FUNCTIONS MODULE */
7
+ /*******************************************************/
8
+
9
+ /*************************************************************/
10
+ /* Purpose: Contains the code for several string functions */
11
+ /* including str-cat, sym-cat, str-length, str-compare, */
12
+ /* upcase, lowcase, sub-string, str-index, eval, and */
13
+ /* build. */
14
+ /* */
15
+ /* Principal Programmer(s): */
16
+ /* Gary D. Riley */
17
+ /* */
18
+ /* Contributing Programmer(s): */
19
+ /* Barry Cameron */
20
+ /* */
21
+ /* Revision History: */
22
+ /* */
23
+ /* 6.23: Correction for FalseSymbol/TrueSymbol. DR0859 */
24
+ /* */
25
+ /* 6.30: Support for long long integers. */
26
+ /* */
27
+ /* Removed conditional code for unsupported */
28
+ /* compilers/operating systems (IBM_MCW and */
29
+ /* MAC_MCW). */
30
+ /* */
31
+ /* Used gensprintf instead of sprintf. */
32
+ /* */
33
+ /* Changed integer type/precision. */
34
+ /* */
35
+ /* Changed garbage collection algorithm. */
36
+ /* */
37
+ /* Added support for UTF-8 strings to str-length, */
38
+ /* str-index, and sub-string functions. */
39
+ /* */
40
+ /* Added const qualifiers to remove C++ */
41
+ /* deprecation warnings. */
42
+ /* */
43
+ /* Added code to keep track of pointers to */
44
+ /* constructs that are contained externally to */
45
+ /* to constructs, DanglingConstructs. */
46
+ /* */
47
+ /* Fixed str-cat bug that could be invoked by */
48
+ /* (funcall str-cat). */
49
+ /* */
50
+ /* 6.31: Prior error flags are cleared before Eval */
51
+ /* and Build are processed. */
52
+ /* */
53
+ /* 6.40: Added Env prefix to GetEvaluationError and */
54
+ /* SetEvaluationError functions. */
55
+ /* */
56
+ /* Added Env prefix to GetHaltExecution and */
57
+ /* SetHaltExecution functions. */
58
+ /* */
59
+ /* Pragma once and other inclusion changes. */
60
+ /* */
61
+ /* Added support for booleans with <stdbool.h>. */
62
+ /* */
63
+ /* Removed use of void pointers for specific */
64
+ /* data structures. */
65
+ /* */
66
+ /* UDF redesign. */
67
+ /* */
68
+ /* Eval support for run time and bload only. */
69
+ /* */
70
+ /* The eval function can now access any local */
71
+ /* variables that have been defined. */
72
+ /* */
73
+ /* The str-index function now returns 1 if the */
74
+ /* search string is "". */
75
+ /* */
76
+ /* The eval and build functions generate an */
77
+ /* error if extraneous input is encountered. */
78
+ /* */
79
+ /* Added str-replace function. */
80
+ /* */
81
+ /* 6.41: Used gensnprintf in place of gensprintf and. */
82
+ /* sprintf. */
83
+ /* */
84
+ /*************************************************************/
85
+
86
+ #include "setup.h"
87
+
88
+ #if STRING_FUNCTIONS
89
+
90
+ #include <stdio.h>
91
+ #include <ctype.h>
92
+ #include <string.h>
93
+
94
+ #include "argacces.h"
95
+ #include "commline.h"
96
+ #include "constrct.h"
97
+ #include "cstrcpsr.h"
98
+ #include "engine.h"
99
+ #include "envrnmnt.h"
100
+ #include "exprnpsr.h"
101
+ #include "extnfunc.h"
102
+ #include "memalloc.h"
103
+ #include "miscfun.h"
104
+ #include "multifld.h"
105
+ #include "prcdrpsr.h"
106
+ #include "pprint.h"
107
+ #include "prntutil.h"
108
+ #include "router.h"
109
+ #include "strngrtr.h"
110
+ #include "scanner.h"
111
+ #include "sysdep.h"
112
+ #include "utility.h"
113
+
114
+ #if DEFRULE_CONSTRUCT
115
+ #include "drive.h"
116
+ #endif
117
+
118
+ #include "strngfun.h"
119
+
120
+ /***************************************/
121
+ /* LOCAL INTERNAL FUNCTION DEFINITIONS */
122
+ /***************************************/
123
+
124
+ static void StrOrSymCatFunction(UDFContext *,UDFValue *,unsigned short);
125
+
126
+ /******************************************/
127
+ /* StringFunctionDefinitions: Initializes */
128
+ /* the string manipulation functions. */
129
+ /******************************************/
130
+ void StringFunctionDefinitions(
131
+ Environment *theEnv)
132
+ {
133
+ #if ! RUN_TIME
134
+ AddUDF(theEnv,"str-cat","sy",1,UNBOUNDED,"synld" ,StrCatFunction,"StrCatFunction",NULL);
135
+ AddUDF(theEnv,"sym-cat","sy",1,UNBOUNDED,"synld" ,SymCatFunction,"SymCatFunction",NULL);
136
+ AddUDF(theEnv,"str-length","l",1,1,"syn",StrLengthFunction,"StrLengthFunction",NULL);
137
+ AddUDF(theEnv,"str-compare","l",2,3,"*;syn;syn;l" ,StrCompareFunction,"StrCompareFunction",NULL);
138
+ AddUDF(theEnv,"upcase","syn",1,1,"syn",UpcaseFunction,"UpcaseFunction",NULL);
139
+ AddUDF(theEnv,"lowcase","syn",1,1,"syn",LowcaseFunction,"LowcaseFunction",NULL);
140
+ AddUDF(theEnv,"sub-string","s",3,3,"*;l;l;syn",SubStringFunction,"SubStringFunction",NULL);
141
+ AddUDF(theEnv,"str-index","bl",2,2,"syn",StrIndexFunction,"StrIndexFunction",NULL);
142
+ AddUDF(theEnv,"eval","*",1,1,"sy",EvalFunction,"EvalFunction",NULL);
143
+ AddUDF(theEnv,"build","b",1,1,"sy",BuildFunction,"BuildFunction",NULL);
144
+ AddUDF(theEnv,"string-to-field","*",1,1,"syn",StringToFieldFunction,"StringToFieldFunction",NULL);
145
+ AddUDF(theEnv,"str-replace","syn",3,3,"syn",StrReplaceFunction,"StrReplaceFunction",NULL);
146
+ #else
147
+ #if MAC_XCD
148
+ #pragma unused(theEnv)
149
+ #endif
150
+ #endif
151
+ }
152
+
153
+ /****************************************/
154
+ /* StrCatFunction: H/L access routine */
155
+ /* for the str-cat function. */
156
+ /****************************************/
157
+ void StrCatFunction(
158
+ Environment *theEnv,
159
+ UDFContext *context,
160
+ UDFValue *returnValue)
161
+ {
162
+ StrOrSymCatFunction(context,returnValue,STRING_TYPE);
163
+ }
164
+
165
+ /****************************************/
166
+ /* SymCatFunction: H/L access routine */
167
+ /* for the sym-cat function. */
168
+ /****************************************/
169
+ void SymCatFunction(
170
+ Environment *theEnv,
171
+ UDFContext *context,
172
+ UDFValue *returnValue)
173
+ {
174
+ StrOrSymCatFunction(context,returnValue,SYMBOL_TYPE);
175
+ }
176
+
177
+ /********************************************************/
178
+ /* StrOrSymCatFunction: Driver routine for implementing */
179
+ /* the str-cat and sym-cat functions. */
180
+ /********************************************************/
181
+ static void StrOrSymCatFunction(
182
+ UDFContext *context,
183
+ UDFValue *returnValue,
184
+ unsigned short returnType)
185
+ {
186
+ UDFValue theArg;
187
+ unsigned int numArgs;
188
+ unsigned int i;
189
+ size_t total;
190
+ size_t j;
191
+ char *theString;
192
+ CLIPSLexeme **arrayOfStrings;
193
+ CLIPSLexeme *hashPtr;
194
+ Environment *theEnv = context->environment;
195
+
196
+ /*===============================================*/
197
+ /* Determine the number of arguments as create a */
198
+ /* string array which is large enough to store */
199
+ /* the string representation of each argument. */
200
+ /*===============================================*/
201
+
202
+ numArgs = UDFArgumentCount(context);
203
+ if (numArgs == 0) return;
204
+
205
+ arrayOfStrings = (CLIPSLexeme **) gm1(theEnv,sizeof(CLIPSLexeme *) * numArgs);
206
+ for (i = 0; i < numArgs; i++)
207
+ { arrayOfStrings[i] = NULL; }
208
+
209
+ /*=============================================*/
210
+ /* Evaluate each argument and store its string */
211
+ /* representation in the string array. */
212
+ /*=============================================*/
213
+
214
+ total = 1;
215
+ for (i = 1 ; i <= numArgs ; i++)
216
+ {
217
+ UDFNthArgument(context,i,ANY_TYPE_BITS,&theArg);
218
+
219
+ switch(theArg.header->type)
220
+ {
221
+ case STRING_TYPE:
222
+ #if OBJECT_SYSTEM
223
+ case INSTANCE_NAME_TYPE:
224
+ #endif
225
+ case SYMBOL_TYPE:
226
+ hashPtr = theArg.lexemeValue;
227
+ arrayOfStrings[i-1] = hashPtr;
228
+ IncrementLexemeCount(hashPtr);
229
+ break;
230
+
231
+ case FLOAT_TYPE:
232
+ hashPtr = CreateString(theEnv,FloatToString(theEnv,theArg.floatValue->contents));
233
+ arrayOfStrings[i-1] = hashPtr;
234
+ IncrementLexemeCount(hashPtr);
235
+ break;
236
+
237
+ case INTEGER_TYPE:
238
+ hashPtr = CreateString(theEnv,LongIntegerToString(theEnv,theArg.integerValue->contents));
239
+ arrayOfStrings[i-1] = hashPtr;
240
+ IncrementLexemeCount(hashPtr);
241
+ break;
242
+
243
+ default:
244
+ UDFInvalidArgumentMessage(context,"string, instance name, symbol, float, or integer");
245
+ SetEvaluationError(theEnv,true);
246
+ break;
247
+ }
248
+
249
+ if (EvaluationData(theEnv)->EvaluationError)
250
+ {
251
+ for (i = 0; i < numArgs; i++)
252
+ {
253
+ if (arrayOfStrings[i] != NULL)
254
+ { ReleaseLexeme(theEnv,arrayOfStrings[i]); }
255
+ }
256
+
257
+ rm(theEnv,arrayOfStrings,sizeof(CLIPSLexeme *) * numArgs);
258
+
259
+ if (returnType == STRING_TYPE)
260
+ { returnValue->value = CreateString(theEnv,""); }
261
+ else
262
+ { returnValue->value = CreateSymbol(theEnv,"nil"); }
263
+ return;
264
+ }
265
+
266
+ total += strlen(arrayOfStrings[i - 1]->contents);
267
+ }
268
+
269
+ /*=========================================================*/
270
+ /* Allocate the memory to store the concatenated string or */
271
+ /* symbol, then copy the values in the string array to the */
272
+ /* memory just allocated. */
273
+ /*=========================================================*/
274
+
275
+ theString = (char *) gm2(theEnv,(sizeof(char) * total));
276
+
277
+ j = 0;
278
+ for (i = 0 ; i < numArgs ; i++)
279
+ {
280
+ gensprintf(&theString[j],"%s",arrayOfStrings[i]->contents);
281
+ j += strlen(arrayOfStrings[i]->contents);
282
+ }
283
+
284
+ /*=========================================*/
285
+ /* Return the concatenated value and clean */
286
+ /* up the temporary memory used. */
287
+ /*=========================================*/
288
+
289
+ if (returnType == STRING_TYPE)
290
+ { returnValue->value = CreateString(theEnv,theString); }
291
+ else
292
+ { returnValue->value = CreateSymbol(theEnv,theString); }
293
+ rm(theEnv,theString,sizeof(char) * total);
294
+
295
+ for (i = 0; i < numArgs; i++)
296
+ {
297
+ if (arrayOfStrings[i] != NULL)
298
+ { ReleaseLexeme(theEnv,arrayOfStrings[i]); }
299
+ }
300
+
301
+ rm(theEnv,arrayOfStrings,sizeof(CLIPSLexeme *) * numArgs);
302
+ }
303
+
304
+ /*******************************************/
305
+ /* StrLengthFunction: H/L access routine */
306
+ /* for the str-length function. */
307
+ /*******************************************/
308
+ void StrLengthFunction(
309
+ Environment *theEnv,
310
+ UDFContext *context,
311
+ UDFValue *returnValue)
312
+ {
313
+ UDFValue theArg;
314
+
315
+ /*==================================================================*/
316
+ /* The argument should be of type symbol, string, or instance name. */
317
+ /*==================================================================*/
318
+
319
+ if (! UDFFirstArgument(context,LEXEME_BITS | INSTANCE_NAME_BIT,&theArg))
320
+ { return; }
321
+
322
+ /*============================================*/
323
+ /* Return the length of the string or symbol. */
324
+ /*============================================*/
325
+
326
+ returnValue->integerValue = CreateInteger(theEnv,(long long) UTF8Length(theArg.lexemeValue->contents));
327
+ }
328
+
329
+ /****************************************/
330
+ /* UpcaseFunction: H/L access routine */
331
+ /* for the upcase function. */
332
+ /****************************************/
333
+ void UpcaseFunction(
334
+ Environment *theEnv,
335
+ UDFContext *context,
336
+ UDFValue *returnValue)
337
+ {
338
+ UDFValue theArg;
339
+ unsigned i;
340
+ size_t slen;
341
+ const char *osptr;
342
+ char *nsptr;
343
+
344
+ /*==================================================*/
345
+ /* The argument should be of type symbol or string. */
346
+ /*==================================================*/
347
+
348
+ if (! UDFFirstArgument(context,LEXEME_BITS | INSTANCE_NAME_BIT,&theArg))
349
+ { return; }
350
+
351
+ /*======================================================*/
352
+ /* Allocate temporary memory and then copy the original */
353
+ /* string or symbol to that memory, while uppercasing */
354
+ /* lower case alphabetic characters. */
355
+ /*======================================================*/
356
+
357
+ osptr = theArg.lexemeValue->contents;
358
+ slen = strlen(osptr) + 1;
359
+ nsptr = (char *) gm2(theEnv,slen);
360
+
361
+ for (i = 0 ; i < slen ; i++)
362
+ {
363
+ if (islower(osptr[i]))
364
+ { nsptr[i] = (char) toupper(osptr[i]); }
365
+ else
366
+ { nsptr[i] = osptr[i]; }
367
+ }
368
+
369
+ /*========================================*/
370
+ /* Return the uppercased string and clean */
371
+ /* up the temporary memory used. */
372
+ /*========================================*/
373
+
374
+ if (CVIsType(&theArg,SYMBOL_BIT))
375
+ { returnValue->value = CreateSymbol(theEnv,nsptr); }
376
+ else if (CVIsType(&theArg,INSTANCE_NAME_BIT))
377
+ { returnValue->value = CreateInstanceName(theEnv,nsptr); }
378
+ else
379
+ { returnValue->value = CreateString(theEnv,nsptr); }
380
+ rm(theEnv,nsptr,slen);
381
+ }
382
+
383
+ /*****************************************/
384
+ /* LowcaseFunction: H/L access routine */
385
+ /* for the lowcase function. */
386
+ /*****************************************/
387
+ void LowcaseFunction(
388
+ Environment *theEnv,
389
+ UDFContext *context,
390
+ UDFValue *returnValue)
391
+ {
392
+ UDFValue theArg;
393
+ unsigned i;
394
+ size_t slen;
395
+ const char *osptr;
396
+ char *nsptr;
397
+
398
+ /*==================================================*/
399
+ /* The argument should be of type symbol or string. */
400
+ /*==================================================*/
401
+
402
+ if (! UDFFirstArgument(context,LEXEME_BITS | INSTANCE_NAME_BIT,&theArg))
403
+ { return; }
404
+
405
+ /*======================================================*/
406
+ /* Allocate temporary memory and then copy the original */
407
+ /* string or symbol to that memory, while lowercasing */
408
+ /* upper case alphabetic characters. */
409
+ /*======================================================*/
410
+
411
+ osptr = theArg.lexemeValue->contents;
412
+ slen = strlen(osptr) + 1;
413
+ nsptr = (char *) gm2(theEnv,slen);
414
+
415
+ for (i = 0 ; i < slen ; i++)
416
+ {
417
+ if (isupper(osptr[i]))
418
+ { nsptr[i] = (char) tolower(osptr[i]); }
419
+ else
420
+ { nsptr[i] = osptr[i]; }
421
+ }
422
+
423
+ /*========================================*/
424
+ /* Return the lowercased string and clean */
425
+ /* up the temporary memory used. */
426
+ /*========================================*/
427
+
428
+ if (CVIsType(&theArg,SYMBOL_BIT))
429
+ { returnValue->value = CreateSymbol(theEnv,nsptr); }
430
+ else if (CVIsType(&theArg,INSTANCE_NAME_BIT))
431
+ { returnValue->value = CreateInstanceName(theEnv,nsptr); }
432
+ else
433
+ { returnValue->value = CreateString(theEnv,nsptr); }
434
+ rm(theEnv,nsptr,slen);
435
+ }
436
+
437
+ /********************************************/
438
+ /* StrCompareFunction: H/L access routine */
439
+ /* for the str-compare function. */
440
+ /********************************************/
441
+ void StrCompareFunction(
442
+ Environment *theEnv,
443
+ UDFContext *context,
444
+ UDFValue *returnValue)
445
+ {
446
+ UDFValue arg1, arg2, arg3;
447
+ int compareResult;
448
+
449
+ /*=============================================================*/
450
+ /* The first two arguments should be of type symbol or string. */
451
+ /*=============================================================*/
452
+
453
+ if (! UDFFirstArgument(context,LEXEME_BITS | INSTANCE_NAME_BIT,&arg1))
454
+ { return; }
455
+
456
+ if (! UDFNextArgument(context,LEXEME_BITS | INSTANCE_NAME_BIT,&arg2))
457
+ { return; }
458
+
459
+ /*===================================================*/
460
+ /* Compare the strings. Use the 3rd argument for the */
461
+ /* maximum length of comparison, if it is provided. */
462
+ /*===================================================*/
463
+
464
+ if (UDFHasNextArgument(context))
465
+ {
466
+ if (! UDFNextArgument(context,INTEGER_BIT,&arg3))
467
+ { return; }
468
+
469
+ compareResult = strncmp(arg1.lexemeValue->contents,arg2.lexemeValue->contents,
470
+ (STD_SIZE) arg3.integerValue->contents);
471
+ }
472
+ else
473
+ { compareResult = strcmp(arg1.lexemeValue->contents,arg2.lexemeValue->contents); }
474
+
475
+ /*========================================================*/
476
+ /* Return Values are as follows: */
477
+ /* -1 is returned if <string-1> is less than <string-2>. */
478
+ /* 1 is return if <string-1> is greater than <string-2>. */
479
+ /* 0 is returned if <string-1> is equal to <string-2>. */
480
+ /*========================================================*/
481
+
482
+ if (compareResult < 0)
483
+ { returnValue->integerValue = CreateInteger(theEnv,-1L); }
484
+ else if (compareResult > 0)
485
+ { returnValue->integerValue = CreateInteger(theEnv,1L); }
486
+ else
487
+ { returnValue->integerValue = CreateInteger(theEnv,0L); }
488
+ }
489
+
490
+ /*******************************************/
491
+ /* SubStringFunction: H/L access routine */
492
+ /* for the sub-string function. */
493
+ /*******************************************/
494
+ void SubStringFunction(
495
+ Environment *theEnv,
496
+ UDFContext *context,
497
+ UDFValue *returnValue)
498
+ {
499
+ UDFValue theArg;
500
+ const char *tempString;
501
+ char *returnString;
502
+ size_t start, end, i, j, length;
503
+
504
+ /*===================================*/
505
+ /* Check and retrieve the arguments. */
506
+ /*===================================*/
507
+
508
+ if (! UDFFirstArgument(context,INTEGER_BIT,&theArg))
509
+ { return; }
510
+
511
+ if (theArg.integerValue->contents < 1)
512
+ { start = 0; }
513
+ else
514
+ { start = (size_t) theArg.integerValue->contents - 1; }
515
+
516
+ if (! UDFNextArgument(context,INTEGER_BIT,&theArg))
517
+ { return; }
518
+
519
+ if (theArg.integerValue->contents < 1)
520
+ {
521
+ returnValue->lexemeValue = CreateString(theEnv,"");
522
+ return;
523
+ }
524
+ else
525
+ { end = (size_t) theArg.integerValue->contents - 1; }
526
+
527
+ if (! UDFNextArgument(context,LEXEME_BITS | INSTANCE_NAME_BIT,&theArg))
528
+ { return; }
529
+
530
+ tempString = theArg.lexemeValue->contents;
531
+
532
+ /*================================================*/
533
+ /* If parameters are out of range return an error */
534
+ /*================================================*/
535
+
536
+ length = UTF8Length(tempString);
537
+
538
+ if (end > length)
539
+ { end = length; }
540
+
541
+ /*==================================*/
542
+ /* If the start is greater than the */
543
+ /* end, return a null string. */
544
+ /*==================================*/
545
+
546
+ if ((start > end) || (length == 0))
547
+ {
548
+ returnValue->lexemeValue = CreateString(theEnv,"");
549
+ return;
550
+ }
551
+
552
+ /*=============================================*/
553
+ /* Otherwise, allocate the string and copy the */
554
+ /* designated portion of the old string to the */
555
+ /* new string. */
556
+ /*=============================================*/
557
+
558
+ else
559
+ {
560
+ start = UTF8Offset(tempString,start);
561
+ end = UTF8Offset(tempString,end + 1) - 1;
562
+
563
+ returnString = (char *) gm2(theEnv,(end - start + 2)); /* (end - start) inclusive + EOS */
564
+ for(j=0, i=start;i <= end; i++, j++)
565
+ { *(returnString+j) = *(tempString+i); }
566
+ *(returnString+j) = '\0';
567
+ }
568
+
569
+ /*========================*/
570
+ /* Return the new string. */
571
+ /*========================*/
572
+
573
+ returnValue->lexemeValue = CreateString(theEnv,returnString);
574
+ rm(theEnv,returnString,(end - start + 2));
575
+ }
576
+
577
+ /******************************************/
578
+ /* StrIndexFunction: H/L access routine */
579
+ /* for the sub-index function. */
580
+ /******************************************/
581
+ void StrIndexFunction(
582
+ Environment *theEnv,
583
+ UDFContext *context,
584
+ UDFValue *returnValue)
585
+ {
586
+ UDFValue theArg1, theArg2;
587
+ const char *strg1, *strg2, *strg3;
588
+ size_t i;
589
+
590
+ returnValue->lexemeValue = FalseSymbol(theEnv);
591
+
592
+ /*===================================*/
593
+ /* Check and retrieve the arguments. */
594
+ /*===================================*/
595
+
596
+ if (! UDFFirstArgument(context,LEXEME_BITS | INSTANCE_NAME_BIT,&theArg1))
597
+ { return; }
598
+
599
+ if (! UDFNextArgument(context,LEXEME_BITS | INSTANCE_NAME_BIT,&theArg2))
600
+ { return; }
601
+
602
+ strg1 = theArg1.lexemeValue->contents;
603
+ strg2 = theArg2.lexemeValue->contents;
604
+
605
+ /*=================================*/
606
+ /* Find the position in string2 of */
607
+ /* string1 (counting from 1). */
608
+ /*=================================*/
609
+
610
+ if (strlen(strg1) == 0)
611
+ {
612
+ returnValue->integerValue = CreateInteger(theEnv,1LL);
613
+ return;
614
+ }
615
+
616
+ strg3 = strstr(strg2,strg1);
617
+
618
+ if (strg3 != NULL)
619
+ {
620
+ i = (size_t) (strg3 - strg2) + 1;
621
+ returnValue->integerValue = CreateInteger(theEnv,(long long) UTF8CharNum(strg2,i));
622
+ }
623
+ }
624
+
625
+ /********************************************/
626
+ /* StringToFieldFunction: H/L access routine */
627
+ /* for the string-to-field function. */
628
+ /********************************************/
629
+ void StringToFieldFunction(
630
+ Environment *theEnv,
631
+ UDFContext *context,
632
+ UDFValue *returnValue)
633
+ {
634
+ UDFValue theArg;
635
+
636
+ ClearErrorValue(theEnv);
637
+
638
+ /*==================================================*/
639
+ /* The argument should be of type symbol or string. */
640
+ /*==================================================*/
641
+
642
+ if (! UDFFirstArgument(context,LEXEME_BITS | INSTANCE_NAME_BIT,&theArg))
643
+ {
644
+ SetErrorValue(theEnv,&CreateSymbol(theEnv,"INVALID_ARGUMENT")->header);
645
+ returnValue->lexemeValue = FalseSymbol(theEnv);
646
+ return;
647
+ }
648
+
649
+ /*================================*/
650
+ /* Convert the string to an atom. */
651
+ /*================================*/
652
+
653
+ StringToField(theEnv,theArg.lexemeValue->contents,returnValue);
654
+ }
655
+
656
+ /*************************************************************/
657
+ /* StringToField: Converts a string to an atomic data value. */
658
+ /*************************************************************/
659
+ void StringToField(
660
+ Environment *theEnv,
661
+ const char *theString,
662
+ UDFValue *returnValue)
663
+ {
664
+ struct token theToken;
665
+
666
+ /*====================================*/
667
+ /* Open the string as an input source */
668
+ /* and retrieve the first value. */
669
+ /*====================================*/
670
+
671
+ OpenStringSource(theEnv,"string-to-field-str",theString,0);
672
+ GetToken(theEnv,"string-to-field-str",&theToken);
673
+ CloseStringSource(theEnv,"string-to-field-str");
674
+
675
+ /*====================================================*/
676
+ /* Copy the token to the return value data structure. */
677
+ /*====================================================*/
678
+
679
+ if ((theToken.tknType == FLOAT_TOKEN) || (theToken.tknType == STRING_TOKEN) ||
680
+ #if OBJECT_SYSTEM
681
+ (theToken.tknType == INSTANCE_NAME_TOKEN) ||
682
+ #endif
683
+ (theToken.tknType == SYMBOL_TOKEN) || (theToken.tknType == INTEGER_TOKEN))
684
+ { returnValue->value = theToken.value; }
685
+ else if (theToken.tknType == STOP_TOKEN)
686
+ {
687
+ SetErrorValue(theEnv,&CreateSymbol(theEnv,"EOF")->header);
688
+ returnValue->value = CreateSymbol(theEnv,"EOF");
689
+ }
690
+ else if (theToken.tknType == UNKNOWN_VALUE_TOKEN)
691
+ {
692
+ SetErrorValue(theEnv,&CreateSymbol(theEnv,"INVALID_ARGUMENT")->header);
693
+ returnValue->lexemeValue = FalseSymbol(theEnv);
694
+ }
695
+ else
696
+ { returnValue->value = CreateSymbol(theEnv,theToken.printForm); }
697
+ }
698
+
699
+ /******************************************/
700
+ /* StrReplaceFunction: H/L access routine */
701
+ /* for the str-replace function. */
702
+ /******************************************/
703
+ void StrReplaceFunction(
704
+ Environment *theEnv,
705
+ UDFContext *context,
706
+ UDFValue *returnValue)
707
+ {
708
+ UDFValue initial, find, replace;
709
+ size_t findLength, replaceLength;
710
+ size_t returnLength;
711
+ const char *traverse, *found;
712
+ const char *initialString, *findString, *replaceString;
713
+ char *returnString, *target;
714
+
715
+ /*========================================*/
716
+ /* The first three arguments should be of */
717
+ /* type symbol, string, or instance name. */
718
+ /*========================================*/
719
+
720
+ if (! UDFFirstArgument(context,LEXEME_BITS | INSTANCE_NAME_BIT,&initial))
721
+ { return; }
722
+
723
+ if (! UDFNextArgument(context,LEXEME_BITS | INSTANCE_NAME_BIT,&find))
724
+ { return; }
725
+
726
+ if (! UDFNextArgument(context,LEXEME_BITS | INSTANCE_NAME_BIT,&replace))
727
+ { return; }
728
+
729
+ initialString = initial.lexemeValue->contents;
730
+ findString = find.lexemeValue->contents;
731
+ replaceString = replace.lexemeValue->contents;
732
+
733
+ /*===================================================*/
734
+ /* If the find string is empty, return the original. */
735
+ /*===================================================*/
736
+
737
+ findLength = strlen(findString);
738
+ if (findLength == 0)
739
+ {
740
+ returnValue->lexemeValue = initial.lexemeValue;
741
+ return;
742
+ }
743
+
744
+ /*====================================*/
745
+ /* Determine the number of characters */
746
+ /* needed for the return value. */
747
+ /*====================================*/
748
+
749
+ replaceLength = strlen(replaceString);
750
+ returnLength = strlen(initialString) + 1;
751
+ if (findLength != replaceLength)
752
+ {
753
+ traverse = initialString;
754
+ while ((traverse = strstr(traverse,findString)) != NULL)
755
+ {
756
+ traverse += findLength;
757
+ returnLength += (replaceLength - findLength);
758
+ }
759
+ }
760
+
761
+ returnString = (char *) gm2(theEnv,(sizeof(char) * returnLength));
762
+
763
+ /*================================*/
764
+ /* Copy values to the new string. */
765
+ /*================================*/
766
+
767
+ traverse = initialString;
768
+ target = returnString;
769
+ while ((found = strstr(traverse,findString)) != NULL)
770
+ {
771
+ strncpy(target,traverse,found - traverse);
772
+ target += (found - traverse);
773
+ strcpy(target,replaceString);
774
+ target += replaceLength;
775
+ traverse = found + findLength;
776
+ }
777
+ strcpy(target,traverse);
778
+
779
+ /*==========================*/
780
+ /* Create the return value. */
781
+ /*==========================*/
782
+
783
+ if (initial.header->type == STRING_TYPE)
784
+ { returnValue->value = CreateString(theEnv,returnString); }
785
+ else if (initial.header->type == SYMBOL_TYPE)
786
+ { returnValue->value = CreateSymbol(theEnv,returnString); }
787
+ else
788
+ { returnValue->value = CreateInstanceName(theEnv,returnString); }
789
+
790
+ rm(theEnv,returnString,sizeof(char) * returnLength);
791
+ }
792
+
793
+ /**************************************/
794
+ /* EvalFunction: H/L access routine */
795
+ /* for the eval function. */
796
+ /**************************************/
797
+ void EvalFunction(
798
+ Environment *theEnv,
799
+ UDFContext *context,
800
+ UDFValue *returnValue)
801
+ {
802
+ UDFValue theArg;
803
+ CLIPSValue cv;
804
+
805
+ /*==================================================*/
806
+ /* The argument should be of type SYMBOL or STRING. */
807
+ /*==================================================*/
808
+
809
+ if (! UDFFirstArgument(context,LEXEME_BITS,&theArg))
810
+ { return; }
811
+
812
+ /*======================*/
813
+ /* Evaluate the string. */
814
+ /*======================*/
815
+
816
+ Eval(theEnv,theArg.lexemeValue->contents,&cv);
817
+ CLIPSToUDFValue(&cv,returnValue);
818
+ }
819
+
820
+ /****************************/
821
+ /* Eval: C access routine */
822
+ /* for the eval function. */
823
+ /****************************/
824
+ EvalError Eval(
825
+ Environment *theEnv,
826
+ const char *theString,
827
+ CLIPSValue *returnValue)
828
+ {
829
+ struct expr *top;
830
+ bool ov;
831
+ static int depth = 0;
832
+ char logicalNameBuffer[20];
833
+ struct BindInfo *oldBinds;
834
+ int danglingConstructs;
835
+ UDFValue evalResult;
836
+ GCBlock gcb;
837
+ struct token theToken;
838
+
839
+ /*========================================*/
840
+ /* Set up the frame for tracking garbage. */
841
+ /*========================================*/
842
+
843
+ GCBlockStart(theEnv,&gcb);
844
+
845
+ /*=====================================*/
846
+ /* If embedded, clear the error flags. */
847
+ /*=====================================*/
848
+
849
+ if (EvaluationData(theEnv)->CurrentExpression == NULL)
850
+ { ResetErrorFlags(theEnv); }
851
+
852
+ /*======================================================*/
853
+ /* Evaluate the string. Create a different logical name */
854
+ /* for use each time the eval function is called. */
855
+ /*======================================================*/
856
+
857
+ depth++;
858
+ gensnprintf(logicalNameBuffer,sizeof(logicalNameBuffer),"Eval-%d",depth);
859
+ if (OpenStringSource(theEnv,logicalNameBuffer,theString,0) == 0)
860
+ {
861
+ SystemError(theEnv,"STRNGFUN",1);
862
+ ExitRouter(theEnv,EXIT_FAILURE);
863
+ }
864
+
865
+ /*================================================*/
866
+ /* Save the current parsing state before routines */
867
+ /* are called to parse the eval string. */
868
+ /*================================================*/
869
+
870
+ ov = GetPPBufferStatus(theEnv);
871
+ SetPPBufferStatus(theEnv,false);
872
+ oldBinds = GetParsedBindNames(theEnv);
873
+ SetParsedBindNames(theEnv,NULL);
874
+ danglingConstructs = ConstructData(theEnv)->DanglingConstructs;
875
+
876
+ /*========================================================*/
877
+ /* Parse the string argument passed to the eval function. */
878
+ /*========================================================*/
879
+
880
+ top = ParseAtomOrExpression(theEnv,logicalNameBuffer,NULL);
881
+
882
+ /*============================*/
883
+ /* Restore the parsing state. */
884
+ /*============================*/
885
+
886
+ SetPPBufferStatus(theEnv,ov);
887
+ ClearParsedBindNames(theEnv);
888
+ SetParsedBindNames(theEnv,oldBinds);
889
+
890
+ /*===========================================*/
891
+ /* Return if an error occured while parsing. */
892
+ /*===========================================*/
893
+
894
+ if (top == NULL)
895
+ {
896
+ SetEvaluationError(theEnv,true);
897
+ CloseStringSource(theEnv,logicalNameBuffer);
898
+ GCBlockEnd(theEnv,&gcb);
899
+ if (returnValue != NULL)
900
+ { returnValue->lexemeValue = FalseSymbol(theEnv); }
901
+ depth--;
902
+ ConstructData(theEnv)->DanglingConstructs = danglingConstructs;
903
+ return EE_PARSING_ERROR;
904
+ }
905
+
906
+ /*======================================*/
907
+ /* Return if there is extraneous input. */
908
+ /*======================================*/
909
+
910
+ GetToken(theEnv,logicalNameBuffer,&theToken);
911
+ if (theToken.tknType != STOP_TOKEN)
912
+ {
913
+ PrintErrorID(theEnv,"STRNGFUN",2,false);
914
+ WriteString(theEnv,STDERR,"Function 'eval' encountered extraneous input.\n");
915
+ SetEvaluationError(theEnv,true);
916
+ ReturnExpression(theEnv,top);
917
+ CloseStringSource(theEnv,logicalNameBuffer);
918
+ GCBlockEnd(theEnv,&gcb);
919
+ if (returnValue != NULL)
920
+ { returnValue->lexemeValue = FalseSymbol(theEnv); }
921
+ depth--;
922
+ ConstructData(theEnv)->DanglingConstructs = danglingConstructs;
923
+ return EE_PARSING_ERROR;
924
+ }
925
+
926
+ /*====================================*/
927
+ /* Evaluate the expression and return */
928
+ /* the memory used to parse it. */
929
+ /*====================================*/
930
+
931
+ ExpressionInstall(theEnv,top);
932
+ EvaluateExpression(theEnv,top,&evalResult);
933
+ ExpressionDeinstall(theEnv,top);
934
+
935
+ depth--;
936
+ ReturnExpression(theEnv,top);
937
+ CloseStringSource(theEnv,logicalNameBuffer);
938
+
939
+ /*====================================================*/
940
+ /* Convert a partial multifield to a full multifield. */
941
+ /*====================================================*/
942
+
943
+ NormalizeMultifield(theEnv,&evalResult);
944
+
945
+ /*==============================================*/
946
+ /* If embedded, reset dangling construct count. */
947
+ /*==============================================*/
948
+
949
+ if (EvaluationData(theEnv)->CurrentExpression == NULL)
950
+ { ConstructData(theEnv)->DanglingConstructs = danglingConstructs; }
951
+
952
+ /*================================*/
953
+ /* Restore the old garbage frame. */
954
+ /*================================*/
955
+
956
+ if (returnValue != NULL)
957
+ { GCBlockEndUDF(theEnv,&gcb,&evalResult); }
958
+ else
959
+ { GCBlockEnd(theEnv,&gcb); }
960
+
961
+ /*==========================================*/
962
+ /* Perform periodic cleanup if the eval was */
963
+ /* issued from an embedded controller. */
964
+ /*==========================================*/
965
+
966
+ if (EvaluationData(theEnv)->CurrentExpression == NULL)
967
+ {
968
+ if (returnValue != NULL)
969
+ { CleanCurrentGarbageFrame(theEnv,&evalResult); }
970
+ else
971
+ { CleanCurrentGarbageFrame(theEnv,NULL); }
972
+ CallPeriodicTasks(theEnv);
973
+ }
974
+
975
+ if (returnValue != NULL)
976
+ { returnValue->value = evalResult.value; }
977
+
978
+ if (GetEvaluationError(theEnv)) return EE_PROCESSING_ERROR;
979
+
980
+ return EE_NO_ERROR;
981
+ }
982
+
983
+ #if (! RUN_TIME) && (! BLOAD_ONLY)
984
+ /***************************************/
985
+ /* BuildFunction: H/L access routine */
986
+ /* for the build function. */
987
+ /***************************************/
988
+ void BuildFunction(
989
+ Environment *theEnv,
990
+ UDFContext *context,
991
+ UDFValue *returnValue)
992
+ {
993
+ UDFValue theArg;
994
+ BuildError rv;
995
+
996
+ /*==================================================*/
997
+ /* The argument should be of type SYMBOL or STRING. */
998
+ /*==================================================*/
999
+
1000
+ if (! UDFFirstArgument(context,LEXEME_BITS,&theArg))
1001
+ { return; }
1002
+
1003
+ /*======================*/
1004
+ /* Build the construct. */
1005
+ /*======================*/
1006
+
1007
+ rv = Build(theEnv,theArg.lexemeValue->contents);
1008
+ returnValue->lexemeValue = CreateBoolean(theEnv,(rv == BE_NO_ERROR));
1009
+ }
1010
+
1011
+ /*****************************/
1012
+ /* Build: C access routine */
1013
+ /* for the build function. */
1014
+ /*****************************/
1015
+ BuildError Build(
1016
+ Environment *theEnv,
1017
+ const char *theString)
1018
+ {
1019
+ const char *constructType;
1020
+ struct token theToken;
1021
+ BuildError errorFlag;
1022
+ GCBlock gcb;
1023
+
1024
+ /*=====================================*/
1025
+ /* If embedded, clear the error flags. */
1026
+ /*=====================================*/
1027
+
1028
+ if (EvaluationData(theEnv)->CurrentExpression == NULL)
1029
+ { ResetErrorFlags(theEnv); }
1030
+
1031
+ /*====================================================*/
1032
+ /* No additions during defrule join network activity. */
1033
+ /*====================================================*/
1034
+
1035
+ #if DEFRULE_CONSTRUCT
1036
+ if (EngineData(theEnv)->JoinOperationInProgress) return BE_COULD_NOT_BUILD_ERROR;
1037
+ #endif
1038
+
1039
+ /*===========================================*/
1040
+ /* Create a string source router so that the */
1041
+ /* string can be used as an input source. */
1042
+ /*===========================================*/
1043
+
1044
+ if (OpenStringSource(theEnv,"build",theString,0) == 0)
1045
+ { return BE_COULD_NOT_BUILD_ERROR; }
1046
+
1047
+ /*===================================*/
1048
+ /* Start a garbage collection block. */
1049
+ /*===================================*/
1050
+
1051
+ GCBlockStart(theEnv,&gcb);
1052
+
1053
+ /*================================*/
1054
+ /* The first token of a construct */
1055
+ /* must be a left parenthesis. */
1056
+ /*================================*/
1057
+
1058
+ GetToken(theEnv,"build",&theToken);
1059
+
1060
+ if (theToken.tknType != LEFT_PARENTHESIS_TOKEN)
1061
+ {
1062
+ CloseStringSource(theEnv,"build");
1063
+ GCBlockEnd(theEnv,&gcb);
1064
+ return BE_PARSING_ERROR;
1065
+ }
1066
+
1067
+ /*==============================================*/
1068
+ /* The next token should be the construct type. */
1069
+ /*==============================================*/
1070
+
1071
+ GetToken(theEnv,"build",&theToken);
1072
+ if (theToken.tknType != SYMBOL_TOKEN)
1073
+ {
1074
+ CloseStringSource(theEnv,"build");
1075
+ GCBlockEnd(theEnv,&gcb);
1076
+ return BE_PARSING_ERROR;
1077
+ }
1078
+
1079
+ constructType = theToken.lexemeValue->contents;
1080
+
1081
+ /*======================*/
1082
+ /* Parse the construct. */
1083
+ /*======================*/
1084
+
1085
+ errorFlag = ParseConstruct(theEnv,constructType,"build");
1086
+
1087
+ /*=============================*/
1088
+ /* Grab any extraneous token. */
1089
+ /*============================*/
1090
+
1091
+ GetToken(theEnv,"build",&theToken);
1092
+
1093
+ /*=================================*/
1094
+ /* Close the string source router. */
1095
+ /*=================================*/
1096
+
1097
+ CloseStringSource(theEnv,"build");
1098
+
1099
+ /*=========================================*/
1100
+ /* If an error occured while parsing the */
1101
+ /* construct, then print an error message. */
1102
+ /*=========================================*/
1103
+
1104
+ if (errorFlag == BE_PARSING_ERROR)
1105
+ {
1106
+ WriteString(theEnv,STDERR,"\nERROR:\n");
1107
+ WriteString(theEnv,STDERR,GetPPBuffer(theEnv));
1108
+ WriteString(theEnv,STDERR,"\n");
1109
+ }
1110
+
1111
+ DestroyPPBuffer(theEnv);
1112
+
1113
+ /*===================================*/
1114
+ /* End the garbage collection block. */
1115
+ /*===================================*/
1116
+
1117
+ GCBlockEnd(theEnv,&gcb);
1118
+
1119
+ /*===============================================*/
1120
+ /* If embedded, clean the topmost garbage frame. */
1121
+ /*===============================================*/
1122
+
1123
+ if (EvaluationData(theEnv)->CurrentExpression == NULL)
1124
+ { CleanCurrentGarbageFrame(theEnv,NULL); }
1125
+
1126
+ /*===================================*/
1127
+ /* Throw error for extraneous input. */
1128
+ /*===================================*/
1129
+
1130
+ if ((errorFlag == BE_NO_ERROR) && (theToken.tknType != STOP_TOKEN))
1131
+ {
1132
+ PrintErrorID(theEnv,"STRNGFUN",2,false);
1133
+ WriteString(theEnv,STDERR,"Function 'build' encountered extraneous input.\n");
1134
+ SetEvaluationError(theEnv,true);
1135
+ errorFlag = BE_PARSING_ERROR;
1136
+ }
1137
+
1138
+ /*===================================================*/
1139
+ /* Return the error code from parsing the construct. */
1140
+ /*===================================================*/
1141
+
1142
+ return errorFlag;
1143
+ }
1144
+ #else
1145
+ /**************************************************/
1146
+ /* BuildFunction: This is the non-functional stub */
1147
+ /* provided for use with a run-time version. */
1148
+ /**************************************************/
1149
+ void BuildFunction(
1150
+ Environment *theEnv,
1151
+ UDFContext *context,
1152
+ UDFValue *returnValue)
1153
+ {
1154
+ PrintErrorID(theEnv,"STRNGFUN",1,false);
1155
+ WriteString(theEnv,STDERR,"Function 'build' does not work in run time modules.\n");
1156
+ returnValue->lexemeValue = FalseSymbol(theEnv);
1157
+ }
1158
+
1159
+ /***************************************************/
1160
+ /* Build: This is the non-functional stub provided */
1161
+ /* for use with a run-time version. */
1162
+ /***************************************************/
1163
+ BuildError Build(
1164
+ Environment *theEnv,
1165
+ const char *theString)
1166
+ {
1167
+ PrintErrorID(theEnv,"STRNGFUN",1,false);
1168
+ WriteString(theEnv,STDERR,"Function 'build' does not work in run time modules.\n");
1169
+ return BE_COULD_NOT_BUILD_ERROR;
1170
+ }
1171
+ #endif /* (! RUN_TIME) && (! BLOAD_ONLY) */
1172
+
1173
+ #endif /* STRING_FUNCTIONS */