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,2045 @@
1
+ /*******************************************************/
2
+ /* "C" Language Integrated Production System */
3
+ /* */
4
+ /* CLIPS Version 6.40 07/05/18 */
5
+ /* */
6
+ /* I/O FUNCTIONS MODULE */
7
+ /*******************************************************/
8
+
9
+ /*************************************************************/
10
+ /* Purpose: Contains the code for several I/O functions */
11
+ /* including printout, read, open, close, remove, rename, */
12
+ /* format, and readline. */
13
+ /* */
14
+ /* Principal Programmer(s): */
15
+ /* Brian L. Dantes */
16
+ /* Gary D. Riley */
17
+ /* Bebe Ly */
18
+ /* */
19
+ /* Contributing Programmer(s): */
20
+ /* */
21
+ /* Revision History: */
22
+ /* */
23
+ /* 6.24: Added the get-char, set-locale, and */
24
+ /* read-number functions. */
25
+ /* */
26
+ /* Modified printing of floats in the format */
27
+ /* function to use the locale from the set-locale */
28
+ /* function. */
29
+ /* */
30
+ /* Moved IllegalLogicalNameMessage function to */
31
+ /* argacces.c. */
32
+ /* */
33
+ /* 6.30: Changed integer type/precision. */
34
+ /* */
35
+ /* Support for long long integers. */
36
+ /* */
37
+ /* Removed the undocumented use of t in the */
38
+ /* printout command to perform the same function */
39
+ /* as crlf. */
40
+ /* */
41
+ /* Replaced EXT_IO and BASIC_IO compiler flags */
42
+ /* with IO_FUNCTIONS compiler flag. */
43
+ /* */
44
+ /* Added rb and ab and removed r+ modes for the */
45
+ /* open function. */
46
+ /* */
47
+ /* Removed conditional code for unsupported */
48
+ /* compilers/operating systems (IBM_MCW and */
49
+ /* MAC_MCW). */
50
+ /* */
51
+ /* Used gensprintf instead of sprintf. */
52
+ /* */
53
+ /* Added put-char function. */
54
+ /* */
55
+ /* Added SetFullCRLF which allows option to */
56
+ /* specify crlf as \n or \r\n. */
57
+ /* */
58
+ /* Added AwaitingInput flag. */
59
+ /* */
60
+ /* Added const qualifiers to remove C++ */
61
+ /* deprecation warnings. */
62
+ /* */
63
+ /* Added STDOUT and STDIN logical name */
64
+ /* definitions. */
65
+ /* */
66
+ /* 6.40: Modified ReadTokenFromStdin to capture */
67
+ /* carriage returns in the input buffer so that */
68
+ /* input buffer count will accurately reflect */
69
+ /* the number of characters typed for GUI */
70
+ /* interfaces that support deleting carriage */
71
+ /* returns. */
72
+ /* */
73
+ /* Added Env prefix to GetEvaluationError and */
74
+ /* SetEvaluationError functions. */
75
+ /* */
76
+ /* Added Env prefix to GetHaltExecution and */
77
+ /* SetHaltExecution functions. */
78
+ /* */
79
+ /* Pragma once and other inclusion changes. */
80
+ /* */
81
+ /* Added support for booleans with <stdbool.h>. */
82
+ /* */
83
+ /* Removed use of void pointers for specific */
84
+ /* data structures. */
85
+ /* */
86
+ /* UDF redesign. */
87
+ /* */
88
+ /* Added print and println functions. */
89
+ /* */
90
+ /* Read function now returns symbols for tokens */
91
+ /* that are not primitive values. */
92
+ /* */
93
+ /* Added unget-char function. */
94
+ /* */
95
+ /* Added r+, w+, a+, rb+, wb+, and ab+ file */
96
+ /* access modes for the open function. */
97
+ /* */
98
+ /* Added flush, rewind, tell, seek, and chdir */
99
+ /* functions. */
100
+ /* */
101
+ /* Changed error return value of read, readline, */
102
+ /* and read-number functions to FALSE and added */
103
+ /* an error code for read. */
104
+ /* */
105
+ /*************************************************************/
106
+
107
+ #include "setup.h"
108
+
109
+ #if IO_FUNCTIONS
110
+ #include <locale.h>
111
+ #include <stdlib.h>
112
+ #include <ctype.h>
113
+ #endif
114
+
115
+ #include <stdio.h>
116
+ #include <string.h>
117
+
118
+ #include "argacces.h"
119
+ #include "commline.h"
120
+ #include "constant.h"
121
+ #include "envrnmnt.h"
122
+ #include "extnfunc.h"
123
+ #include "filertr.h"
124
+ #include "memalloc.h"
125
+ #include "miscfun.h"
126
+ #include "prntutil.h"
127
+ #include "router.h"
128
+ #include "scanner.h"
129
+ #include "strngrtr.h"
130
+ #include "sysdep.h"
131
+ #include "utility.h"
132
+
133
+ #include "iofun.h"
134
+
135
+ /***************/
136
+ /* DEFINITIONS */
137
+ /***************/
138
+
139
+ #define FORMAT_MAX 512
140
+ #define FLAG_MAX 80
141
+
142
+ /********************/
143
+ /* ENVIRONMENT DATA */
144
+ /********************/
145
+
146
+ #define IO_FUNCTION_DATA 64
147
+
148
+ struct IOFunctionData
149
+ {
150
+ CLIPSLexeme *locale;
151
+ bool useFullCRLF;
152
+ };
153
+
154
+ #define IOFunctionData(theEnv) ((struct IOFunctionData *) GetEnvironmentData(theEnv,IO_FUNCTION_DATA))
155
+
156
+ /****************************************/
157
+ /* LOCAL INTERNAL FUNCTION DEFINITIONS */
158
+ /****************************************/
159
+
160
+ #if IO_FUNCTIONS
161
+ static void ReadTokenFromStdin(Environment *,struct token *);
162
+ static const char *ControlStringCheck(UDFContext *,unsigned int);
163
+ static char FindFormatFlag(const char *,size_t *,char *,size_t);
164
+ static const char *PrintFormatFlag(UDFContext *,const char *,unsigned int,int);
165
+ static char *FillBuffer(Environment *,const char *,size_t *,size_t *);
166
+ static void ReadNumber(Environment *,const char *,struct token *,bool);
167
+ static void PrintDriver(UDFContext *,const char *,bool);
168
+ #endif
169
+
170
+ /**************************************/
171
+ /* IOFunctionDefinitions: Initializes */
172
+ /* the I/O functions. */
173
+ /**************************************/
174
+ void IOFunctionDefinitions(
175
+ Environment *theEnv)
176
+ {
177
+ AllocateEnvironmentData(theEnv,IO_FUNCTION_DATA,sizeof(struct IOFunctionData),NULL);
178
+
179
+ #if IO_FUNCTIONS
180
+ IOFunctionData(theEnv)->useFullCRLF = false;
181
+ IOFunctionData(theEnv)->locale = CreateSymbol(theEnv,setlocale(LC_ALL,NULL));
182
+ IncrementLexemeCount(IOFunctionData(theEnv)->locale);
183
+ #endif
184
+
185
+ #if ! RUN_TIME
186
+ #if IO_FUNCTIONS
187
+ AddUDF(theEnv,"printout","v",1,UNBOUNDED,"*;ldsyn",PrintoutFunction,"PrintoutFunction",NULL);
188
+ AddUDF(theEnv,"print","v",0,UNBOUNDED,NULL,PrintFunction,"PrintFunction",NULL);
189
+ AddUDF(theEnv,"println","v",0,UNBOUNDED,NULL,PrintlnFunction,"PrintlnFunction",NULL);
190
+ AddUDF(theEnv,"read","synldfie",0,1,";ldsyn",ReadFunction,"ReadFunction",NULL);
191
+ AddUDF(theEnv,"open","b",2,3,"*;sy;ldsyn;s",OpenFunction,"OpenFunction",NULL);
192
+ AddUDF(theEnv,"close","b",0,1,"ldsyn",CloseFunction,"CloseFunction",NULL);
193
+ AddUDF(theEnv,"flush","b",0,1,"ldsyn",FlushFunction,"FlushFunction",NULL);
194
+ AddUDF(theEnv,"rewind","b",1,1,";ldsyn",RewindFunction,"RewindFunction",NULL);
195
+ AddUDF(theEnv,"tell","lb",1,1,";ldsyn",TellFunction,"TellFunction",NULL);
196
+ AddUDF(theEnv,"seek","b",3,3,";ldsyn;l;y",SeekFunction,"SeekFunction",NULL);
197
+ AddUDF(theEnv,"get-char","l",0,1,";ldsyn",GetCharFunction,"GetCharFunction",NULL);
198
+ AddUDF(theEnv,"unget-char","l",1,2,";ldsyn;l",UngetCharFunction,"UngetCharFunction",NULL);
199
+ AddUDF(theEnv,"put-char","v",1,2,";ldsyn;l",PutCharFunction,"PutCharFunction",NULL);
200
+ AddUDF(theEnv,"remove","b",1,1,"sy",RemoveFunction,"RemoveFunction",NULL);
201
+ AddUDF(theEnv,"rename","b",2,2,"sy",RenameFunction,"RenameFunction",NULL);
202
+ AddUDF(theEnv,"format","s",2,UNBOUNDED,"*;ldsyn;s",FormatFunction,"FormatFunction",NULL);
203
+ AddUDF(theEnv,"readline","sy",0,1,";ldsyn",ReadlineFunction,"ReadlineFunction",NULL);
204
+ AddUDF(theEnv,"set-locale","sy",0,1,";s",SetLocaleFunction,"SetLocaleFunction",NULL);
205
+ AddUDF(theEnv,"read-number","syld",0,1,";ldsyn",ReadNumberFunction,"ReadNumberFunction",NULL);
206
+ AddUDF(theEnv,"chdir","b",0,1,"sy",ChdirFunction,"ChdirFunction",NULL);
207
+ #endif
208
+ #else
209
+ #if MAC_XCD
210
+ #pragma unused(theEnv)
211
+ #endif
212
+ #endif
213
+ }
214
+
215
+ #if IO_FUNCTIONS
216
+
217
+ /******************************************/
218
+ /* PrintoutFunction: H/L access routine */
219
+ /* for the printout function. */
220
+ /******************************************/
221
+ void PrintoutFunction(
222
+ Environment *theEnv,
223
+ UDFContext *context,
224
+ UDFValue *returnValue)
225
+ {
226
+ const char *logicalName;
227
+
228
+ /*=====================================================*/
229
+ /* Get the logical name to which output is to be sent. */
230
+ /*=====================================================*/
231
+
232
+ logicalName = GetLogicalName(context,STDOUT);
233
+ if (logicalName == NULL)
234
+ {
235
+ IllegalLogicalNameMessage(theEnv,"printout");
236
+ SetHaltExecution(theEnv,true);
237
+ SetEvaluationError(theEnv,true);
238
+ return;
239
+ }
240
+
241
+ /*============================================================*/
242
+ /* Determine if any router recognizes the output destination. */
243
+ /*============================================================*/
244
+
245
+ if (strcmp(logicalName,"nil") == 0)
246
+ { return; }
247
+ else if (QueryRouters(theEnv,logicalName) == false)
248
+ {
249
+ UnrecognizedRouterMessage(theEnv,logicalName);
250
+ return;
251
+ }
252
+
253
+ /*========================*/
254
+ /* Call the print driver. */
255
+ /*========================*/
256
+
257
+ PrintDriver(context,logicalName,false);
258
+ }
259
+
260
+ /*************************************/
261
+ /* PrintFunction: H/L access routine */
262
+ /* for the print function. */
263
+ /*************************************/
264
+ void PrintFunction(
265
+ Environment *theEnv,
266
+ UDFContext *context,
267
+ UDFValue *returnValue)
268
+ {
269
+ PrintDriver(context,STDOUT,false);
270
+ }
271
+
272
+ /*************************************/
273
+ /* PrintlnFunction: H/L access routine */
274
+ /* for the println function. */
275
+ /*************************************/
276
+ void PrintlnFunction(
277
+ Environment *theEnv,
278
+ UDFContext *context,
279
+ UDFValue *returnValue)
280
+ {
281
+ PrintDriver(context,STDOUT,true);
282
+ }
283
+
284
+ /*************************************************/
285
+ /* PrintDriver: Driver routine for the printout, */
286
+ /* print, and println functions. */
287
+ /*************************************************/
288
+ static void PrintDriver(
289
+ UDFContext *context,
290
+ const char *logicalName,
291
+ bool endCRLF)
292
+ {
293
+ UDFValue theArg;
294
+ Environment *theEnv = context->environment;
295
+
296
+ /*==============================*/
297
+ /* Print each of the arguments. */
298
+ /*==============================*/
299
+
300
+ while (UDFHasNextArgument(context))
301
+ {
302
+ if (! UDFNextArgument(context,ANY_TYPE_BITS,&theArg))
303
+ { break; }
304
+
305
+ if (EvaluationData(theEnv)->HaltExecution) break;
306
+
307
+ switch(theArg.header->type)
308
+ {
309
+ case SYMBOL_TYPE:
310
+ if (strcmp(theArg.lexemeValue->contents,"crlf") == 0)
311
+ {
312
+ if (IOFunctionData(theEnv)->useFullCRLF)
313
+ { WriteString(theEnv,logicalName,"\r\n"); }
314
+ else
315
+ { WriteString(theEnv,logicalName,"\n"); }
316
+ }
317
+ else if (strcmp(theArg.lexemeValue->contents,"tab") == 0)
318
+ { WriteString(theEnv,logicalName,"\t"); }
319
+ else if (strcmp(theArg.lexemeValue->contents,"vtab") == 0)
320
+ { WriteString(theEnv,logicalName,"\v"); }
321
+ else if (strcmp(theArg.lexemeValue->contents,"ff") == 0)
322
+ { WriteString(theEnv,logicalName,"\f"); }
323
+ else
324
+ { WriteString(theEnv,logicalName,theArg.lexemeValue->contents); }
325
+ break;
326
+
327
+ case STRING_TYPE:
328
+ WriteString(theEnv,logicalName,theArg.lexemeValue->contents);
329
+ break;
330
+
331
+ default:
332
+ WriteUDFValue(theEnv,logicalName,&theArg);
333
+ break;
334
+ }
335
+ }
336
+
337
+ if (endCRLF)
338
+ {
339
+ if (IOFunctionData(theEnv)->useFullCRLF)
340
+ { WriteString(theEnv,logicalName,"\r\n"); }
341
+ else
342
+ { WriteString(theEnv,logicalName,"\n"); }
343
+ }
344
+ }
345
+
346
+ /*****************************************************/
347
+ /* SetFullCRLF: Set the flag which indicates whether */
348
+ /* crlf is treated just as '\n' or '\r\n'. */
349
+ /*****************************************************/
350
+ bool SetFullCRLF(
351
+ Environment *theEnv,
352
+ bool value)
353
+ {
354
+ bool oldValue = IOFunctionData(theEnv)->useFullCRLF;
355
+
356
+ IOFunctionData(theEnv)->useFullCRLF = value;
357
+
358
+ return(oldValue);
359
+ }
360
+
361
+ /*************************************************************/
362
+ /* ReadFunction: H/L access routine for the read function. */
363
+ /*************************************************************/
364
+ void ReadFunction(
365
+ Environment *theEnv,
366
+ UDFContext *context,
367
+ UDFValue *returnValue)
368
+ {
369
+ struct token theToken;
370
+ const char *logicalName = NULL;
371
+
372
+ ClearErrorValue(theEnv);
373
+
374
+ /*======================================================*/
375
+ /* Determine the logical name from which input is read. */
376
+ /*======================================================*/
377
+
378
+ if (! UDFHasNextArgument(context))
379
+ { logicalName = STDIN; }
380
+ else
381
+ {
382
+ logicalName = GetLogicalName(context,STDIN);
383
+ if (logicalName == NULL)
384
+ {
385
+ IllegalLogicalNameMessage(theEnv,"read");
386
+ SetHaltExecution(theEnv,true);
387
+ SetEvaluationError(theEnv,true);
388
+ SetErrorValue(theEnv,&CreateSymbol(theEnv,"LOGICAL_NAME_ERROR")->header);
389
+ returnValue->lexemeValue = FalseSymbol(theEnv);
390
+ return;
391
+ }
392
+ }
393
+
394
+ /*============================================*/
395
+ /* Check to see that the logical name exists. */
396
+ /*============================================*/
397
+
398
+ if (QueryRouters(theEnv,logicalName) == false)
399
+ {
400
+ UnrecognizedRouterMessage(theEnv,logicalName);
401
+ SetHaltExecution(theEnv,true);
402
+ SetEvaluationError(theEnv,true);
403
+ SetErrorValue(theEnv,&CreateSymbol(theEnv,"LOGICAL_NAME_ERROR")->header);
404
+ returnValue->lexemeValue = FalseSymbol(theEnv);
405
+ return;
406
+ }
407
+
408
+ /*=======================================*/
409
+ /* Collect input into string if the read */
410
+ /* source is stdin, else just get token. */
411
+ /*=======================================*/
412
+
413
+ if (strcmp(logicalName,STDIN) == 0)
414
+ { ReadTokenFromStdin(theEnv,&theToken); }
415
+ else
416
+ { GetToken(theEnv,logicalName,&theToken); }
417
+
418
+ /*====================================================*/
419
+ /* Copy the token to the return value data structure. */
420
+ /*====================================================*/
421
+
422
+ if ((theToken.tknType == FLOAT_TOKEN) || (theToken.tknType == STRING_TOKEN) ||
423
+ #if OBJECT_SYSTEM
424
+ (theToken.tknType == INSTANCE_NAME_TOKEN) ||
425
+ #endif
426
+ (theToken.tknType == SYMBOL_TOKEN) || (theToken.tknType == INTEGER_TOKEN))
427
+ { returnValue->value = theToken.value; }
428
+ else if (theToken.tknType == STOP_TOKEN)
429
+ {
430
+ SetErrorValue(theEnv,&CreateSymbol(theEnv,"EOF")->header);
431
+ returnValue->value = CreateSymbol(theEnv,"EOF");
432
+ }
433
+ else if (theToken.tknType == UNKNOWN_VALUE_TOKEN)
434
+ {
435
+ SetErrorValue(theEnv,&CreateSymbol(theEnv,"READ_ERROR")->header);
436
+ returnValue->lexemeValue = FalseSymbol(theEnv);
437
+ }
438
+ else
439
+ { returnValue->value = CreateSymbol(theEnv,theToken.printForm); }
440
+ }
441
+
442
+ /********************************************************/
443
+ /* ReadTokenFromStdin: Special routine used by the read */
444
+ /* function to read a token from standard input. */
445
+ /********************************************************/
446
+ static void ReadTokenFromStdin(
447
+ Environment *theEnv,
448
+ struct token *theToken)
449
+ {
450
+ char *inputString;
451
+ size_t inputStringSize;
452
+ int inchar;
453
+
454
+ /*===========================================*/
455
+ /* Initialize the variables used for storing */
456
+ /* the characters retrieved from stdin. */
457
+ /*===========================================*/
458
+
459
+ inputString = NULL;
460
+ RouterData(theEnv)->CommandBufferInputCount = 0;
461
+ RouterData(theEnv)->InputUngets = 0;
462
+ RouterData(theEnv)->AwaitingInput = true;
463
+ inputStringSize = 0;
464
+
465
+ /*=============================================*/
466
+ /* Continue processing until a token is found. */
467
+ /*=============================================*/
468
+
469
+ theToken->tknType = STOP_TOKEN;
470
+ while (theToken->tknType == STOP_TOKEN)
471
+ {
472
+ /*========================================================*/
473
+ /* Continue reading characters until a carriage return is */
474
+ /* entered or the user halts execution (usually with */
475
+ /* control-c). Waiting for the carriage return prevents */
476
+ /* the input from being prematurely parsed (such as when */
477
+ /* a space is entered after a symbol has been typed). */
478
+ /*========================================================*/
479
+
480
+ inchar = ReadRouter(theEnv,STDIN);
481
+
482
+ while ((inchar != '\n') && (inchar != '\r') && (inchar != EOF) &&
483
+ (! GetHaltExecution(theEnv)))
484
+ {
485
+ inputString = ExpandStringWithChar(theEnv,inchar,inputString,&RouterData(theEnv)->CommandBufferInputCount,
486
+ &inputStringSize,inputStringSize + 80);
487
+ inchar = ReadRouter(theEnv,STDIN);
488
+ }
489
+
490
+ /*====================================================*/
491
+ /* Add the final carriage return to the input buffer. */
492
+ /*====================================================*/
493
+
494
+ if ((inchar == '\n') || (inchar == '\r'))
495
+ {
496
+ inputString = ExpandStringWithChar(theEnv,inchar,inputString,&RouterData(theEnv)->CommandBufferInputCount,
497
+ &inputStringSize,inputStringSize + 80);
498
+ }
499
+
500
+ /*==================================================*/
501
+ /* Open a string input source using the characters */
502
+ /* retrieved from stdin and extract the first token */
503
+ /* contained in the string. */
504
+ /*==================================================*/
505
+
506
+ OpenStringSource(theEnv,"read",inputString,0);
507
+ GetToken(theEnv,"read",theToken);
508
+ CloseStringSource(theEnv,"read");
509
+
510
+ /*===========================================*/
511
+ /* Pressing control-c (or comparable action) */
512
+ /* aborts the read function. */
513
+ /*===========================================*/
514
+
515
+ if (GetHaltExecution(theEnv))
516
+ {
517
+ SetErrorValue(theEnv,&CreateSymbol(theEnv,"READ_ERROR")->header);
518
+ theToken->tknType = SYMBOL_TOKEN;
519
+ theToken->value = FalseSymbol(theEnv);
520
+ }
521
+
522
+ /*====================================================*/
523
+ /* Return the EOF symbol if the end of file for stdin */
524
+ /* has been encountered. This typically won't occur, */
525
+ /* but is possible (for example by pressing control-d */
526
+ /* in the UNIX operating system). */
527
+ /*====================================================*/
528
+
529
+ if ((theToken->tknType == STOP_TOKEN) && (inchar == EOF))
530
+ {
531
+ theToken->tknType = SYMBOL_TOKEN;
532
+ theToken->value = CreateSymbol(theEnv,"EOF");
533
+ }
534
+ }
535
+
536
+ if (inputStringSize > 0) rm(theEnv,inputString,inputStringSize);
537
+
538
+ RouterData(theEnv)->CommandBufferInputCount = 0;
539
+ RouterData(theEnv)->InputUngets = 0;
540
+ RouterData(theEnv)->AwaitingInput = false;
541
+ }
542
+
543
+ /*************************************************************/
544
+ /* OpenFunction: H/L access routine for the open function. */
545
+ /*************************************************************/
546
+ void OpenFunction(
547
+ Environment *theEnv,
548
+ UDFContext *context,
549
+ UDFValue *returnValue)
550
+ {
551
+ const char *fileName, *logicalName, *accessMode = NULL;
552
+ UDFValue theArg;
553
+
554
+ /*====================*/
555
+ /* Get the file name. */
556
+ /*====================*/
557
+
558
+ if ((fileName = GetFileName(context)) == NULL)
559
+ {
560
+ returnValue->lexemeValue = FalseSymbol(theEnv);
561
+ return;
562
+ }
563
+
564
+ /*=======================================*/
565
+ /* Get the logical name to be associated */
566
+ /* with the opened file. */
567
+ /*=======================================*/
568
+
569
+ logicalName = GetLogicalName(context,NULL);
570
+ if (logicalName == NULL)
571
+ {
572
+ SetHaltExecution(theEnv,true);
573
+ SetEvaluationError(theEnv,true);
574
+ IllegalLogicalNameMessage(theEnv,"open");
575
+ returnValue->lexemeValue = FalseSymbol(theEnv);
576
+ return;
577
+ }
578
+
579
+ /*==================================*/
580
+ /* Check to see if the logical name */
581
+ /* is already in use. */
582
+ /*==================================*/
583
+
584
+ if (FindFile(theEnv,logicalName,NULL))
585
+ {
586
+ SetHaltExecution(theEnv,true);
587
+ SetEvaluationError(theEnv,true);
588
+ PrintErrorID(theEnv,"IOFUN",2,false);
589
+ WriteString(theEnv,STDERR,"Logical name '");
590
+ WriteString(theEnv,STDERR,logicalName);
591
+ WriteString(theEnv,STDERR,"' already in use.\n");
592
+ returnValue->lexemeValue = FalseSymbol(theEnv);
593
+ return;
594
+ }
595
+
596
+ /*===========================*/
597
+ /* Get the file access mode. */
598
+ /*===========================*/
599
+
600
+ if (! UDFHasNextArgument(context))
601
+ { accessMode = "r"; }
602
+ else
603
+ {
604
+ if (! UDFNextArgument(context,STRING_BIT,&theArg))
605
+ { return; }
606
+ accessMode = theArg.lexemeValue->contents;
607
+ }
608
+
609
+ /*=====================================*/
610
+ /* Check for a valid file access mode. */
611
+ /*=====================================*/
612
+
613
+ if ((strcmp(accessMode,"r") != 0) &&
614
+ (strcmp(accessMode,"r+") != 0) &&
615
+ (strcmp(accessMode,"w") != 0) &&
616
+ (strcmp(accessMode,"w+") != 0) &&
617
+ (strcmp(accessMode,"a") != 0) &&
618
+ (strcmp(accessMode,"a+") != 0) &&
619
+ (strcmp(accessMode,"rb") != 0) &&
620
+ (strcmp(accessMode,"r+b") != 0) &&
621
+ (strcmp(accessMode,"rb+") != 0) &&
622
+ (strcmp(accessMode,"wb") != 0) &&
623
+ (strcmp(accessMode,"w+b") != 0) &&
624
+ (strcmp(accessMode,"wb+") != 0) &&
625
+ (strcmp(accessMode,"ab") != 0) &&
626
+ (strcmp(accessMode,"a+b") != 0) &&
627
+ (strcmp(accessMode,"ab+")))
628
+ {
629
+ SetHaltExecution(theEnv,true);
630
+ SetEvaluationError(theEnv,true);
631
+ ExpectedTypeError1(theEnv,"open",3,"'file access mode string'");
632
+ returnValue->lexemeValue = FalseSymbol(theEnv);
633
+ return;
634
+ }
635
+
636
+ /*================================================*/
637
+ /* Open the named file and associate it with the */
638
+ /* specified logical name. Return TRUE if the */
639
+ /* file was opened successfully, otherwise FALSE. */
640
+ /*================================================*/
641
+
642
+ returnValue->lexemeValue = CreateBoolean(theEnv,OpenAFile(theEnv,fileName,accessMode,logicalName));
643
+ }
644
+
645
+ /*************************************************************/
646
+ /* CloseFunction: H/L access routine for the close function. */
647
+ /*************************************************************/
648
+ void CloseFunction(
649
+ Environment *theEnv,
650
+ UDFContext *context,
651
+ UDFValue *returnValue)
652
+ {
653
+ const char *logicalName;
654
+
655
+ /*=====================================================*/
656
+ /* If no arguments are specified, then close all files */
657
+ /* opened with the open command. Return true if all */
658
+ /* files were closed successfully, otherwise false. */
659
+ /*=====================================================*/
660
+
661
+ if (! UDFHasNextArgument(context))
662
+ {
663
+ returnValue->lexemeValue = CreateBoolean(theEnv,CloseAllFiles(theEnv));
664
+ return;
665
+ }
666
+
667
+ /*================================*/
668
+ /* Get the logical name argument. */
669
+ /*================================*/
670
+
671
+ logicalName = GetLogicalName(context,NULL);
672
+ if (logicalName == NULL)
673
+ {
674
+ IllegalLogicalNameMessage(theEnv,"close");
675
+ SetHaltExecution(theEnv,true);
676
+ SetEvaluationError(theEnv,true);
677
+ returnValue->lexemeValue = FalseSymbol(theEnv);
678
+ return;
679
+ }
680
+
681
+ /*========================================================*/
682
+ /* Close the file associated with the specified logical */
683
+ /* name. Return true if the file was closed successfully, */
684
+ /* otherwise false. */
685
+ /*========================================================*/
686
+
687
+ returnValue->lexemeValue = CreateBoolean(theEnv,CloseFile(theEnv,logicalName));
688
+ }
689
+
690
+ /*************************************************************/
691
+ /* FlushFunction: H/L access routine for the flush function. */
692
+ /*************************************************************/
693
+ void FlushFunction(
694
+ Environment *theEnv,
695
+ UDFContext *context,
696
+ UDFValue *returnValue)
697
+ {
698
+ const char *logicalName;
699
+
700
+ /*=====================================================*/
701
+ /* If no arguments are specified, then flush all files */
702
+ /* opened with the open command. Return true if all */
703
+ /* files were flushed successfully, otherwise false. */
704
+ /*=====================================================*/
705
+
706
+ if (! UDFHasNextArgument(context))
707
+ {
708
+ returnValue->lexemeValue = CreateBoolean(theEnv,FlushAllFiles(theEnv));
709
+ return;
710
+ }
711
+
712
+ /*================================*/
713
+ /* Get the logical name argument. */
714
+ /*================================*/
715
+
716
+ logicalName = GetLogicalName(context,NULL);
717
+ if (logicalName == NULL)
718
+ {
719
+ IllegalLogicalNameMessage(theEnv,"flush");
720
+ SetHaltExecution(theEnv,true);
721
+ SetEvaluationError(theEnv,true);
722
+ returnValue->lexemeValue = FalseSymbol(theEnv);
723
+ return;
724
+ }
725
+
726
+ /*=========================================================*/
727
+ /* Flush the file associated with the specified logical */
728
+ /* name. Return true if the file was flushed successfully, */
729
+ /* otherwise false. */
730
+ /*=========================================================*/
731
+
732
+ returnValue->lexemeValue = CreateBoolean(theEnv,FlushFile(theEnv,logicalName));
733
+ }
734
+
735
+ /***************************************************************/
736
+ /* RewindFunction: H/L access routine for the rewind function. */
737
+ /***************************************************************/
738
+ void RewindFunction(
739
+ Environment *theEnv,
740
+ UDFContext *context,
741
+ UDFValue *returnValue)
742
+ {
743
+ const char *logicalName;
744
+
745
+ /*================================*/
746
+ /* Get the logical name argument. */
747
+ /*================================*/
748
+
749
+ logicalName = GetLogicalName(context,NULL);
750
+ if (logicalName == NULL)
751
+ {
752
+ IllegalLogicalNameMessage(theEnv,"flush");
753
+ SetHaltExecution(theEnv,true);
754
+ SetEvaluationError(theEnv,true);
755
+ returnValue->lexemeValue = FalseSymbol(theEnv);
756
+ return;
757
+ }
758
+
759
+ /*============================================*/
760
+ /* Check to see that the logical name exists. */
761
+ /*============================================*/
762
+
763
+ if (QueryRouters(theEnv,logicalName) == false)
764
+ {
765
+ UnrecognizedRouterMessage(theEnv,logicalName);
766
+ SetHaltExecution(theEnv,true);
767
+ SetEvaluationError(theEnv,true);
768
+ returnValue->lexemeValue = FalseSymbol(theEnv);
769
+ return;
770
+ }
771
+
772
+ /*=========================================================*/
773
+ /* Rewind the file associated with the specified logical */
774
+ /* name. Return true if the file was rewound successfully, */
775
+ /* otherwise false. */
776
+ /*=========================================================*/
777
+
778
+ returnValue->lexemeValue = CreateBoolean(theEnv,RewindFile(theEnv,logicalName));
779
+ }
780
+
781
+ /***********************************************************/
782
+ /* TellFunction: H/L access routine for the tell function. */
783
+ /***********************************************************/
784
+ void TellFunction(
785
+ Environment *theEnv,
786
+ UDFContext *context,
787
+ UDFValue *returnValue)
788
+ {
789
+ const char *logicalName;
790
+ long long rv;
791
+
792
+ /*================================*/
793
+ /* Get the logical name argument. */
794
+ /*================================*/
795
+
796
+ logicalName = GetLogicalName(context,NULL);
797
+ if (logicalName == NULL)
798
+ {
799
+ IllegalLogicalNameMessage(theEnv,"tell");
800
+ SetHaltExecution(theEnv,true);
801
+ SetEvaluationError(theEnv,true);
802
+ returnValue->lexemeValue = FalseSymbol(theEnv);
803
+ return;
804
+ }
805
+
806
+ /*============================================*/
807
+ /* Check to see that the logical name exists. */
808
+ /*============================================*/
809
+
810
+ if (QueryRouters(theEnv,logicalName) == false)
811
+ {
812
+ UnrecognizedRouterMessage(theEnv,logicalName);
813
+ SetHaltExecution(theEnv,true);
814
+ SetEvaluationError(theEnv,true);
815
+ returnValue->lexemeValue = FalseSymbol(theEnv);
816
+ return;
817
+ }
818
+
819
+ /*===========================*/
820
+ /* Return the file position. */
821
+ /*===========================*/
822
+
823
+ rv = TellFile(theEnv,logicalName);
824
+
825
+ if (rv == LLONG_MIN)
826
+ { returnValue->lexemeValue = FalseSymbol(theEnv); }
827
+ else
828
+ { returnValue->integerValue = CreateInteger(theEnv,rv); }
829
+ }
830
+
831
+ /***********************************************************/
832
+ /* SeekFunction: H/L access routine for the seek function. */
833
+ /***********************************************************/
834
+ void SeekFunction(
835
+ Environment *theEnv,
836
+ UDFContext *context,
837
+ UDFValue *returnValue)
838
+ {
839
+ const char *logicalName;
840
+ UDFValue theArg;
841
+ long offset;
842
+ const char *seekCode;
843
+
844
+ /*================================*/
845
+ /* Get the logical name argument. */
846
+ /*================================*/
847
+
848
+ logicalName = GetLogicalName(context,NULL);
849
+ if (logicalName == NULL)
850
+ {
851
+ IllegalLogicalNameMessage(theEnv,"seek");
852
+ SetHaltExecution(theEnv,true);
853
+ SetEvaluationError(theEnv,true);
854
+ returnValue->lexemeValue = FalseSymbol(theEnv);
855
+ return;
856
+ }
857
+
858
+ /*============================================*/
859
+ /* Check to see that the logical name exists. */
860
+ /*============================================*/
861
+
862
+ if (QueryRouters(theEnv,logicalName) == false)
863
+ {
864
+ UnrecognizedRouterMessage(theEnv,logicalName);
865
+ SetHaltExecution(theEnv,true);
866
+ SetEvaluationError(theEnv,true);
867
+ returnValue->lexemeValue = FalseSymbol(theEnv);
868
+ return;
869
+ }
870
+
871
+ /*=================*/
872
+ /* Get the offset. */
873
+ /*=================*/
874
+
875
+ if (! UDFNextArgument(context,INTEGER_BIT,&theArg))
876
+ {
877
+ returnValue->lexemeValue = FalseSymbol(theEnv);
878
+ return;
879
+ }
880
+
881
+ offset = (long) theArg.integerValue->contents;
882
+
883
+ /*====================*/
884
+ /* Get the seek code. */
885
+ /*====================*/
886
+
887
+ if (! UDFNextArgument(context,SYMBOL_BIT,&theArg))
888
+ {
889
+ returnValue->lexemeValue = FalseSymbol(theEnv);
890
+ return;
891
+ }
892
+
893
+ seekCode = theArg.lexemeValue->contents;
894
+
895
+ if (strcmp(seekCode,"seek-set") == 0)
896
+ { returnValue->lexemeValue = CreateBoolean(theEnv,SeekFile(theEnv,logicalName,offset,SEEK_SET)); }
897
+ else if (strcmp(seekCode,"seek-cur") == 0)
898
+ { returnValue->lexemeValue = CreateBoolean(theEnv,SeekFile(theEnv,logicalName,offset,SEEK_CUR)); }
899
+ else if (strcmp(seekCode,"seek-end") == 0)
900
+ { returnValue->lexemeValue = CreateBoolean(theEnv,SeekFile(theEnv,logicalName,offset,SEEK_END)); }
901
+ else
902
+ {
903
+ UDFInvalidArgumentMessage(context,
904
+ "symbol with value seek-set, seek-cur, or seek-end");
905
+ returnValue->lexemeValue = FalseSymbol(theEnv);
906
+ return;
907
+ }
908
+ }
909
+
910
+ /***************************************/
911
+ /* GetCharFunction: H/L access routine */
912
+ /* for the get-char function. */
913
+ /***************************************/
914
+ void GetCharFunction(
915
+ Environment *theEnv,
916
+ UDFContext *context,
917
+ UDFValue *returnValue)
918
+ {
919
+ const char *logicalName;
920
+
921
+ /*================================*/
922
+ /* Get the logical name argument. */
923
+ /*================================*/
924
+
925
+ if (! UDFHasNextArgument(context))
926
+ { logicalName = STDIN; }
927
+ else
928
+ {
929
+ logicalName = GetLogicalName(context,STDIN);
930
+ if (logicalName == NULL)
931
+ {
932
+ IllegalLogicalNameMessage(theEnv,"get-char");
933
+ SetHaltExecution(theEnv,true);
934
+ SetEvaluationError(theEnv,true);
935
+ returnValue->integerValue = CreateInteger(theEnv,-1);
936
+ return;
937
+ }
938
+ }
939
+
940
+ /*============================================*/
941
+ /* Check to see that the logical name exists. */
942
+ /*============================================*/
943
+
944
+ if (QueryRouters(theEnv,logicalName) == false)
945
+ {
946
+ UnrecognizedRouterMessage(theEnv,logicalName);
947
+ SetHaltExecution(theEnv,true);
948
+ SetEvaluationError(theEnv,true);
949
+ returnValue->integerValue = CreateInteger(theEnv,-1);
950
+ return;
951
+ }
952
+
953
+ if (strcmp(logicalName,STDIN) == 0)
954
+ {
955
+ if (RouterData(theEnv)->InputUngets > 0)
956
+ {
957
+ returnValue->integerValue = CreateInteger(theEnv,ReadRouter(theEnv,logicalName));
958
+ RouterData(theEnv)->InputUngets--;
959
+ }
960
+ else
961
+ {
962
+ int theChar;
963
+
964
+ RouterData(theEnv)->AwaitingInput = true;
965
+ theChar = ReadRouter(theEnv,logicalName);
966
+ RouterData(theEnv)->AwaitingInput = false;
967
+
968
+ if (theChar == '\b')
969
+ {
970
+ if (RouterData(theEnv)->CommandBufferInputCount > 0)
971
+ { RouterData(theEnv)->CommandBufferInputCount--; }
972
+ }
973
+ else
974
+ { RouterData(theEnv)->CommandBufferInputCount++; }
975
+
976
+ returnValue->integerValue = CreateInteger(theEnv,theChar);
977
+ }
978
+
979
+ return;
980
+ }
981
+
982
+ returnValue->integerValue = CreateInteger(theEnv,ReadRouter(theEnv,logicalName));
983
+ }
984
+
985
+ /*****************************************/
986
+ /* UngetCharFunction: H/L access routine */
987
+ /* for the unget-char function. */
988
+ /*****************************************/
989
+ void UngetCharFunction(
990
+ Environment *theEnv,
991
+ UDFContext *context,
992
+ UDFValue *returnValue)
993
+ {
994
+ unsigned int numberOfArguments;
995
+ const char *logicalName;
996
+ UDFValue theArg;
997
+ long long theChar;
998
+
999
+ numberOfArguments = UDFArgumentCount(context);
1000
+
1001
+ /*=======================*/
1002
+ /* Get the logical name. */
1003
+ /*=======================*/
1004
+
1005
+ if (numberOfArguments == 1)
1006
+ { logicalName = STDIN; }
1007
+ else
1008
+ {
1009
+ logicalName = GetLogicalName(context,STDIN);
1010
+ if (logicalName == NULL)
1011
+ {
1012
+ IllegalLogicalNameMessage(theEnv,"ungetc-char");
1013
+ SetHaltExecution(theEnv,true);
1014
+ SetEvaluationError(theEnv,true);
1015
+ returnValue->integerValue = CreateInteger(theEnv,-1);
1016
+ return;
1017
+ }
1018
+ }
1019
+
1020
+ if (QueryRouters(theEnv,logicalName) == false)
1021
+ {
1022
+ UnrecognizedRouterMessage(theEnv,logicalName);
1023
+ SetHaltExecution(theEnv,true);
1024
+ SetEvaluationError(theEnv,true);
1025
+ returnValue->integerValue = CreateInteger(theEnv,-1);
1026
+ return;
1027
+ }
1028
+
1029
+ /*=============================*/
1030
+ /* Get the character to unget. */
1031
+ /*=============================*/
1032
+
1033
+ if (! UDFNextArgument(context,INTEGER_BIT,&theArg))
1034
+ { return; }
1035
+
1036
+ theChar = theArg.integerValue->contents;
1037
+ if (theChar == -1)
1038
+ {
1039
+ returnValue->integerValue = CreateInteger(theEnv,-1);
1040
+ return;
1041
+ }
1042
+
1043
+ /*=======================*/
1044
+ /* Ungetc the character. */
1045
+ /*=======================*/
1046
+
1047
+ if (strcmp(logicalName,STDIN) == 0)
1048
+ { RouterData(theEnv)->InputUngets++; }
1049
+
1050
+ returnValue->integerValue = CreateInteger(theEnv,UnreadRouter(theEnv,logicalName,(int) theChar));
1051
+ }
1052
+
1053
+ /***************************************/
1054
+ /* PutCharFunction: H/L access routine */
1055
+ /* for the put-char function. */
1056
+ /***************************************/
1057
+ void PutCharFunction(
1058
+ Environment *theEnv,
1059
+ UDFContext *context,
1060
+ UDFValue *returnValue)
1061
+ {
1062
+ unsigned int numberOfArguments;
1063
+ const char *logicalName;
1064
+ UDFValue theArg;
1065
+ long long theChar;
1066
+ FILE *theFile;
1067
+
1068
+ numberOfArguments = UDFArgumentCount(context);
1069
+
1070
+ /*=======================*/
1071
+ /* Get the logical name. */
1072
+ /*=======================*/
1073
+
1074
+ if (numberOfArguments == 1)
1075
+ { logicalName = STDOUT; }
1076
+ else
1077
+ {
1078
+ logicalName = GetLogicalName(context,STDOUT);
1079
+ if (logicalName == NULL)
1080
+ {
1081
+ IllegalLogicalNameMessage(theEnv,"put-char");
1082
+ SetHaltExecution(theEnv,true);
1083
+ SetEvaluationError(theEnv,true);
1084
+ return;
1085
+ }
1086
+ }
1087
+
1088
+ if (QueryRouters(theEnv,logicalName) == false)
1089
+ {
1090
+ UnrecognizedRouterMessage(theEnv,logicalName);
1091
+ SetHaltExecution(theEnv,true);
1092
+ SetEvaluationError(theEnv,true);
1093
+ return;
1094
+ }
1095
+
1096
+ /*===========================*/
1097
+ /* Get the character to put. */
1098
+ /*===========================*/
1099
+
1100
+ if (! UDFNextArgument(context,INTEGER_BIT,&theArg))
1101
+ { return; }
1102
+
1103
+ theChar = theArg.integerValue->contents;
1104
+
1105
+ /*===================================================*/
1106
+ /* If the "fast load" option is being used, then the */
1107
+ /* logical name is actually a pointer to a file and */
1108
+ /* we can bypass the router and directly output the */
1109
+ /* value. */
1110
+ /*===================================================*/
1111
+
1112
+ theFile = FindFptr(theEnv,logicalName);
1113
+ if (theFile != NULL)
1114
+ { putc((int) theChar,theFile); }
1115
+ }
1116
+
1117
+ /****************************************/
1118
+ /* RemoveFunction: H/L access routine */
1119
+ /* for the remove function. */
1120
+ /****************************************/
1121
+ void RemoveFunction(
1122
+ Environment *theEnv,
1123
+ UDFContext *context,
1124
+ UDFValue *returnValue)
1125
+ {
1126
+ const char *theFileName;
1127
+
1128
+ /*====================*/
1129
+ /* Get the file name. */
1130
+ /*====================*/
1131
+
1132
+ if ((theFileName = GetFileName(context)) == NULL)
1133
+ {
1134
+ returnValue->lexemeValue = FalseSymbol(theEnv);
1135
+ return;
1136
+ }
1137
+
1138
+ /*==============================================*/
1139
+ /* Remove the file. Return true if the file was */
1140
+ /* sucessfully removed, otherwise false. */
1141
+ /*==============================================*/
1142
+
1143
+ returnValue->lexemeValue = CreateBoolean(theEnv,genremove(theEnv,theFileName));
1144
+ }
1145
+
1146
+ /****************************************/
1147
+ /* RenameFunction: H/L access routine */
1148
+ /* for the rename function. */
1149
+ /****************************************/
1150
+ void RenameFunction(
1151
+ Environment *theEnv,
1152
+ UDFContext *context,
1153
+ UDFValue *returnValue)
1154
+ {
1155
+ const char *oldFileName, *newFileName;
1156
+
1157
+ /*===========================*/
1158
+ /* Check for the file names. */
1159
+ /*===========================*/
1160
+
1161
+ if ((oldFileName = GetFileName(context)) == NULL)
1162
+ {
1163
+ returnValue->lexemeValue = FalseSymbol(theEnv);
1164
+ return;
1165
+ }
1166
+
1167
+ if ((newFileName = GetFileName(context)) == NULL)
1168
+ {
1169
+ returnValue->lexemeValue = FalseSymbol(theEnv);
1170
+ return;
1171
+ }
1172
+
1173
+ /*==============================================*/
1174
+ /* Rename the file. Return true if the file was */
1175
+ /* sucessfully renamed, otherwise false. */
1176
+ /*==============================================*/
1177
+
1178
+ returnValue->lexemeValue = CreateBoolean(theEnv,genrename(theEnv,oldFileName,newFileName));
1179
+ }
1180
+
1181
+ /*************************************/
1182
+ /* ChdirFunction: H/L access routine */
1183
+ /* for the chdir function. */
1184
+ /*************************************/
1185
+ void ChdirFunction(
1186
+ Environment *theEnv,
1187
+ UDFContext *context,
1188
+ UDFValue *returnValue)
1189
+ {
1190
+ const char *theFileName;
1191
+ int success;
1192
+
1193
+ /*===============================================*/
1194
+ /* If called with no arguments, the return value */
1195
+ /* indicates whether chdir is supported. */
1196
+ /*===============================================*/
1197
+
1198
+ if (! UDFHasNextArgument(context))
1199
+ {
1200
+ if (genchdir(theEnv,NULL))
1201
+ { returnValue->lexemeValue = TrueSymbol(theEnv); }
1202
+ else
1203
+ { returnValue->lexemeValue = FalseSymbol(theEnv); }
1204
+
1205
+ return;
1206
+ }
1207
+
1208
+ /*====================*/
1209
+ /* Get the file name. */
1210
+ /*====================*/
1211
+
1212
+ if ((theFileName = GetFileName(context)) == NULL)
1213
+ {
1214
+ returnValue->lexemeValue = FalseSymbol(theEnv);
1215
+ return;
1216
+ }
1217
+
1218
+ /*==================================================*/
1219
+ /* Change the directory. Return TRUE if successful, */
1220
+ /* FALSE if unsuccessful, and UNSUPPORTED if the */
1221
+ /* chdir functionality is not implemented. */
1222
+ /*==================================================*/
1223
+
1224
+ success = genchdir(theEnv,theFileName);
1225
+
1226
+ switch (success)
1227
+ {
1228
+ case 1:
1229
+ returnValue->lexemeValue = TrueSymbol(theEnv);
1230
+ break;
1231
+
1232
+ case 0:
1233
+ returnValue->lexemeValue = FalseSymbol(theEnv);
1234
+ break;
1235
+
1236
+ default:
1237
+ WriteString(theEnv,STDERR,"The chdir function is not supported on this system.\n");
1238
+ SetHaltExecution(theEnv,true);
1239
+ SetEvaluationError(theEnv,true);
1240
+ returnValue->lexemeValue = FalseSymbol(theEnv);
1241
+ break;
1242
+ }
1243
+ }
1244
+
1245
+ /****************************************/
1246
+ /* FormatFunction: H/L access routine */
1247
+ /* for the format function. */
1248
+ /****************************************/
1249
+ void FormatFunction(
1250
+ Environment *theEnv,
1251
+ UDFContext *context,
1252
+ UDFValue *returnValue)
1253
+ {
1254
+ unsigned int argCount;
1255
+ size_t start_pos;
1256
+ const char *formatString;
1257
+ const char *logicalName;
1258
+ char formatFlagType;
1259
+ unsigned int f_cur_arg = 3;
1260
+ size_t form_pos = 0;
1261
+ char percentBuffer[FLAG_MAX];
1262
+ char *fstr = NULL;
1263
+ size_t fmaxm = 0;
1264
+ size_t fpos = 0;
1265
+ void *hptr;
1266
+ const char *theString;
1267
+
1268
+ /*======================================*/
1269
+ /* Set default return value for errors. */
1270
+ /*======================================*/
1271
+
1272
+ hptr = CreateString(theEnv,"");
1273
+
1274
+ /*=========================================*/
1275
+ /* Format requires at least two arguments: */
1276
+ /* a logical name and a format string. */
1277
+ /*=========================================*/
1278
+
1279
+ argCount = UDFArgumentCount(context);
1280
+
1281
+ /*========================================*/
1282
+ /* First argument must be a logical name. */
1283
+ /*========================================*/
1284
+
1285
+ if ((logicalName = GetLogicalName(context,STDOUT)) == NULL)
1286
+ {
1287
+ IllegalLogicalNameMessage(theEnv,"format");
1288
+ SetHaltExecution(theEnv,true);
1289
+ SetEvaluationError(theEnv,true);
1290
+ returnValue->value = hptr;
1291
+ return;
1292
+ }
1293
+
1294
+ if (strcmp(logicalName,"nil") == 0)
1295
+ { /* do nothing */ }
1296
+ else if (QueryRouters(theEnv,logicalName) == false)
1297
+ {
1298
+ UnrecognizedRouterMessage(theEnv,logicalName);
1299
+ returnValue->value = hptr;
1300
+ return;
1301
+ }
1302
+
1303
+ /*=====================================================*/
1304
+ /* Second argument must be a string. The appropriate */
1305
+ /* number of arguments specified by the string must be */
1306
+ /* present in the argument list. */
1307
+ /*=====================================================*/
1308
+
1309
+ if ((formatString = ControlStringCheck(context,argCount)) == NULL)
1310
+ {
1311
+ returnValue->value = hptr;
1312
+ return;
1313
+ }
1314
+
1315
+ /*========================================*/
1316
+ /* Search the format string, printing the */
1317
+ /* format flags as they are encountered. */
1318
+ /*========================================*/
1319
+
1320
+ while (formatString[form_pos] != '\0')
1321
+ {
1322
+ if (formatString[form_pos] != '%')
1323
+ {
1324
+ start_pos = form_pos;
1325
+ while ((formatString[form_pos] != '%') &&
1326
+ (formatString[form_pos] != '\0'))
1327
+ { form_pos++; }
1328
+ fstr = AppendNToString(theEnv,&formatString[start_pos],fstr,form_pos-start_pos,&fpos,&fmaxm);
1329
+ }
1330
+ else
1331
+ {
1332
+ form_pos++;
1333
+ formatFlagType = FindFormatFlag(formatString,&form_pos,percentBuffer,FLAG_MAX);
1334
+ if (formatFlagType != ' ')
1335
+ {
1336
+ if ((theString = PrintFormatFlag(context,percentBuffer,f_cur_arg,formatFlagType)) == NULL)
1337
+ {
1338
+ if (fstr != NULL) rm(theEnv,fstr,fmaxm);
1339
+ returnValue->value = hptr;
1340
+ return;
1341
+ }
1342
+ fstr = AppendToString(theEnv,theString,fstr,&fpos,&fmaxm);
1343
+ if (fstr == NULL)
1344
+ {
1345
+ returnValue->value = hptr;
1346
+ return;
1347
+ }
1348
+ f_cur_arg++;
1349
+ }
1350
+ else
1351
+ {
1352
+ fstr = AppendToString(theEnv,percentBuffer,fstr,&fpos,&fmaxm);
1353
+ if (fstr == NULL)
1354
+ {
1355
+ returnValue->value = hptr;
1356
+ return;
1357
+ }
1358
+ }
1359
+ }
1360
+ }
1361
+
1362
+ if (fstr != NULL)
1363
+ {
1364
+ hptr = CreateString(theEnv,fstr);
1365
+ if (strcmp(logicalName,"nil") != 0) WriteString(theEnv,logicalName,fstr);
1366
+ rm(theEnv,fstr,fmaxm);
1367
+ }
1368
+ else
1369
+ { hptr = CreateString(theEnv,""); }
1370
+
1371
+ returnValue->value = hptr;
1372
+ }
1373
+
1374
+ /*********************************************************************/
1375
+ /* ControlStringCheck: Checks the 2nd parameter which is the format */
1376
+ /* control string to see if there are enough matching arguments. */
1377
+ /*********************************************************************/
1378
+ static const char *ControlStringCheck(
1379
+ UDFContext *context,
1380
+ unsigned int argCount)
1381
+ {
1382
+ UDFValue t_ptr;
1383
+ const char *str_array;
1384
+ char print_buff[FLAG_MAX];
1385
+ size_t i;
1386
+ unsigned int per_count;
1387
+ char formatFlag;
1388
+ Environment *theEnv = context->environment;
1389
+
1390
+ if (! UDFNthArgument(context,2,STRING_BIT,&t_ptr))
1391
+ { return NULL; }
1392
+
1393
+ per_count = 0;
1394
+ str_array = t_ptr.lexemeValue->contents;
1395
+ for (i = 0; str_array[i] != '\0' ; )
1396
+ {
1397
+ if (str_array[i] == '%')
1398
+ {
1399
+ i++;
1400
+ formatFlag = FindFormatFlag(str_array,&i,print_buff,FLAG_MAX);
1401
+ if (formatFlag == '-')
1402
+ {
1403
+ PrintErrorID(theEnv,"IOFUN",3,false);
1404
+ WriteString(theEnv,STDERR,"Invalid format flag \"");
1405
+ WriteString(theEnv,STDERR,print_buff);
1406
+ WriteString(theEnv,STDERR,"\" specified in format function.\n");
1407
+ SetEvaluationError(theEnv,true);
1408
+ return (NULL);
1409
+ }
1410
+ else if (formatFlag != ' ')
1411
+ { per_count++; }
1412
+ }
1413
+ else
1414
+ { i++; }
1415
+ }
1416
+
1417
+ if ((per_count + 2) != argCount)
1418
+ {
1419
+ ExpectedCountError(theEnv,"format",EXACTLY,per_count+2);
1420
+ SetEvaluationError(theEnv,true);
1421
+ return (NULL);
1422
+ }
1423
+
1424
+ return(str_array);
1425
+ }
1426
+
1427
+ /***********************************************/
1428
+ /* FindFormatFlag: This function searches for */
1429
+ /* a format flag in the format string. */
1430
+ /***********************************************/
1431
+ static char FindFormatFlag(
1432
+ const char *formatString,
1433
+ size_t *a,
1434
+ char *formatBuffer,
1435
+ size_t bufferMax)
1436
+ {
1437
+ char inchar, formatFlagType;
1438
+ size_t copy_pos = 0;
1439
+
1440
+ /*====================================================*/
1441
+ /* Set return values to the default value. A blank */
1442
+ /* character indicates that no format flag was found */
1443
+ /* which requires a parameter. */
1444
+ /*====================================================*/
1445
+
1446
+ formatFlagType = ' ';
1447
+
1448
+ /*=====================================================*/
1449
+ /* The format flags for carriage returns, line feeds, */
1450
+ /* horizontal and vertical tabs, and the percent sign, */
1451
+ /* do not require a parameter. */
1452
+ /*=====================================================*/
1453
+
1454
+ if (formatString[*a] == 'n')
1455
+ {
1456
+ gensprintf(formatBuffer,"\n");
1457
+ (*a)++;
1458
+ return(formatFlagType);
1459
+ }
1460
+ else if (formatString[*a] == 'r')
1461
+ {
1462
+ gensprintf(formatBuffer,"\r");
1463
+ (*a)++;
1464
+ return(formatFlagType);
1465
+ }
1466
+ else if (formatString[*a] == 't')
1467
+ {
1468
+ gensprintf(formatBuffer,"\t");
1469
+ (*a)++;
1470
+ return(formatFlagType);
1471
+ }
1472
+ else if (formatString[*a] == 'v')
1473
+ {
1474
+ gensprintf(formatBuffer,"\v");
1475
+ (*a)++;
1476
+ return(formatFlagType);
1477
+ }
1478
+ else if (formatString[*a] == '%')
1479
+ {
1480
+ gensprintf(formatBuffer,"%%");
1481
+ (*a)++;
1482
+ return(formatFlagType);
1483
+ }
1484
+
1485
+ /*======================================================*/
1486
+ /* Identify the format flag which requires a parameter. */
1487
+ /*======================================================*/
1488
+
1489
+ formatBuffer[copy_pos++] = '%';
1490
+ formatBuffer[copy_pos] = '\0';
1491
+ while ((formatString[*a] != '%') &&
1492
+ (formatString[*a] != '\0') &&
1493
+ (copy_pos < (bufferMax - 5)))
1494
+ {
1495
+ inchar = formatString[*a];
1496
+ (*a)++;
1497
+
1498
+ if ( (inchar == 'd') ||
1499
+ (inchar == 'o') ||
1500
+ (inchar == 'x') ||
1501
+ (inchar == 'u'))
1502
+ {
1503
+ formatFlagType = inchar;
1504
+ formatBuffer[copy_pos++] = 'l';
1505
+ formatBuffer[copy_pos++] = 'l';
1506
+ formatBuffer[copy_pos++] = inchar;
1507
+ formatBuffer[copy_pos] = '\0';
1508
+ return(formatFlagType);
1509
+ }
1510
+ else if ( (inchar == 'c') ||
1511
+ (inchar == 's') ||
1512
+ (inchar == 'e') ||
1513
+ (inchar == 'f') ||
1514
+ (inchar == 'g') )
1515
+ {
1516
+ formatBuffer[copy_pos++] = inchar;
1517
+ formatBuffer[copy_pos] = '\0';
1518
+ formatFlagType = inchar;
1519
+ return(formatFlagType);
1520
+ }
1521
+
1522
+ /*=======================================================*/
1523
+ /* If the type hasn't been read, then this should be the */
1524
+ /* -M.N part of the format specification (where M and N */
1525
+ /* are integers). */
1526
+ /*=======================================================*/
1527
+
1528
+ if ( (! isdigit(inchar)) &&
1529
+ (inchar != '.') &&
1530
+ (inchar != '-') )
1531
+ {
1532
+ formatBuffer[copy_pos++] = inchar;
1533
+ formatBuffer[copy_pos] = '\0';
1534
+ return('-');
1535
+ }
1536
+
1537
+ formatBuffer[copy_pos++] = inchar;
1538
+ formatBuffer[copy_pos] = '\0';
1539
+ }
1540
+
1541
+ return(formatFlagType);
1542
+ }
1543
+
1544
+ /**********************************************************************/
1545
+ /* PrintFormatFlag: Prints out part of the total format string along */
1546
+ /* with the argument for that part of the format string. */
1547
+ /**********************************************************************/
1548
+ static const char *PrintFormatFlag(
1549
+ UDFContext *context,
1550
+ const char *formatString,
1551
+ unsigned int whichArg,
1552
+ int formatType)
1553
+ {
1554
+ UDFValue theResult;
1555
+ const char *theString;
1556
+ char *printBuffer;
1557
+ size_t theLength;
1558
+ CLIPSLexeme *oldLocale;
1559
+ Environment *theEnv = context->environment;
1560
+
1561
+ /*=================*/
1562
+ /* String argument */
1563
+ /*=================*/
1564
+
1565
+ switch (formatType)
1566
+ {
1567
+ case 's':
1568
+ if (! UDFNthArgument(context,whichArg,LEXEME_BITS,&theResult))
1569
+ { return(NULL); }
1570
+ theLength = strlen(formatString) + strlen(theResult.lexemeValue->contents) + 200;
1571
+ printBuffer = (char *) gm2(theEnv,(sizeof(char) * theLength));
1572
+ gensprintf(printBuffer,formatString,theResult.lexemeValue->contents);
1573
+ break;
1574
+
1575
+ case 'c':
1576
+ UDFNthArgument(context,whichArg,ANY_TYPE_BITS,&theResult);
1577
+ if ((theResult.header->type == STRING_TYPE) ||
1578
+ (theResult.header->type == SYMBOL_TYPE))
1579
+ {
1580
+ theLength = strlen(formatString) + 200;
1581
+ printBuffer = (char *) gm2(theEnv,(sizeof(char) * theLength));
1582
+ gensprintf(printBuffer,formatString,theResult.lexemeValue->contents[0]);
1583
+ }
1584
+ else if (theResult.header->type == INTEGER_TYPE)
1585
+ {
1586
+ theLength = strlen(formatString) + 200;
1587
+ printBuffer = (char *) gm2(theEnv,(sizeof(char) * theLength));
1588
+ gensprintf(printBuffer,formatString,(char) theResult.integerValue->contents);
1589
+ }
1590
+ else
1591
+ {
1592
+ ExpectedTypeError1(theEnv,"format",whichArg,"symbol, string, or integer");
1593
+ return NULL;
1594
+ }
1595
+ break;
1596
+
1597
+ case 'd':
1598
+ case 'x':
1599
+ case 'o':
1600
+ case 'u':
1601
+ if (! UDFNthArgument(context,whichArg,NUMBER_BITS,&theResult))
1602
+ { return(NULL); }
1603
+ theLength = strlen(formatString) + 200;
1604
+ printBuffer = (char *) gm2(theEnv,(sizeof(char) * theLength));
1605
+
1606
+ oldLocale = CreateSymbol(theEnv,setlocale(LC_NUMERIC,NULL));
1607
+ setlocale(LC_NUMERIC,IOFunctionData(theEnv)->locale->contents);
1608
+
1609
+ if (theResult.header->type == FLOAT_TYPE)
1610
+ { gensprintf(printBuffer,formatString,(long long) theResult.floatValue->contents); }
1611
+ else
1612
+ { gensprintf(printBuffer,formatString,theResult.integerValue->contents); }
1613
+
1614
+ setlocale(LC_NUMERIC,oldLocale->contents);
1615
+ break;
1616
+
1617
+ case 'f':
1618
+ case 'g':
1619
+ case 'e':
1620
+ if (! UDFNthArgument(context,whichArg,NUMBER_BITS,&theResult))
1621
+ { return(NULL); }
1622
+ theLength = strlen(formatString) + 200;
1623
+ printBuffer = (char *) gm2(theEnv,(sizeof(char) * theLength));
1624
+
1625
+ oldLocale = CreateSymbol(theEnv,setlocale(LC_NUMERIC,NULL));
1626
+
1627
+ setlocale(LC_NUMERIC,IOFunctionData(theEnv)->locale->contents);
1628
+
1629
+ if (theResult.header->type == FLOAT_TYPE)
1630
+ { gensprintf(printBuffer,formatString,theResult.floatValue->contents); }
1631
+ else
1632
+ { gensprintf(printBuffer,formatString,(double) theResult.integerValue->contents); }
1633
+
1634
+ setlocale(LC_NUMERIC,oldLocale->contents);
1635
+
1636
+ break;
1637
+
1638
+ default:
1639
+ WriteString(theEnv,STDERR," Error in format, the conversion character");
1640
+ WriteString(theEnv,STDERR," for formatted output is not valid\n");
1641
+ return NULL;
1642
+ }
1643
+
1644
+ theString = CreateString(theEnv,printBuffer)->contents;
1645
+ rm(theEnv,printBuffer,sizeof(char) * theLength);
1646
+ return(theString);
1647
+ }
1648
+
1649
+ /******************************************/
1650
+ /* ReadlineFunction: H/L access routine */
1651
+ /* for the readline function. */
1652
+ /******************************************/
1653
+ void ReadlineFunction(
1654
+ Environment *theEnv,
1655
+ UDFContext *context,
1656
+ UDFValue *returnValue)
1657
+ {
1658
+ char *buffer;
1659
+ size_t line_max = 0;
1660
+ const char *logicalName;
1661
+
1662
+ if (! UDFHasNextArgument(context))
1663
+ { logicalName = STDIN; }
1664
+ else
1665
+ {
1666
+ logicalName = GetLogicalName(context,STDIN);
1667
+ if (logicalName == NULL)
1668
+ {
1669
+ IllegalLogicalNameMessage(theEnv,"readline");
1670
+ SetHaltExecution(theEnv,true);
1671
+ SetEvaluationError(theEnv,true);
1672
+ returnValue->lexemeValue = FalseSymbol(theEnv);
1673
+ return;
1674
+ }
1675
+ }
1676
+
1677
+ if (QueryRouters(theEnv,logicalName) == false)
1678
+ {
1679
+ UnrecognizedRouterMessage(theEnv,logicalName);
1680
+ SetHaltExecution(theEnv,true);
1681
+ SetEvaluationError(theEnv,true);
1682
+ returnValue->lexemeValue = FalseSymbol(theEnv);
1683
+ return;
1684
+ }
1685
+
1686
+ if (strcmp(logicalName,STDIN) == 0)
1687
+ {
1688
+ RouterData(theEnv)->CommandBufferInputCount = 0;
1689
+ RouterData(theEnv)->InputUngets = 0;
1690
+ RouterData(theEnv)->AwaitingInput = true;
1691
+
1692
+ buffer = FillBuffer(theEnv,logicalName,&RouterData(theEnv)->CommandBufferInputCount,&line_max);
1693
+
1694
+ RouterData(theEnv)->CommandBufferInputCount = 0;
1695
+ RouterData(theEnv)->InputUngets = 0;
1696
+ RouterData(theEnv)->AwaitingInput = false;
1697
+ }
1698
+ else
1699
+ {
1700
+ size_t currentPos = 0;
1701
+
1702
+ buffer = FillBuffer(theEnv,logicalName,&currentPos,&line_max);
1703
+ }
1704
+
1705
+ if (GetHaltExecution(theEnv))
1706
+ {
1707
+ returnValue->lexemeValue = FalseSymbol(theEnv);
1708
+ if (buffer != NULL) rm(theEnv,buffer,sizeof (char) * line_max);
1709
+ return;
1710
+ }
1711
+
1712
+ if (buffer == NULL)
1713
+ {
1714
+ returnValue->lexemeValue = CreateSymbol(theEnv,"EOF");
1715
+ return;
1716
+ }
1717
+
1718
+ returnValue->lexemeValue = CreateString(theEnv,buffer);
1719
+ rm(theEnv,buffer,sizeof (char) * line_max);
1720
+ return;
1721
+ }
1722
+
1723
+ /*************************************************************/
1724
+ /* FillBuffer: Read characters from a specified logical name */
1725
+ /* and places them into a buffer until a carriage return */
1726
+ /* or end-of-file character is read. */
1727
+ /*************************************************************/
1728
+ static char *FillBuffer(
1729
+ Environment *theEnv,
1730
+ const char *logicalName,
1731
+ size_t *currentPosition,
1732
+ size_t *maximumSize)
1733
+ {
1734
+ int c;
1735
+ char *buf = NULL;
1736
+
1737
+ /*================================*/
1738
+ /* Read until end of line or eof. */
1739
+ /*================================*/
1740
+
1741
+ c = ReadRouter(theEnv,logicalName);
1742
+
1743
+ if (c == EOF)
1744
+ { return NULL; }
1745
+
1746
+ /*==================================*/
1747
+ /* Grab characters until cr or eof. */
1748
+ /*==================================*/
1749
+
1750
+ while ((c != '\n') && (c != '\r') && (c != EOF) &&
1751
+ (! GetHaltExecution(theEnv)))
1752
+ {
1753
+ buf = ExpandStringWithChar(theEnv,c,buf,currentPosition,maximumSize,*maximumSize+80);
1754
+ c = ReadRouter(theEnv,logicalName);
1755
+ }
1756
+
1757
+ /*==================*/
1758
+ /* Add closing EOS. */
1759
+ /*==================*/
1760
+
1761
+ buf = ExpandStringWithChar(theEnv,EOS,buf,currentPosition,maximumSize,*maximumSize+80);
1762
+ return (buf);
1763
+ }
1764
+
1765
+ /*****************************************/
1766
+ /* SetLocaleFunction: H/L access routine */
1767
+ /* for the set-locale function. */
1768
+ /*****************************************/
1769
+ void SetLocaleFunction(
1770
+ Environment *theEnv,
1771
+ UDFContext *context,
1772
+ UDFValue *returnValue)
1773
+ {
1774
+ UDFValue theArg;
1775
+
1776
+ /*=================================*/
1777
+ /* If there are no arguments, just */
1778
+ /* return the current locale. */
1779
+ /*=================================*/
1780
+
1781
+ if (! UDFHasNextArgument(context))
1782
+ {
1783
+ returnValue->value = IOFunctionData(theEnv)->locale;
1784
+ return;
1785
+ }
1786
+
1787
+ /*=================*/
1788
+ /* Get the locale. */
1789
+ /*=================*/
1790
+
1791
+ if (! UDFFirstArgument(context,STRING_BIT,&theArg))
1792
+ { return; }
1793
+
1794
+ /*=====================================*/
1795
+ /* Return the old value of the locale. */
1796
+ /*=====================================*/
1797
+
1798
+ returnValue->value = IOFunctionData(theEnv)->locale;
1799
+
1800
+ /*======================================================*/
1801
+ /* Change the value of the locale to the one specified. */
1802
+ /*======================================================*/
1803
+
1804
+ ReleaseLexeme(theEnv,IOFunctionData(theEnv)->locale);
1805
+ IOFunctionData(theEnv)->locale = theArg.lexemeValue;
1806
+ IncrementLexemeCount(IOFunctionData(theEnv)->locale);
1807
+ }
1808
+
1809
+ /******************************************/
1810
+ /* ReadNumberFunction: H/L access routine */
1811
+ /* for the read-number function. */
1812
+ /******************************************/
1813
+ void ReadNumberFunction(
1814
+ Environment *theEnv,
1815
+ UDFContext *context,
1816
+ UDFValue *returnValue)
1817
+ {
1818
+ struct token theToken;
1819
+ const char *logicalName = NULL;
1820
+
1821
+ /*======================================================*/
1822
+ /* Determine the logical name from which input is read. */
1823
+ /*======================================================*/
1824
+
1825
+ if (! UDFHasNextArgument(context))
1826
+ { logicalName = STDIN; }
1827
+ else
1828
+ {
1829
+ logicalName = GetLogicalName(context,STDIN);
1830
+ if (logicalName == NULL)
1831
+ {
1832
+ IllegalLogicalNameMessage(theEnv,"read");
1833
+ SetHaltExecution(theEnv,true);
1834
+ SetEvaluationError(theEnv,true);
1835
+ returnValue->lexemeValue = FalseSymbol(theEnv);
1836
+ return;
1837
+ }
1838
+ }
1839
+
1840
+ /*============================================*/
1841
+ /* Check to see that the logical name exists. */
1842
+ /*============================================*/
1843
+
1844
+ if (QueryRouters(theEnv,logicalName) == false)
1845
+ {
1846
+ UnrecognizedRouterMessage(theEnv,logicalName);
1847
+ SetHaltExecution(theEnv,true);
1848
+ SetEvaluationError(theEnv,true);
1849
+ returnValue->lexemeValue = FalseSymbol(theEnv);
1850
+ return;
1851
+ }
1852
+
1853
+ /*=======================================*/
1854
+ /* Collect input into string if the read */
1855
+ /* source is stdin, else just get token. */
1856
+ /*=======================================*/
1857
+
1858
+ if (strcmp(logicalName,STDIN) == 0)
1859
+ {
1860
+ RouterData(theEnv)->CommandBufferInputCount = 0;
1861
+ RouterData(theEnv)->InputUngets = 0;
1862
+ RouterData(theEnv)->AwaitingInput = true;
1863
+
1864
+ ReadNumber(theEnv,logicalName,&theToken,true);
1865
+
1866
+ RouterData(theEnv)->CommandBufferInputCount = 0;
1867
+ RouterData(theEnv)->InputUngets = 0;
1868
+ RouterData(theEnv)->AwaitingInput = false;
1869
+ }
1870
+ else
1871
+ { ReadNumber(theEnv,logicalName,&theToken,false); }
1872
+
1873
+ /*====================================================*/
1874
+ /* Copy the token to the return value data structure. */
1875
+ /*====================================================*/
1876
+
1877
+ if ((theToken.tknType == FLOAT_TOKEN) || (theToken.tknType == STRING_TOKEN) ||
1878
+ #if OBJECT_SYSTEM
1879
+ (theToken.tknType == INSTANCE_NAME_TOKEN) ||
1880
+ #endif
1881
+ (theToken.tknType == SYMBOL_TOKEN) || (theToken.tknType == INTEGER_TOKEN))
1882
+ { returnValue->value = theToken.value; }
1883
+ else if (theToken.tknType == STOP_TOKEN)
1884
+ { returnValue->value = CreateSymbol(theEnv,"EOF"); }
1885
+ else if (theToken.tknType == UNKNOWN_VALUE_TOKEN)
1886
+ { returnValue->lexemeValue = FalseSymbol(theEnv); }
1887
+ else
1888
+ { returnValue->value = CreateString(theEnv,theToken.printForm); }
1889
+
1890
+ return;
1891
+ }
1892
+
1893
+ /********************************************/
1894
+ /* ReadNumber: Special routine used by the */
1895
+ /* read-number function to read a number. */
1896
+ /********************************************/
1897
+ static void ReadNumber(
1898
+ Environment *theEnv,
1899
+ const char *logicalName,
1900
+ struct token *theToken,
1901
+ bool isStdin)
1902
+ {
1903
+ char *inputString;
1904
+ char *charPtr = NULL;
1905
+ size_t inputStringSize;
1906
+ int inchar;
1907
+ long long theLong;
1908
+ double theDouble;
1909
+ CLIPSLexeme *oldLocale;
1910
+
1911
+ theToken->tknType = STOP_TOKEN;
1912
+
1913
+ /*===========================================*/
1914
+ /* Initialize the variables used for storing */
1915
+ /* the characters retrieved from stdin. */
1916
+ /*===========================================*/
1917
+
1918
+ inputString = NULL;
1919
+ inputStringSize = 0;
1920
+ inchar = ReadRouter(theEnv,logicalName);
1921
+
1922
+ /*====================================*/
1923
+ /* Skip whitespace before any number. */
1924
+ /*====================================*/
1925
+
1926
+ while (isspace(inchar) && (inchar != EOF) &&
1927
+ (! GetHaltExecution(theEnv)))
1928
+ { inchar = ReadRouter(theEnv,logicalName); }
1929
+
1930
+ /*=============================================================*/
1931
+ /* Continue reading characters until whitespace is found again */
1932
+ /* (for anything other than stdin) or a CR/LF (for stdin). */
1933
+ /*=============================================================*/
1934
+
1935
+ while ((((! isStdin) && (! isspace(inchar))) ||
1936
+ (isStdin && (inchar != '\n') && (inchar != '\r'))) &&
1937
+ (inchar != EOF) &&
1938
+ (! GetHaltExecution(theEnv)))
1939
+ {
1940
+ inputString = ExpandStringWithChar(theEnv,inchar,inputString,&RouterData(theEnv)->CommandBufferInputCount,
1941
+ &inputStringSize,inputStringSize + 80);
1942
+ inchar = ReadRouter(theEnv,logicalName);
1943
+ }
1944
+
1945
+ /*===========================================*/
1946
+ /* Pressing control-c (or comparable action) */
1947
+ /* aborts the read-number function. */
1948
+ /*===========================================*/
1949
+
1950
+ if (GetHaltExecution(theEnv))
1951
+ {
1952
+ theToken->tknType = SYMBOL_TOKEN;
1953
+ theToken->value = FalseSymbol(theEnv);
1954
+ SetErrorValue(theEnv,&CreateSymbol(theEnv,"READ_ERROR")->header);
1955
+ if (inputStringSize > 0) rm(theEnv,inputString,inputStringSize);
1956
+ return;
1957
+ }
1958
+
1959
+ /*====================================================*/
1960
+ /* Return the EOF symbol if the end of file for stdin */
1961
+ /* has been encountered. This typically won't occur, */
1962
+ /* but is possible (for example by pressing control-d */
1963
+ /* in the UNIX operating system). */
1964
+ /*====================================================*/
1965
+
1966
+ if (inchar == EOF)
1967
+ {
1968
+ theToken->tknType = SYMBOL_TOKEN;
1969
+ theToken->value = CreateSymbol(theEnv,"EOF");
1970
+ if (inputStringSize > 0) rm(theEnv,inputString,inputStringSize);
1971
+ return;
1972
+ }
1973
+
1974
+ /*==================================================*/
1975
+ /* Open a string input source using the characters */
1976
+ /* retrieved from stdin and extract the first token */
1977
+ /* contained in the string. */
1978
+ /*==================================================*/
1979
+
1980
+ /*=======================================*/
1981
+ /* Change the locale so that numbers are */
1982
+ /* converted using the localized format. */
1983
+ /*=======================================*/
1984
+
1985
+ oldLocale = CreateSymbol(theEnv,setlocale(LC_NUMERIC,NULL));
1986
+ setlocale(LC_NUMERIC,IOFunctionData(theEnv)->locale->contents);
1987
+
1988
+ /*========================================*/
1989
+ /* Try to parse the number as a long. The */
1990
+ /* terminating character must either be */
1991
+ /* white space or the string terminator. */
1992
+ /*========================================*/
1993
+
1994
+ #if WIN_MVC
1995
+ theLong = _strtoi64(inputString,&charPtr,10);
1996
+ #else
1997
+ theLong = strtoll(inputString,&charPtr,10);
1998
+ #endif
1999
+
2000
+ if ((charPtr != inputString) &&
2001
+ (isspace(*charPtr) || (*charPtr == '\0')))
2002
+ {
2003
+ theToken->tknType = INTEGER_TOKEN;
2004
+ theToken->value = CreateInteger(theEnv,theLong);
2005
+ if (inputStringSize > 0) rm(theEnv,inputString,inputStringSize);
2006
+ setlocale(LC_NUMERIC,oldLocale->contents);
2007
+ return;
2008
+ }
2009
+
2010
+ /*==========================================*/
2011
+ /* Try to parse the number as a double. The */
2012
+ /* terminating character must either be */
2013
+ /* white space or the string terminator. */
2014
+ /*==========================================*/
2015
+
2016
+ theDouble = strtod(inputString,&charPtr);
2017
+ if ((charPtr != inputString) &&
2018
+ (isspace(*charPtr) || (*charPtr == '\0')))
2019
+ {
2020
+ theToken->tknType = FLOAT_TOKEN;
2021
+ theToken->value = CreateFloat(theEnv,theDouble);
2022
+ if (inputStringSize > 0) rm(theEnv,inputString,inputStringSize);
2023
+ setlocale(LC_NUMERIC,oldLocale->contents);
2024
+ return;
2025
+ }
2026
+
2027
+ /*============================================*/
2028
+ /* Restore the "C" locale so that any parsing */
2029
+ /* of numbers uses the C format. */
2030
+ /*============================================*/
2031
+
2032
+ setlocale(LC_NUMERIC,oldLocale->contents);
2033
+
2034
+ /*=========================================*/
2035
+ /* Return "*** READ ERROR ***" to indicate */
2036
+ /* a number was not successfully parsed. */
2037
+ /*=========================================*/
2038
+
2039
+ theToken->tknType = SYMBOL_TOKEN;
2040
+ theToken->value = FalseSymbol(theEnv);
2041
+ SetErrorValue(theEnv,&CreateSymbol(theEnv,"READ_ERROR")->header);
2042
+ }
2043
+
2044
+ #endif
2045
+