PageRenderTime 59ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/Classes/common-42s/core_globals.cc

https://bitbucket.org/byronvf/42x
C++ | 3488 lines | 3466 code | 6 blank | 16 comment | 0 complexity | f95c7bc6f32c9f486f19b1de23ead199 MD5 | raw file
Possible License(s): GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. /*****************************************************************************
  2. * Free42 -- an HP-42S calculator simulator
  3. * Copyright (C) 2004-2011 Thomas Okken
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License, version 2,
  7. * as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, see http://www.gnu.org/licenses/.
  16. *****************************************************************************/
  17. #include <stdlib.h>
  18. #include "core_globals.h"
  19. #include "core_commands2.h"
  20. #include "core_commands4.h"
  21. #include "core_display.h"
  22. #include "core_helpers.h"
  23. #include "core_main.h"
  24. #include "core_math1.h"
  25. #include "core_tables.h"
  26. #include "core_variables.h"
  27. #include "undo.h"
  28. #include "shell.h"
  29. error_spec errors[] = {
  30. { /* NONE */ NULL, 0 },
  31. { /* ALPHA_DATA_IS_INVALID */ "Alpha Data Is Invalid", 21 },
  32. { /* INSUFFICIENT_MEMORY */ "Insufficient Memory", 19 },
  33. { /* NOT_YET_IMPLEMENTED */ "Not Yet Implemented", 19 },
  34. { /* OUT_OF_RANGE */ "Out of Range", 12 },
  35. { /* DIVIDE_BY_0 */ "Divide by 0", 11 },
  36. { /* INVALID_TYPE */ "Invalid Type", 12 },
  37. { /* INVALID_DATA */ "Invalid Data", 12 },
  38. { /* DIMENSION_ERROR */ "Dimension Error", 15 },
  39. { /* SIZE_ERROR */ "Size Error", 10 },
  40. { /* INTERNAL_ERROR */ "Internal Error", 14 },
  41. { /* NONEXISTENT */ "Nonexistent", 11 },
  42. { /* RESTRICTED_OPERATION */ "Restricted Operation", 20 },
  43. { /* YES */ "Yes", 3 },
  44. { /* NO */ "No", 2 },
  45. { /* STOP */ NULL, 0 },
  46. { /* LABEL_NOT_FOUND */ "Label Not Found", 15 },
  47. { /* NO_REAL_VARIABLES */ "No Real Variables", 17 },
  48. { /* NO_COMPLEX_VARIABLES */ "No Complex Variables", 20 },
  49. { /* NO_MATRIX_VARIABLES */ "No Matrix Variables", 19 },
  50. { /* NO_MENU_VARIABLES */ "No Menu Variables", 17 },
  51. { /* STAT_MATH_ERROR */ "Stat Math Error", 15 },
  52. { /* INVALID_FORECAST_MODEL */ "Invalid Forecast Model", 22 },
  53. { /* SOLVE_INTEG_RTN_LOST */ "Solve/Integ RTN Lost", 20 },
  54. { /* SINGULAR_MATRIX */ "Singular Matrix", 15 },
  55. { /* SOLVE_SOLVE */ "Solve(Solve)", 12 },
  56. { /* INTEG_INTEG */ "Integ(Integ)", 12 },
  57. { /* RUN */ NULL, 0 },
  58. { /* INTERRUPTED */ "Interrupted", 11 },
  59. { /* PRINTING_IS_DISABLED */ "Printing Is Disabled", 20 },
  60. { /* INTERRUPTIBLE */ NULL, 0 },
  61. { /* NO_VARIABLES */ "No Variables", 12 }
  62. };
  63. menu_spec menus[] = {
  64. { /* MENU_ALPHA1 */ MENU_NONE, MENU_ALPHA2, MENU_ALPHA2,
  65. { { MENU_ALPHA_ABCDE1, 5, "ABCDE" },
  66. { MENU_ALPHA_FGHI, 4, "FGHI" },
  67. { MENU_ALPHA_JKLM, 4, "JKLM" },
  68. { MENU_ALPHA_NOPQ1, 4, "NOPQ" },
  69. { MENU_ALPHA_RSTUV1, 5, "RSTUV" },
  70. { MENU_ALPHA_WXYZ, 4, "WXYZ" } } },
  71. { /* MENU_ALPHA2 */ MENU_NONE, MENU_ALPHA1, MENU_ALPHA1,
  72. { { MENU_ALPHA_PAREN, 5, "( [ {" },
  73. { MENU_ALPHA_ARROW, 3, "\020^\016" },
  74. { MENU_ALPHA_COMP, 5, "< = >" },
  75. { MENU_ALPHA_MATH, 4, "MATH" },
  76. { MENU_ALPHA_PUNC1, 4, "PUNC" },
  77. { MENU_ALPHA_MISC1, 4, "MISC" } } },
  78. { /* MENU_ALPHA_ABCDE1 */ MENU_ALPHA1, MENU_ALPHA_ABCDE2, MENU_ALPHA_ABCDE2,
  79. { { MENU_NONE, 1, "A" },
  80. { MENU_NONE, 1, "B" },
  81. { MENU_NONE, 1, "C" },
  82. { MENU_NONE, 1, "D" },
  83. { MENU_NONE, 1, "E" },
  84. { MENU_NONE, 1, " " } } },
  85. { /* MENU_ALPHA_ABCDE2 */ MENU_ALPHA1, MENU_ALPHA_ABCDE1, MENU_ALPHA_ABCDE1,
  86. { { MENU_NONE, 1, "\026" },
  87. { MENU_NONE, 1, "\024" },
  88. { MENU_NONE, 1, "\031" },
  89. { MENU_NONE, 1, " " },
  90. { MENU_NONE, 1, " " },
  91. { MENU_NONE, 1, " " } } },
  92. { /* MENU_ALPHA_FGHI */ MENU_ALPHA1, MENU_NONE, MENU_NONE,
  93. { { MENU_NONE, 1, "F" },
  94. { MENU_NONE, 1, "G" },
  95. { MENU_NONE, 1, "H" },
  96. { MENU_NONE, 1, "I" },
  97. { MENU_NONE, 1, " " },
  98. { MENU_NONE, 1, " " } } },
  99. { /* MENU_ALPHA_JKLM */ MENU_ALPHA1, MENU_NONE, MENU_NONE,
  100. { { MENU_NONE, 1, "J" },
  101. { MENU_NONE, 1, "K" },
  102. { MENU_NONE, 1, "L" },
  103. { MENU_NONE, 1, "M" },
  104. { MENU_NONE, 1, " " },
  105. { MENU_NONE, 1, " " } } },
  106. { /* MENU_ALPHA_NOPQ1 */ MENU_ALPHA1, MENU_ALPHA_NOPQ2, MENU_ALPHA_NOPQ2,
  107. { { MENU_NONE, 1, "N" },
  108. { MENU_NONE, 1, "O" },
  109. { MENU_NONE, 1, "P" },
  110. { MENU_NONE, 1, "Q" },
  111. { MENU_NONE, 1, " " },
  112. { MENU_NONE, 1, " " } } },
  113. { /* MENU_ALPHA_NOPQ2 */ MENU_ALPHA1, MENU_ALPHA_NOPQ1, MENU_ALPHA_NOPQ1,
  114. { { MENU_NONE, 1, "\025" },
  115. { MENU_NONE, 1, "\034" },
  116. { MENU_NONE, 1, " " },
  117. { MENU_NONE, 1, " " },
  118. { MENU_NONE, 1, " " },
  119. { MENU_NONE, 1, " " } } },
  120. { /* MENU_ALPHA_RSTUV1 */ MENU_ALPHA1, MENU_ALPHA_RSTUV2, MENU_ALPHA_RSTUV2,
  121. { { MENU_NONE, 1, "R" },
  122. { MENU_NONE, 1, "S" },
  123. { MENU_NONE, 1, "T" },
  124. { MENU_NONE, 1, "U" },
  125. { MENU_NONE, 1, "V" },
  126. { MENU_NONE, 1, " " } } },
  127. { /* MENU_ALPHA_RSTUV2 */ MENU_ALPHA1, MENU_ALPHA_RSTUV1, MENU_ALPHA_RSTUV1,
  128. { { MENU_NONE, 1, " " },
  129. { MENU_NONE, 1, " " },
  130. { MENU_NONE, 1, " " },
  131. { MENU_NONE, 1, "\035" },
  132. { MENU_NONE, 1, " " },
  133. { MENU_NONE, 1, " " } } },
  134. { /* MENU_ALPHA_WXYZ */ MENU_ALPHA1, MENU_NONE, MENU_NONE,
  135. { { MENU_NONE, 1, "W" },
  136. { MENU_NONE, 1, "X" },
  137. { MENU_NONE, 1, "Y" },
  138. { MENU_NONE, 1, "Z" },
  139. { MENU_NONE, 1, " " },
  140. { MENU_NONE, 1, " " } } },
  141. { /* MENU_ALPHA_PAREN */ MENU_ALPHA2, MENU_NONE, MENU_NONE,
  142. { { MENU_NONE, 1, "(" },
  143. { MENU_NONE, 1, ")" },
  144. { MENU_NONE, 1, "[" },
  145. { MENU_NONE, 1, "]" },
  146. { MENU_NONE, 1, "{" },
  147. { MENU_NONE, 1, "}" } } },
  148. { /* MENU_ALPHA_ARROW */ MENU_ALPHA2, MENU_NONE, MENU_NONE,
  149. { { MENU_NONE, 1, "\020" },
  150. { MENU_NONE, 1, "^" },
  151. { MENU_NONE, 1, "\016" },
  152. { MENU_NONE, 1, "\017" },
  153. { MENU_NONE, 1, " " },
  154. { MENU_NONE, 1, " " } } },
  155. { /* MENU_ALPHA_COMP */ MENU_ALPHA2, MENU_NONE, MENU_NONE,
  156. { { MENU_NONE, 1, "=" },
  157. { MENU_NONE, 1, "\014" },
  158. { MENU_NONE, 1, "<" },
  159. { MENU_NONE, 1, ">" },
  160. { MENU_NONE, 1, "\011" },
  161. { MENU_NONE, 1, "\013" } } },
  162. { /* MENU_ALPHA_MATH */ MENU_ALPHA2, MENU_NONE, MENU_NONE,
  163. { { MENU_NONE, 1, "\005" },
  164. { MENU_NONE, 1, "\003" },
  165. { MENU_NONE, 1, "\002" },
  166. { MENU_NONE, 1, "\027" },
  167. { MENU_NONE, 1, "\023" },
  168. { MENU_NONE, 1, "\021" } } },
  169. { /* MENU_ALPHA_PUNC1 */ MENU_ALPHA2, MENU_ALPHA_PUNC2, MENU_ALPHA_PUNC2,
  170. { { MENU_NONE, 1, "," },
  171. { MENU_NONE, 1, ";" },
  172. { MENU_NONE, 1, ":" },
  173. { MENU_NONE, 1, "!" },
  174. { MENU_NONE, 1, "?" },
  175. { MENU_NONE, 1, "\"" } } },
  176. { /* MENU_ALPHA_PUNC2 */ MENU_ALPHA2, MENU_ALPHA_PUNC1, MENU_ALPHA_PUNC1,
  177. { { MENU_NONE, 1, "\032" },
  178. { MENU_NONE, 1, "_" },
  179. { MENU_NONE, 1, "`" },
  180. { MENU_NONE, 1, "'" },
  181. { MENU_NONE, 1, "\010" },
  182. { MENU_NONE, 1, "\012" } } },
  183. { /* MENU_ALPHA_MISC1 */ MENU_ALPHA2, MENU_ALPHA_MISC2, MENU_ALPHA_MISC2,
  184. { { MENU_NONE, 1, "$" },
  185. { MENU_NONE, 1, "*" },
  186. { MENU_NONE, 1, "#" },
  187. { MENU_NONE, 1, "/" },
  188. { MENU_NONE, 1, "\037" },
  189. { MENU_NONE, 1, " " } } },
  190. { /* MENU_ALPHA_MISC2 */ MENU_ALPHA2, MENU_ALPHA_MISC1, MENU_ALPHA_MISC1,
  191. { { MENU_NONE, 1, "\022" },
  192. { MENU_NONE, 1, "&" },
  193. { MENU_NONE, 1, "@" },
  194. { MENU_NONE, 1, "\\" },
  195. { MENU_NONE, 1, "~" },
  196. { MENU_NONE, 1, "|" } } },
  197. { /* MENU_ST */ MENU_NONE, MENU_NONE, MENU_NONE,
  198. { { MENU_NONE, 4, "ST L" },
  199. { MENU_NONE, 4, "ST X" },
  200. { MENU_NONE, 4, "ST Y" },
  201. { MENU_NONE, 4, "ST Z" },
  202. { MENU_NONE, 4, "ST T" },
  203. { MENU_NONE, 0, "" } } },
  204. { /* MENU_IND_ST */ MENU_NONE, MENU_NONE, MENU_NONE,
  205. { { MENU_NONE, 3, "IND" },
  206. { MENU_NONE, 4, "ST L" },
  207. { MENU_NONE, 4, "ST X" },
  208. { MENU_NONE, 4, "ST Y" },
  209. { MENU_NONE, 4, "ST Z" },
  210. { MENU_NONE, 4, "ST T" } } },
  211. { /* MENU_IND */ MENU_NONE, MENU_NONE, MENU_NONE,
  212. { { MENU_NONE, 3, "IND" },
  213. { MENU_NONE, 0, "" },
  214. { MENU_NONE, 0, "" },
  215. { MENU_NONE, 0, "" },
  216. { MENU_NONE, 0, "" },
  217. { MENU_NONE, 0, "" } } },
  218. { /* MENU_MODES1 */ MENU_NONE, MENU_MODES2, MENU_MODES2,
  219. { { 0x2000 + CMD_DEG, 0, "" },
  220. { 0x2000 + CMD_RAD, 0, "" },
  221. { 0x2000 + CMD_GRAD, 0, "" },
  222. { 0x1000 + CMD_NULL, 0, "" },
  223. { 0x2000 + CMD_RECT, 0, "" },
  224. { 0x2000 + CMD_POLAR, 0, "" } } },
  225. { /* MENU_MODES2 */ MENU_NONE, MENU_MODES1, MENU_MODES1,
  226. { { 0x1000 + CMD_SIZE, 0, "" },
  227. { 0x2000 + CMD_QUIET, 0, "" },
  228. { 0x2000 + CMD_CPXRES, 0, "" },
  229. { 0x2000 + CMD_REALRES, 0, "" },
  230. { 0x2000 + CMD_KEYASN, 0, "" },
  231. { 0x2000 + CMD_LCLBL, 0, "" } } },
  232. { /* MENU_DISP */ MENU_NONE, MENU_NONE, MENU_NONE,
  233. { { 0x2000 + CMD_FIX, 0, "" },
  234. { 0x2000 + CMD_SCI, 0, "" },
  235. { 0x2000 + CMD_ENG, 0, "" },
  236. { 0x2000 + CMD_ALL, 0, "" },
  237. { 0x2000 + CMD_RDXDOT, 0, "" },
  238. { 0x2000 + CMD_RDXCOMMA, 0, "" } } },
  239. #ifdef BIGSTACK
  240. { /* MENU_CLEAR1 */ MENU_NONE, MENU_CLEAR2, MENU_CLEAR3,
  241. #else
  242. { /* MENU_CLEAR1 */ MENU_NONE, MENU_CLEAR2, MENU_CLEAR2,
  243. #endif
  244. { { 0x1000 + CMD_CLSIGMA, 0, "" },
  245. { 0x1000 + CMD_CLP, 0, "" },
  246. { 0x1000 + CMD_CLV, 0, "" },
  247. { 0x1000 + CMD_CLST, 0, "" },
  248. { 0x1000 + CMD_CLA, 0, "" },
  249. { 0x1000 + CMD_CLX, 0, "" } } },
  250. #ifdef BIGSTACK
  251. { /* MENU_CLEAR2 */ MENU_NONE, MENU_CLEAR3, MENU_CLEAR1,
  252. #else
  253. { /* MENU_CLEAR2 */ MENU_NONE, MENU_CLEAR1, MENU_CLEAR1,
  254. #endif
  255. { { 0x1000 + CMD_CLRG, 0, "" },
  256. { 0x1000 + CMD_DEL, 0, "" },
  257. { 0x1000 + CMD_CLKEYS, 0, "" },
  258. { 0x1000 + CMD_CLLCD, 0, "" },
  259. { 0x1000 + CMD_CLMENU, 0, "" },
  260. { 0x1000 + CMD_CLALLa, 0, "" } } },
  261. { /* MENU_CONVERT1 */ MENU_NONE, MENU_CONVERT2, MENU_CONVERT4,
  262. { { 0, 0, "" },
  263. { 0, 0, "" },
  264. { 0, 0, "" },
  265. { 0, 0, "" },
  266. { 0, 0, "" },
  267. { 0, 0, "" } } },
  268. { /* MENU_CONVERT2 */ MENU_NONE, MENU_CONVERT3, MENU_CONVERT1,
  269. { { 0 , 0, "" },
  270. { 0, 0, "" },
  271. { 0, 0, "" },
  272. { 0, 0, "" },
  273. { 0, 0, "" },
  274. { 0, 0, "" } } },
  275. { /* MENU_FLAGS */ MENU_NONE, MENU_NONE, MENU_NONE,
  276. { { 0x1000 + CMD_SF, 0, "" },
  277. { 0x1000 + CMD_CF, 0, "" },
  278. { 0x1000 + CMD_FS_T, 0, "" },
  279. { 0x1000 + CMD_FC_T, 0, "" },
  280. { 0x1000 + CMD_FSC_T, 0, "" },
  281. { 0x1000 + CMD_FCC_T, 0, "" } } },
  282. { /* MENU_PROB */ MENU_NONE, MENU_NONE, MENU_NONE,
  283. { { 0x1000 + CMD_COMB, 0, "" },
  284. { 0x1000 + CMD_PERM, 0, "" },
  285. { 0x1000 + CMD_FACT, 0, "" },
  286. { 0x1000 + CMD_GAMMA, 0, "" },
  287. { 0x1000 + CMD_RAN, 0, "" },
  288. { 0x1000 + CMD_SEED, 0, "" } } },
  289. { /* MENU_CUSTOM1 */ MENU_NONE, MENU_CUSTOM2, MENU_CUSTOM3,
  290. { { 0, 0, "" },
  291. { 0, 0, "" },
  292. { 0, 0, "" },
  293. { 0, 0, "" },
  294. { 0, 0, "" },
  295. { 0, 0, "" } } },
  296. { /* MENU_CUSTOM2 */ MENU_NONE, MENU_CUSTOM3, MENU_CUSTOM1,
  297. { { 0, 0, "" },
  298. { 0, 0, "" },
  299. { 0, 0, "" },
  300. { 0, 0, "" },
  301. { 0, 0, "" },
  302. { 0, 0, "" } } },
  303. { /* MENU_CUSTOM3 */ MENU_NONE, MENU_CUSTOM1, MENU_CUSTOM2,
  304. { { 0, 0, "" },
  305. { 0, 0, "" },
  306. { 0, 0, "" },
  307. { 0, 0, "" },
  308. { 0, 0, "" },
  309. { 0, 0, "" } } },
  310. { /* MENU_PGM_FCN1 */ MENU_NONE, MENU_PGM_FCN2, MENU_PGM_FCN4,
  311. { { 0x1000 + CMD_LBL, 0, "" },
  312. { 0x1000 + CMD_RTN, 0, "" },
  313. { 0x1000 + CMD_INPUT, 0, "" },
  314. { 0x1000 + CMD_VIEW, 0, "" },
  315. { 0x1000 + CMD_AVIEW, 0, "" },
  316. { 0x1000 + CMD_XEQ, 0, "" } } },
  317. { /* MENU_PGM_FCN2 */ MENU_NONE, MENU_PGM_FCN3, MENU_PGM_FCN1,
  318. { { MENU_PGM_XCOMP0, 3, "X?0" },
  319. { MENU_PGM_XCOMPY, 3, "X?Y" },
  320. { 0x1000 + CMD_PROMPT, 0, "" },
  321. { 0x1000 + CMD_PSE, 0, "" },
  322. { 0x1000 + CMD_ISG, 0, "" },
  323. { 0x1000 + CMD_DSE, 0, "" } } },
  324. { /* MENU_PGM_FCN3 */ MENU_NONE, MENU_PGM_FCN4, MENU_PGM_FCN2,
  325. { { 0x1000 + CMD_AIP, 0, "" },
  326. { 0x1000 + CMD_XTOA, 0, "" },
  327. { 0x1000 + CMD_AGRAPH, 0, "" },
  328. { 0x1000 + CMD_PIXEL, 0, "" },
  329. { 0x1000 + CMD_BEEP, 0, "" },
  330. { 0x1000 + CMD_TONE, 0, "" } } },
  331. { /* MENU_PGM_FCN4 */ MENU_NONE, MENU_PGM_FCN1, MENU_PGM_FCN3,
  332. { { 0x1000 + CMD_MVAR, 0, "" },
  333. { 0x1000 + CMD_VARMENU, 0, "" },
  334. { 0x1000 + CMD_GETKEY, 0, "" },
  335. { 0x1000 + CMD_MENU, 0, "" },
  336. { 0x1000 + CMD_KEYG, 0, "" },
  337. { 0x1000 + CMD_KEYX, 0, "" } } },
  338. { /* MENU_PGM_XCOMP0 */ MENU_PGM_FCN2, MENU_NONE, MENU_NONE,
  339. { { 0x1000 + CMD_X_EQ_0, 0, "" },
  340. { 0x1000 + CMD_X_NE_0, 0, "" },
  341. { 0x1000 + CMD_X_LT_0, 0, "" },
  342. { 0x1000 + CMD_X_GT_0, 0, "" },
  343. { 0x1000 + CMD_X_LE_0, 0, "" },
  344. { 0x1000 + CMD_X_GE_0, 0, "" } } },
  345. { /* MENU_PGM_XCOMPY */ MENU_PGM_FCN2, MENU_NONE, MENU_NONE,
  346. { { 0x1000 + CMD_X_EQ_Y, 0, "" },
  347. { 0x1000 + CMD_X_NE_Y, 0, "" },
  348. { 0x1000 + CMD_X_LT_Y, 0, "" },
  349. { 0x1000 + CMD_X_GT_Y, 0, "" },
  350. { 0x1000 + CMD_X_LE_Y, 0, "" },
  351. { 0x1000 + CMD_X_GE_Y, 0, "" } } },
  352. { /* MENU_PRINT1 */ MENU_NONE, MENU_PRINT2, MENU_PRINT3,
  353. { { 0x1000 + CMD_PRSIGMA, 0, "" },
  354. { 0x1000 + CMD_PRP, 0, "" },
  355. { 0x1000 + CMD_PRV, 0, "" },
  356. { 0x1000 + CMD_PRSTK, 0, "" },
  357. { 0x1000 + CMD_PRA, 0, "" },
  358. { 0x1000 + CMD_PRX, 0, "" } } },
  359. { /* MENU_PRINT2 */ MENU_NONE, MENU_PRINT3, MENU_PRINT1,
  360. { { 0x1000 + CMD_PRUSR, 0, "" },
  361. { 0x1000 + CMD_LIST, 0, "" },
  362. { 0x1000 + CMD_ADV, 0, "" },
  363. { 0x1000 + CMD_PRLCD, 0, "" },
  364. { 0x1000 + CMD_NULL, 0, "" },
  365. { 0x1000 + CMD_DELAY, 0, "" } } },
  366. { /* MENU_PRINT3 */ MENU_NONE, MENU_PRINT1, MENU_PRINT2,
  367. { { 0x2000 + CMD_PON, 0, "" },
  368. { 0x2000 + CMD_POFF, 0, "" },
  369. { 0x1000 + CMD_NULL, 0, "" },
  370. { 0x2000 + CMD_MAN, 0, "" },
  371. { 0x2000 + CMD_NORM, 0, "" },
  372. { 0x2000 + CMD_TRACE, 0, "" } } },
  373. { /* MENU_TOP_FCN */ MENU_NONE, MENU_NONE, MENU_NONE,
  374. { { 0x1000 + CMD_SIGMAADD, 0, "" },
  375. { 0x1000 + CMD_INV, 0, "" },
  376. { 0x1000 + CMD_SQRT, 0, "" },
  377. { 0x1000 + CMD_LOG, 0, "" },
  378. { 0x1000 + CMD_LN, 0, "" },
  379. { 0x1000 + CMD_XEQ, 0, "" } } },
  380. { /* MENU_CATALOG */ MENU_NONE, MENU_NONE, MENU_NONE,
  381. { { 0, 0, "" },
  382. { 0, 0, "" },
  383. { 0, 0, "" },
  384. { 0, 0, "" },
  385. { 0, 0, "" },
  386. { 0, 0, "" } } },
  387. { /* MENU_BLANK */ MENU_NONE, MENU_NONE, MENU_NONE,
  388. { { 0, 0, "" },
  389. { 0, 0, "" },
  390. { 0, 0, "" },
  391. { 0, 0, "" },
  392. { 0, 0, "" },
  393. { 0, 0, "" } } },
  394. { /* MENU_PROGRAMMABLE */ MENU_NONE, MENU_NONE, MENU_NONE,
  395. { { 0, 0, "" },
  396. { 0, 0, "" },
  397. { 0, 0, "" },
  398. { 0, 0, "" },
  399. { 0, 0, "" },
  400. { 0, 0, "" } } },
  401. { /* MENU_VARMENU */ MENU_NONE, MENU_NONE, MENU_NONE,
  402. { { 0, 0, "" },
  403. { 0, 0, "" },
  404. { 0, 0, "" },
  405. { 0, 0, "" },
  406. { 0, 0, "" },
  407. { 0, 0, "" } } },
  408. { /* MENU_STAT1 */ MENU_NONE, MENU_STAT2, MENU_STAT2,
  409. { { 0x1000 + CMD_SIGMAADD, 0, "" },
  410. { 0x1000 + CMD_SUM, 0, "" },
  411. { 0x1000 + CMD_MEAN, 0, "" },
  412. { 0x1000 + CMD_WMEAN, 0, "" },
  413. { 0x1000 + CMD_SDEV, 0, "" },
  414. { MENU_STAT_CFIT, 4, "CFIT" } } },
  415. { /* MENU_STAT2 */ MENU_NONE, MENU_STAT1, MENU_STAT1,
  416. { { 0x2000 + CMD_ALLSIGMA, 0, "" },
  417. { 0x2000 + CMD_LINSIGMA, 0, "" },
  418. { 0x1000 + CMD_NULL, 0, "" },
  419. { 0x1000 + CMD_NULL, 0, "" },
  420. { 0x1000 + CMD_SIGMAREG, 0, "" },
  421. { 0x1000 + CMD_SIGMAREG_T, 0, "" } } },
  422. { /* MENU_STAT_CFIT */ MENU_STAT1, MENU_NONE, MENU_NONE,
  423. { { 0x1000 + CMD_FCSTX, 0, "" },
  424. { 0x1000 + CMD_FCSTY, 0, "" },
  425. { 0x1000 + CMD_SLOPE, 0, "" },
  426. { 0x1000 + CMD_YINT, 0, "" },
  427. { 0x1000 + CMD_CORR, 0, "" },
  428. { MENU_STAT_MODL, 4, "MODL" } } },
  429. { /* MENU_STAT_MODL */ MENU_STAT_CFIT, MENU_NONE, MENU_NONE,
  430. { { 0x2000 + CMD_LINF, 0, "" },
  431. { 0x2000 + CMD_LOGF, 0, "" },
  432. { 0x2000 + CMD_EXPF, 0, "" },
  433. { 0x2000 + CMD_PWRF, 0, "" },
  434. { 0x1000 + CMD_NULL, 0, "" },
  435. { 0x1000 + CMD_BEST, 0, "" } } },
  436. { /* MENU_MATRIX1 */ MENU_NONE, MENU_MATRIX2, MENU_MATRIX3,
  437. { { 0x1000 + CMD_NEWMAT, 0, "" },
  438. { 0x1000 + CMD_INVRT, 0, "" },
  439. { 0x1000 + CMD_DET, 0, "" },
  440. { 0x1000 + CMD_TRANS, 0, "" },
  441. { 0x1000 + CMD_SIMQ, 0, "" },
  442. { 0x1000 + CMD_EDIT, 0, "" } } },
  443. { /* MENU_MATRIX2 */ MENU_NONE, MENU_MATRIX3, MENU_MATRIX1,
  444. { { 0x1000 + CMD_DOT, 0, "" },
  445. { 0x1000 + CMD_CROSS, 0, "" },
  446. { 0x1000 + CMD_UVEC, 0, "" },
  447. { 0x1000 + CMD_DIM, 0, "" },
  448. { 0x1000 + CMD_INDEX, 0, "" },
  449. { 0x1000 + CMD_EDITN, 0, "" } } },
  450. { /* MENU_MATRIX3 */ MENU_NONE, MENU_MATRIX1, MENU_MATRIX2,
  451. { { 0x1000 + CMD_STOIJ, 0, "" },
  452. { 0x1000 + CMD_RCLIJ, 0, "" },
  453. { 0x1000 + CMD_STOEL, 0, "" },
  454. { 0x1000 + CMD_RCLEL, 0, "" },
  455. { 0x1000 + CMD_PUTM, 0, "" },
  456. { 0x1000 + CMD_GETM, 0, "" } } },
  457. { /* MENU_MATRIX_SIMQ */ MENU_MATRIX1, MENU_NONE, MENU_NONE,
  458. { { 0x1000 + CMD_MATA, 0, "" },
  459. { 0x1000 + CMD_MATB, 0, "" },
  460. { 0x1000 + CMD_MATX, 0, "" },
  461. { 0x1000 + CMD_NULL, 0, "" },
  462. { 0x1000 + CMD_NULL, 0, "" },
  463. { 0x1000 + CMD_NULL, 0, "" } } },
  464. { /* MENU_MATRIX_EDIT1 */ MENU_NONE, MENU_MATRIX_EDIT2, MENU_MATRIX_EDIT2,
  465. { { 0x1000 + CMD_LEFT, 0, "" },
  466. { 0x1000 + CMD_OLD, 0, "" },
  467. { 0x1000 + CMD_UP, 0, "" },
  468. { 0x1000 + CMD_DOWN, 0, "" },
  469. { 0x1000 + CMD_GOTOROW, 0, "" },
  470. { 0x1000 + CMD_RIGHT, 0, "" } } },
  471. { /* MENU_MATRIX_EDIT2 */ MENU_NONE, MENU_MATRIX_EDIT1, MENU_MATRIX_EDIT1,
  472. { { 0x1000 + CMD_INSR, 0, "" },
  473. { 0x1000 + CMD_NULL, 0, "" },
  474. { 0x1000 + CMD_DELR, 0, "" },
  475. { 0x1000 + CMD_NULL, 0, "" },
  476. { 0x2000 + CMD_WRAP, 0, "" },
  477. { 0x2000 + CMD_GROW, 0, "" } } },
  478. { /* MENU_BASE */ MENU_NONE, MENU_NONE, MENU_NONE,
  479. { { 0x1000 + CMD_A_THRU_F, 0, "" },
  480. { 0x2000 + CMD_HEXM, 0, "" },
  481. { 0x2000 + CMD_DECM, 0, "" },
  482. { 0x2000 + CMD_OCTM, 0, "" },
  483. { 0x2000 + CMD_BINM, 0, "" },
  484. { MENU_BASE_LOGIC, 5, "LOGIC" } } },
  485. { /* MENU_BASE_A_THRU_F */ MENU_BASE, MENU_NONE, MENU_NONE,
  486. { { 0x4000, 1, "A" },
  487. { 0x4000, 1, "B" },
  488. { 0x4000, 1, "C" },
  489. { 0x4000, 1, "D" },
  490. { 0x4000, 1, "E" },
  491. { 0x4000, 1, "F" } } },
  492. { /* MENU_BASE_LOGIC */ MENU_BASE, MENU_NONE, MENU_NONE,
  493. { { 0x1000 + CMD_AND, 0, "" },
  494. { 0x1000 + CMD_OR, 0, "" },
  495. { 0x1000 + CMD_XOR, 0, "" },
  496. { 0x1000 + CMD_NOT, 0, "" },
  497. { 0x1000 + CMD_BIT_T, 0, "" },
  498. { 0x1000 + CMD_ROTXY, 0, "" } } },
  499. { /* MENU_SOLVE */ MENU_NONE, MENU_NONE, MENU_NONE,
  500. { { 0x1000 + CMD_MVAR, 0, "" },
  501. { 0x1000 + CMD_NULL, 0, "" },
  502. { 0x1000 + CMD_NULL, 0, "" },
  503. { 0x1000 + CMD_NULL, 0, "" },
  504. { 0x1000 + CMD_PGMSLV, 0, "" },
  505. { 0x1000 + CMD_SOLVE, 0, "" } } },
  506. { /* MENU_INTEG */ MENU_NONE, MENU_NONE, MENU_NONE,
  507. { { 0x1000 + CMD_MVAR, 0, "" },
  508. { 0x1000 + CMD_NULL, 0, "" },
  509. { 0x1000 + CMD_NULL, 0, "" },
  510. { 0x1000 + CMD_NULL, 0, "" },
  511. { 0x1000 + CMD_PGMINT, 0, "" },
  512. { 0x1000 + CMD_INTEG, 0, "" } } },
  513. { /* MENU_INTEG_PARAMS */ MENU_NONE, MENU_NONE, MENU_NONE,
  514. { { 0, 4, "LLIM" },
  515. { 0, 4, "ULIM" },
  516. { 0, 3, "ACC" },
  517. { 0x1000 + CMD_NULL, 0, "" },
  518. { 0x1000 + CMD_NULL, 0, "" },
  519. { 0, 1, "\003" } } },
  520. #ifdef BIGSTACK
  521. { /* MENU_CLEAR3 */ MENU_NONE, MENU_CLEAR1, MENU_CLEAR2,
  522. { { 0x1000 + CMD_DROP, 0, "" },
  523. { 0x1000 + CMD_UNDO, 0, "" },
  524. { 0x1000 + CMD_REDO, 0, "" },
  525. { 0x1000 + CMD_NULL, 0, "" },
  526. { 0x1000 + CMD_NULL, 0, "" },
  527. { 0x1000 + CMD_NULL, 0, "" } } },
  528. { /* MENU_CONVERT3 */ MENU_NONE, MENU_CONVERT4, MENU_CONVERT2,
  529. { { 0x1000 + CMD_TO_DEG, 0, "" },
  530. { 0x1000 + CMD_TO_RAD, 0, "" },
  531. { 0x1000 + CMD_TO_HR, 0, "" },
  532. { 0x1000 + CMD_TO_HMS, 0, "" },
  533. { 0x1000 + CMD_TO_REC, 0, "" },
  534. { 0x1000 + CMD_TO_POL, 0, "" } } },
  535. { /* MENU_CONVERT4 */ MENU_NONE, MENU_CONVERT1, MENU_CONVERT3,
  536. { { 0x1000 + CMD_IP, 0, "" },
  537. { 0x1000 + CMD_FP, 0, "" },
  538. { 0x1000 + CMD_RND, 0, "" },
  539. { 0x1000 + CMD_ABS, 0, "" },
  540. { 0x1000 + CMD_SIGN, 0, "" },
  541. { 0x1000 + CMD_MOD, 0, "" } } },
  542. { /* MENU_UNITS */ MENU_NONE, MENU_NONE, MENU_NONE,
  543. { { 0 , 0, "" },
  544. { 0, 0, "" },
  545. { 0, 0, "" },
  546. { 0, 0, "" },
  547. { 0, 0, "" },
  548. { 0, 0, "" } } },
  549. #endif
  550. };
  551. /* By how much do the variables, programs, and labels
  552. * arrays grow when they are full
  553. */
  554. #define VARS_INCREMENT 25
  555. #define PRGMS_INCREMENT 10
  556. #define LABELS_INCREMENT 10
  557. /* Registers */
  558. vartype *reg_x = NULL;
  559. vartype *reg_y = NULL;
  560. vartype *reg_z = NULL;
  561. vartype *reg_t = NULL;
  562. vartype *reg_lastx = NULL;
  563. int reg_alpha_length = 0;
  564. char reg_alpha[44];
  565. /* Flags */
  566. flags_struct flags;
  567. /* Variables */
  568. int vars_capacity = 0;
  569. int vars_count = 0;
  570. var_struct *vars = NULL;
  571. /* Programs */
  572. int prgms_capacity = 0;
  573. int prgms_count = 0;
  574. prgm_struct *prgms = NULL;
  575. int labels_capacity = 0;
  576. int labels_count = 0;
  577. label_struct *labels = NULL;
  578. int current_prgm = -1;
  579. int4 pc;
  580. int prgm_highlight_row = 0;
  581. int varmenu_length;
  582. char varmenu[7];
  583. int varmenu_rows;
  584. int varmenu_row;
  585. int varmenu_labellength[6];
  586. char varmenu_labeltext[6][7];
  587. int varmenu_role;
  588. bool mode_clall;
  589. int (*mode_interruptible)(int) = NULL;
  590. bool mode_stoppable;
  591. bool mode_command_entry;
  592. bool mode_number_entry;
  593. bool mode_alpha_entry;
  594. bool mode_shift;
  595. int mode_appmenu;
  596. int mode_plainmenu;
  597. bool mode_plainmenu_sticky;
  598. int mode_transientmenu;
  599. int mode_alphamenu;
  600. int mode_commandmenu;
  601. bool mode_running;
  602. bool mode_getkey;
  603. bool mode_pause = false;
  604. bool mode_disable_stack_lift; /* transient */
  605. bool mode_varmenu;
  606. bool mode_updown;
  607. int4 mode_sigma_reg;
  608. int mode_goose;
  609. bool mode_time_clktd;
  610. bool mode_time_clk24;
  611. bool mode_time_dmy;
  612. #if BIGSTACK
  613. stack_item *bigstack_head = NULL;
  614. /* True if we are currently operating with the extended stack */
  615. bool mode_rpl_enter = false;
  616. int stacksize = 4; /* stack size is always at least 4 */
  617. int last_pending_command = CMD_NONE;
  618. /* Keep track of what the stack type was before solve or integration */
  619. int orig_stack_type_before_solve = 0;
  620. #endif
  621. bool cllcd_cmd = false;
  622. phloat entered_number;
  623. int entered_string_length;
  624. char entered_string[15];
  625. int pending_command;
  626. arg_struct pending_command_arg;
  627. int xeq_invisible;
  628. /* Multi-keystroke commands -- edit state */
  629. /* Relevant when mode_command_entry != 0 */
  630. int incomplete_command;
  631. int incomplete_ind;
  632. int incomplete_alpha;
  633. int incomplete_length;
  634. int incomplete_maxdigits;
  635. int incomplete_argtype;
  636. int incomplete_num;
  637. char incomplete_str[7];
  638. int4 incomplete_saved_pc;
  639. int4 incomplete_saved_highlight_row;
  640. /* Command line handling temporaries */
  641. char cmdline[100];
  642. int cmdline_length;
  643. int cmdline_row;
  644. /* Matrix editor / matrix indexing */
  645. int matedit_mode; /* 0=off, 1=index, 2=edit, 3=editn */
  646. char matedit_name[7];
  647. int matedit_length;
  648. vartype *matedit_x;
  649. int4 matedit_i;
  650. int4 matedit_j;
  651. int matedit_prev_appmenu;
  652. /* INPUT */
  653. char input_name[11];
  654. int input_length;
  655. arg_struct input_arg;
  656. /* BASE application */
  657. int baseapp = 0;
  658. /* Random number generator */
  659. phloat random_number;
  660. /* NORM & TRACE mode: number waiting to be printed */
  661. int deferred_print = 0;
  662. /* Keystroke buffer - holds keystrokes received while
  663. * there is a program running.
  664. */
  665. int keybuf_head = 0;
  666. int keybuf_tail = 0;
  667. int keybuf[16];
  668. int remove_program_catalog = 0;
  669. bool bin_dec_mode_switch;
  670. bool state_file_has_old_bcd;
  671. /*******************/
  672. /* Private globals */
  673. /*******************/
  674. static bool state_bool_is_int;
  675. #define MAX_RTNS 8
  676. static int rtn_sp = 0;
  677. static int rtn_prgm[MAX_RTNS];
  678. static int4 rtn_pc[MAX_RTNS];
  679. typedef struct {
  680. int type;
  681. int4 rows;
  682. int4 columns;
  683. } matrix_persister;
  684. static int array_count;
  685. static int array_list_capacity;
  686. static void **array_list;
  687. static bool read_int(int *n) GLOBALS_SECT;
  688. static bool write_int(int n) GLOBALS_SECT;
  689. static bool read_int4(int4 *n) GLOBALS_SECT;
  690. static bool write_int4(int4 n) GLOBALS_SECT;
  691. static bool read_bool(bool *n) GLOBALS_SECT;
  692. static bool write_bool(bool n) GLOBALS_SECT;
  693. static bool array_list_grow() GLOBALS_SECT;
  694. static int array_list_search(void *array) GLOBALS_SECT;
  695. static bool persist_vartype(vartype *v) GLOBALS_SECT;
  696. static bool unpersist_vartype(vartype **v) GLOBALS_SECT;
  697. static void update_label_table(int prgm, int4 pc, int inserted) GLOBALS_SECT;
  698. static void invalidate_lclbls(int prgm_index) GLOBALS_SECT;
  699. static int pc_line_convert(int4 loc, int loc_is_pc) GLOBALS_SECT;
  700. static bool convert_programs() GLOBALS_SECT;
  701. #ifdef IPHONE
  702. static void convert_bigstack_drop() GLOBALS_SECT;
  703. static bool persist_undo() GLOBALS_SECT;
  704. static bool unpersist_undo() GLOBALS_SECT;
  705. #endif
  706. static bool array_list_grow() {
  707. if (array_count < array_list_capacity)
  708. return true;
  709. array_list_capacity += 10;
  710. void **p = (void **) realloc(array_list,
  711. array_list_capacity * sizeof(void *));
  712. if (p == NULL)
  713. return false;
  714. array_list = p;
  715. return true;
  716. }
  717. static int array_list_search(void *array) {
  718. for (int i = 0; i < array_count; i++)
  719. if (array_list[i] == array)
  720. return i;
  721. return -1;
  722. }
  723. static bool persist_vartype(vartype *v) {
  724. if (v == NULL) {
  725. int type = TYPE_NULL;
  726. return shell_write_saved_state(&type, sizeof(int));
  727. }
  728. switch (v->type) {
  729. case TYPE_REAL:
  730. return shell_write_saved_state(v, sizeof(vartype_real));
  731. case TYPE_COMPLEX:
  732. return shell_write_saved_state(v, sizeof(vartype_complex));
  733. case TYPE_STRING:
  734. return shell_write_saved_state(v, sizeof(vartype_string));
  735. case TYPE_REALMATRIX: {
  736. matrix_persister mp;
  737. vartype_realmatrix *rm = (vartype_realmatrix *) v;
  738. mp.type = rm->type;
  739. mp.rows = rm->rows;
  740. mp.columns = rm->columns;
  741. int4 size = mp.rows * mp.columns;
  742. bool must_write = true;
  743. if (rm->array->refcount > 1) {
  744. int n = array_list_search(rm->array);
  745. if (n == -1) {
  746. // A negative row count signals a new shared matrix
  747. mp.rows = -mp.rows;
  748. if (!array_list_grow())
  749. return false;
  750. array_list[array_count++] = rm->array;
  751. } else {
  752. // A zero row count means this matrix shares its data
  753. // with a previously written matrix
  754. mp.rows = 0;
  755. mp.columns = n;
  756. must_write = false;
  757. }
  758. }
  759. if (!shell_write_saved_state(&mp, sizeof(matrix_persister)))
  760. return false;
  761. if (must_write) {
  762. if (!shell_write_saved_state(rm->array->data,
  763. size * sizeof(phloat)))
  764. return false;
  765. if (!shell_write_saved_state(rm->array->is_string, size))
  766. return false;
  767. }
  768. return true;
  769. }
  770. case TYPE_COMPLEXMATRIX: {
  771. matrix_persister mp;
  772. vartype_complexmatrix *cm = (vartype_complexmatrix *) v;
  773. mp.type = cm->type;
  774. mp.rows = cm->rows;
  775. mp.columns = cm->columns;
  776. int4 size = mp.rows * mp.columns;
  777. bool must_write = true;
  778. if (cm->array->refcount > 1) {
  779. int n = array_list_search(cm->array);
  780. if (n == -1) {
  781. // A negative row count signals a new shared matrix
  782. mp.rows = -mp.rows;
  783. if (!array_list_grow())
  784. return false;
  785. array_list[array_count++] = cm->array;
  786. } else {
  787. // A zero row count means this matrix shares its data
  788. // with a previously written matrix
  789. mp.rows = 0;
  790. mp.columns = n;
  791. must_write = false;
  792. }
  793. }
  794. if (!shell_write_saved_state(&mp, sizeof(matrix_persister)))
  795. return false;
  796. if (must_write) {
  797. if (!shell_write_saved_state(cm->array->data,
  798. 2 * size * sizeof(phloat)))
  799. return false;
  800. }
  801. return true;
  802. }
  803. default:
  804. /* Should not happen */
  805. return true;
  806. }
  807. }
  808. // A few declarations to help unpersist_vartype get the offsets right,
  809. // in the case it needs to convert the state file.
  810. struct fake_bcd {
  811. short d_[P+1];
  812. };
  813. struct bin_real {
  814. int type;
  815. double x;
  816. };
  817. struct bin_complex {
  818. int type;
  819. double re, im;
  820. };
  821. struct dec_real {
  822. int type;
  823. fake_bcd x;
  824. };
  825. struct dec_complex {
  826. int type;
  827. fake_bcd re, im;
  828. };
  829. static bool unpersist_vartype(vartype **v) {
  830. int type;
  831. if (shell_read_saved_state(&type, sizeof(int)) != sizeof(int))
  832. return false;
  833. switch (type) {
  834. case TYPE_NULL: {
  835. *v = NULL;
  836. return true;
  837. }
  838. case TYPE_REAL: {
  839. vartype_real *r = (vartype_real *) new_real(0);
  840. if (r == NULL)
  841. return false;
  842. if (bin_dec_mode_switch) {
  843. #ifdef BCD_MATH
  844. int n = sizeof(bin_real) - sizeof(int);
  845. bin_real br;
  846. if (shell_read_saved_state(&br.type + 1, n) != n) {
  847. free_vartype((vartype *) r);
  848. return false;
  849. }
  850. r->x = br.x;
  851. #else
  852. int n = sizeof(dec_real) - sizeof(int);
  853. dec_real dr;
  854. if (shell_read_saved_state(&dr.type + 1, n) != n) {
  855. free_vartype((vartype *) r);
  856. return false;
  857. }
  858. r->x = bcd2double(dr.x.d_, state_file_has_old_bcd);
  859. #endif
  860. } else {
  861. int n = sizeof(vartype_real) - sizeof(int);
  862. if (shell_read_saved_state(&r->type + 1, n) != n) {
  863. free_vartype((vartype *) r);
  864. return false;
  865. }
  866. #ifdef BCD_MATH
  867. if (state_file_has_old_bcd)
  868. bcdfloat_old2new(r->x.bcd.d_);
  869. #endif
  870. }
  871. *v = (vartype *) r;
  872. return true;
  873. }
  874. case TYPE_COMPLEX: {
  875. vartype_complex *c = (vartype_complex *) new_complex(0, 0);
  876. if (c == NULL)
  877. return false;
  878. if (bin_dec_mode_switch) {
  879. #ifdef BCD_MATH
  880. int n = sizeof(bin_complex) - sizeof(int);
  881. bin_complex bc;
  882. if (shell_read_saved_state(&bc.type + 1, n) != n) {
  883. free_vartype((vartype *) c);
  884. return false;
  885. }
  886. c->re = bc.re;
  887. c->im = bc.im;
  888. #else
  889. int n = sizeof(dec_complex) - sizeof(int);
  890. dec_complex dc;
  891. if (shell_read_saved_state(&dc.type + 1, n) != n) {
  892. free_vartype((vartype *) c);
  893. return false;
  894. }
  895. c->re = bcd2double(dc.re.d_, state_file_has_old_bcd);
  896. c->im = bcd2double(dc.im.d_, state_file_has_old_bcd);
  897. #endif
  898. } else {
  899. int n = sizeof(vartype_complex) - sizeof(int);
  900. if (shell_read_saved_state(&c->type + 1, n) != n) {
  901. free_vartype((vartype *) c);
  902. return false;
  903. }
  904. #ifdef BCD_MATH
  905. if (state_file_has_old_bcd) {
  906. bcdfloat_old2new(c->re.bcd.d_);
  907. bcdfloat_old2new(c->im.bcd.d_);
  908. }
  909. #endif
  910. }
  911. *v = (vartype *) c;
  912. return true;
  913. }
  914. case TYPE_STRING: {
  915. vartype_string *s = (vartype_string *) new_string("", 0);
  916. int n = sizeof(vartype_string) - sizeof(int);
  917. if (s == NULL)
  918. return false;
  919. if (shell_read_saved_state(&s->type + 1, n) != n) {
  920. free_vartype((vartype *) s);
  921. return false;
  922. } else {
  923. *v = (vartype *) s;
  924. return true;
  925. }
  926. }
  927. case TYPE_REALMATRIX: {
  928. matrix_persister mp;
  929. int n = sizeof(matrix_persister) - sizeof(int);
  930. if (shell_read_saved_state(&mp.type + 1, n) != n)
  931. return false;
  932. if (mp.rows == 0) {
  933. // Shared matrix
  934. vartype *m = new_matrix_alias((vartype *) array_list[mp.columns]);
  935. if (m == NULL)
  936. return false;
  937. else {
  938. *v = m;
  939. return true;
  940. }
  941. }
  942. bool shared = mp.rows < 0;
  943. if (shared)
  944. mp.rows = -mp.rows;
  945. vartype_realmatrix *rm = (vartype_realmatrix *) new_realmatrix(mp.rows, mp.columns);
  946. if (rm == NULL)
  947. return false;
  948. if (bin_dec_mode_switch) {
  949. int4 size = mp.rows * mp.columns;
  950. #ifdef BCD_MATH
  951. int phsz = sizeof(double);
  952. #else
  953. int phsz = sizeof(fake_bcd);
  954. #endif
  955. int4 tsz = size * phsz;
  956. char *temp = (char *) malloc(tsz);
  957. if (temp == NULL) {
  958. free_vartype((vartype *) rm);
  959. return false;
  960. }
  961. if (shell_read_saved_state(temp, tsz) != tsz) {
  962. free(temp);
  963. free_vartype((vartype *) rm);
  964. return false;
  965. }
  966. if (shell_read_saved_state(rm->array->is_string, size) != size) {
  967. free(temp);
  968. free_vartype((vartype *) rm);
  969. return false;
  970. }
  971. #ifdef BCD_MATH
  972. for (int4 i = 0; i < size; i++) {
  973. if (rm->array->is_string[i]) {
  974. char *src = temp + i * phsz;
  975. char *dst = (char *) (rm->array->data + i);
  976. for (int j = 0; j < 7; j++)
  977. *dst++ = *src++;
  978. } else {
  979. rm->array->data[i] = ((double *) temp)[i];
  980. }
  981. }
  982. #else
  983. for (int4 i = 0; i < size; i++) {
  984. if (rm->array->is_string[i]) {
  985. char *src = temp + i * phsz;
  986. char *dst = (char *) (rm->array->data + i);
  987. for (int j = 0; j < 7; j++)
  988. *dst++ = *src++;
  989. } else {
  990. rm->array->data[i] = bcd2double((short *) (temp + phsz * i), state_file_has_old_bcd);
  991. }
  992. }
  993. #endif
  994. free(temp);
  995. } else {
  996. int4 size = mp.rows * mp.columns * sizeof(phloat);
  997. if (shell_read_saved_state(rm->array->data, size) != size) {
  998. free_vartype((vartype *) rm);
  999. return false;
  1000. }
  1001. size = mp.rows * mp.columns;
  1002. if (shell_read_saved_state(rm->array->is_string, size) != size) {
  1003. free_vartype((vartype *) rm);
  1004. return false;
  1005. }
  1006. #ifdef BCD_MATH
  1007. if (state_file_has_old_bcd)
  1008. for (int4 i = 0; i < size; i++)
  1009. if (!rm->array->is_string[i])
  1010. bcdfloat_old2new(rm->array->data[i].bcd.d_);
  1011. #endif
  1012. }
  1013. if (shared) {
  1014. if (!array_list_grow()) {
  1015. free_vartype((vartype *) rm);
  1016. return false;
  1017. }
  1018. array_list[array_count++] = rm;
  1019. }
  1020. *v = (vartype *) rm;
  1021. return true;
  1022. }
  1023. case TYPE_COMPLEXMATRIX: {
  1024. matrix_persister mp;
  1025. int n = sizeof(matrix_persister) - sizeof(int);
  1026. if (shell_read_saved_state(&mp.type + 1, n) != n)
  1027. return false;
  1028. if (mp.rows == 0) {
  1029. // Shared matrix
  1030. vartype *m = new_matrix_alias((vartype *) array_list[mp.columns]);
  1031. if (m == NULL)
  1032. return false;
  1033. else {
  1034. *v = m;
  1035. return true;
  1036. }
  1037. }
  1038. bool shared = mp.rows < 0;
  1039. if (shared)
  1040. mp.rows = -mp.rows;
  1041. vartype_complexmatrix *cm = (vartype_complexmatrix *)
  1042. new_complexmatrix(mp.rows, mp.columns);
  1043. if (cm == NULL)
  1044. return false;
  1045. if (bin_dec_mode_switch) {
  1046. int4 size = 2 * mp.rows * mp.columns;
  1047. for (int4 i = 0; i < size; i++)
  1048. if (!read_phloat(cm->array->data + i)) {
  1049. free_vartype((vartype *) cm);
  1050. return false;
  1051. }
  1052. } else {
  1053. int4 size = 2 * mp.rows * mp.columns * sizeof(phloat);
  1054. if (shell_read_saved_state(cm->array->data, size) != size) {
  1055. free_vartype((vartype *) cm);
  1056. return false;
  1057. }
  1058. #ifdef BCD_MATH
  1059. if (state_file_has_old_bcd)
  1060. for (int4 i = 0; i < size; i++)
  1061. bcdfloat_old2new(cm->array->data[i].bcd.d_);
  1062. #endif
  1063. }
  1064. if (shared) {
  1065. if (!array_list_grow()) {
  1066. free_vartype((vartype *) cm);
  1067. return false;
  1068. }
  1069. array_list[array_count++] = cm;
  1070. }
  1071. *v = (vartype *) cm;
  1072. return true;
  1073. }
  1074. default:
  1075. return false;
  1076. }
  1077. }
  1078. static bool persist_globals() GLOBALS_SECT;
  1079. static bool persist_globals() {
  1080. int i;
  1081. array_count = 0;
  1082. array_list_capacity = 0;
  1083. array_list = NULL;
  1084. bool ret = false;
  1085. #if BIGSTACK
  1086. stack_item *si = bigstack_head;
  1087. #endif
  1088. if (!persist_vartype(reg_x))
  1089. goto done;
  1090. if (!persist_vartype(reg_y))
  1091. goto done;
  1092. if (!persist_vartype(reg_z))
  1093. goto done;
  1094. if (!persist_vartype(reg_t))
  1095. goto done;
  1096. if (!persist_vartype(reg_lastx))
  1097. goto done;
  1098. #if BIGSTACK
  1099. if (!write_bool(true)) /* Yes, big stack block exists */
  1100. goto done;
  1101. persist_undo();
  1102. if (!write_int(stacksize))
  1103. goto done;
  1104. while (si != NULL) {
  1105. if (!persist_vartype(si->var))
  1106. goto done;
  1107. si = si->next;
  1108. }
  1109. if (!write_bool(mode_rpl_enter))
  1110. goto done;
  1111. #else
  1112. if (!write_bool(false)) /* No, big stack block does not exist */
  1113. goto done;
  1114. #endif
  1115. if (!write_int(reg_alpha_length))
  1116. goto done;
  1117. if (!shell_write_saved_state(reg_alpha, 44))
  1118. goto done;
  1119. if (!write_int4(mode_sigma_reg))
  1120. goto done;
  1121. if (!write_int(mode_goose))
  1122. goto done;
  1123. if (!write_bool(mode_time_clktd))
  1124. goto done;
  1125. if (!write_bool(mode_time_clk24))
  1126. goto done;
  1127. if (!write_bool(mode_time_dmy))
  1128. goto done;
  1129. if (!shell_write_saved_state(&flags, sizeof(flags_struct)))
  1130. goto done;
  1131. if (!write_int(vars_count))
  1132. goto done;
  1133. if (!shell_write_saved_state(vars, vars_count * sizeof(var_struct)))
  1134. goto done;
  1135. for (i = 0; i < vars_count; i++)
  1136. if (!persist_vartype(vars[i].value))
  1137. goto done;
  1138. if (!write_int(prgms_count))
  1139. goto done;
  1140. if (!shell_write_saved_state(prgms, prgms_count * sizeof(prgm_struct)))
  1141. goto done;
  1142. for (i = 0; i < prgms_count; i++)
  1143. if (!shell_write_saved_state(prgms[i].text, prgms[i].size))
  1144. goto done;
  1145. if (!write_int(current_prgm))
  1146. goto done;
  1147. if (!write_int4(pc))
  1148. goto done;
  1149. if (!write_int(prgm_highlight_row))
  1150. goto done;
  1151. if (!write_int(varmenu_length))
  1152. goto done;
  1153. if (!shell_write_saved_state(varmenu, 7))
  1154. goto done;
  1155. if (!write_int(varmenu_rows))
  1156. goto done;
  1157. if (!write_int(varmenu_row))
  1158. goto done;
  1159. if (!shell_write_saved_state(varmenu_labellength, 6 * sizeof(int)))
  1160. goto done;
  1161. if (!shell_write_saved_state(varmenu_labeltext, 42))
  1162. goto done;
  1163. if (!write_int(varmenu_role))
  1164. goto done;
  1165. if (!write_int(rtn_sp))
  1166. goto done;
  1167. if (!shell_write_saved_state(&rtn_prgm, MAX_RTNS * sizeof(int)))
  1168. goto done;
  1169. if (!shell_write_saved_state(&rtn_pc, MAX_RTNS * sizeof(int4)))
  1170. goto done;
  1171. ret = true;
  1172. done:
  1173. free(array_list);
  1174. return ret;
  1175. }
  1176. static bool unpersist_globals(int4 ver) GLOBALS_SECT;
  1177. static bool unpersist_globals(int4 ver) {
  1178. int4 n;
  1179. int i;
  1180. array_count = 0;
  1181. array_list_capacity = 0;
  1182. array_list = NULL;
  1183. bool ret = false;
  1184. bool bigstack = false;
  1185. free_vartype(reg_x);
  1186. if (!unpersist_vartype(&reg_x))
  1187. goto done;
  1188. free_vartype(reg_y);
  1189. if (!unpersist_vartype(&reg_y))
  1190. goto done;
  1191. free_vartype(reg_z);
  1192. if (!unpersist_vartype(&reg_z))
  1193. goto done;
  1194. free_vartype(reg_t);
  1195. if (!unpersist_vartype(&reg_t))
  1196. goto done;
  1197. free_vartype(reg_lastx);
  1198. if (!unpersist_vartype(&reg_lastx))
  1199. goto done;
  1200. if (ver >= 12) {
  1201. /* we are on atleast version 12, so this block exists */
  1202. if (!read_bool(&bigstack))
  1203. goto done;
  1204. }
  1205. #ifdef BIGSTACK
  1206. if (bigstack)
  1207. {
  1208. if (ver >= 17) {
  1209. unpersist_undo();
  1210. }
  1211. stacksize = 20; /* backward compatible pre version 13 big stack */
  1212. if (ver >= 13) {
  1213. if (!read_int(&stacksize))
  1214. goto done;
  1215. while(bigstack_head != NULL)
  1216. {
  1217. shift_big_stack_down();
  1218. free_vartype(reg_t);
  1219. }
  1220. }
  1221. int i = stacksize - 4;
  1222. stack_item *lastsi = NULL;
  1223. while (i-- > 0) {
  1224. vartype *v = NULL;
  1225. if (!unpersist_vartype(&v))
  1226. goto done;
  1227. stack_item *si = new_stack_item(v);
  1228. si->next = NULL;
  1229. if (lastsi == NULL)
  1230. bigstack_head = si;
  1231. else
  1232. lastsi->next = si;
  1233. lastsi = si;
  1234. }
  1235. if (!read_bool(&mode_rpl_enter))
  1236. goto done;
  1237. }
  1238. #endif
  1239. if (!read_int(&reg_alpha_length)) {
  1240. reg_alpha_length = 0;
  1241. goto done;
  1242. }
  1243. if (shell_read_saved_state(reg_alpha, 44) != 44) {
  1244. reg_alpha_length = 0;
  1245. goto done;
  1246. }
  1247. if (!read_int4(&mode_sigma_reg)) {
  1248. mode_sigma_reg = 11;
  1249. goto done;
  1250. }
  1251. if (!read_int(&mode_goose)) {
  1252. mode_goose = -1;
  1253. goto done;
  1254. }
  1255. if (ver >= 16) {
  1256. if (!read_bool(&mode_time_clktd)) {
  1257. mode_time_clktd = false;
  1258. goto done;
  1259. }
  1260. if (!read_bool(&mode_time_clk24)) {
  1261. mode_time_clk24 = false;
  1262. goto done;
  1263. }
  1264. if (!read_bool(&mode_time_dmy)) {
  1265. mode_time_dmy = false;
  1266. goto done;
  1267. }
  1268. }
  1269. if (shell_read_saved_state(&flags, sizeof(flags_struct))
  1270. != sizeof(flags_struct))
  1271. goto done;
  1272. vars_capacity = 0;
  1273. if (vars != NULL) {
  1274. free(vars);
  1275. vars = NULL;
  1276. }
  1277. if (!read_int(&vars_count)) {
  1278. vars_count = 0;
  1279. goto done;
  1280. }
  1281. n = vars_count * sizeof(var_struct);
  1282. vars = (var_struct *) malloc(n);
  1283. if (vars == NULL) {
  1284. vars_count = 0;
  1285. goto done;
  1286. }
  1287. if (shell_read_saved_state(vars, n) != n) {
  1288. free(vars);
  1289. vars = NULL;
  1290. vars_count = 0;
  1291. goto done;
  1292. }
  1293. vars_capacity = vars_count;
  1294. for (i = 0; i < vars_count; i++)
  1295. vars[i].value = NULL;
  1296. for (i = 0; i < vars_count; i++)
  1297. if (!unpersist_vartype(&vars[i].value)) {
  1298. purge_all_vars();
  1299. goto done;
  1300. }
  1301. prgms_capacity = 0;
  1302. if (prgms != NULL) {
  1303. free(prgms);
  1304. prgms = NULL;
  1305. }
  1306. if (!read_int(&prgms_count)) {
  1307. prgms_count = 0;
  1308. goto done;
  1309. }
  1310. n = prgms_count * sizeof(prgm_struct);
  1311. prgms = (prgm_struct *) malloc(n);
  1312. if (prgms == NULL) {
  1313. prgms_count = 0;
  1314. goto done;
  1315. }
  1316. if (shell_read_saved_state(prgms, n) != n) {
  1317. free(prgms);
  1318. prgms = NULL;
  1319. prgms_count = 0;
  1320. goto done;
  1321. }
  1322. prgms_capacity = prgms_count;
  1323. for (i = 0; i < prgms_count; i++) {
  1324. prgms[i].capacity = prgms[i].size;
  1325. prgms[i].text = (unsigned char *) malloc(prgms[i].size);
  1326. // TODO - handle memory allocation failure
  1327. }
  1328. for (i = 0; i < prgms_count; i++) {
  1329. if (shell_read_saved_state(prgms[i].text, prgms[i].size)
  1330. != prgms[i].size) {
  1331. clear_all_prgms();
  1332. goto done;
  1333. }
  1334. }
  1335. if (!read_int(&current_prgm)) {
  1336. current_prgm = 0;
  1337. goto done;
  1338. }
  1339. if (!read_int4(&pc)) {
  1340. pc = -1;
  1341. goto done;
  1342. }
  1343. if (!read_int(&prgm_highlight_row)) {
  1344. prgm_highlight_row = 0;
  1345. goto done;
  1346. }
  1347. if (!read_int(&varmenu_length)) {
  1348. varmenu_length = 0;
  1349. goto done;
  1350. }
  1351. if (shell_read_saved_state(varmenu, 7) != 7) {
  1352. varmenu_length = 0;
  1353. goto done;
  1354. }
  1355. if (!read_int(&varmenu_rows)) {
  1356. varmenu_length = 0;
  1357. goto done;
  1358. }
  1359. if (!read_int(&varmenu_row)) {
  1360. varmenu_length = 0;
  1361. goto done;
  1362. }
  1363. if (shell_read_saved_state(varmenu_labellength, 6 * sizeof(int))
  1364. != 6 * sizeof(int))
  1365. goto done;
  1366. if (shell_read_saved_state(varmenu_labeltext, 42) != 42)
  1367. goto done;
  1368. if (!read_int(&varmenu_role))
  1369. goto done;
  1370. if (!read_int(&rtn_sp))
  1371. goto done;
  1372. if (shell_read_saved_state(rtn_prgm, MAX_RTNS * sizeof(int))
  1373. != MAX_RTNS * sizeof(int))
  1374. goto done;
  1375. if (shell_read_saved_state(rtn_pc, MAX_RTNS * sizeof(int4))
  1376. != MAX_RTNS * sizeof(int4))
  1377. goto done;
  1378. if (bin_dec_mode_switch)
  1379. if (!convert_programs()) {
  1380. clear_all_prgms();
  1381. goto done;
  1382. }
  1383. #ifdef IPHONE
  1384. if (ver == 12 || ver == 13) {
  1385. // CMD_DROP redefined from 315 to 329, to resolve clash with
  1386. // Underhill's COPAN extensions.
  1387. convert_bigstack_drop();
  1388. }
  1389. #endif
  1390. rebuild_label_table();
  1391. ret = true;
  1392. done:
  1393. free(array_list);
  1394. return ret;
  1395. }
  1396. void clear_all_prgms() {
  1397. if (prgms != NULL) {
  1398. int i;
  1399. for (i = 0; i < prgms_count; i++)
  1400. if (prgms[i].text != NULL)
  1401. free(prgms[i].text);
  1402. free(prgms);
  1403. }
  1404. prgms = NULL;
  1405. prgms_capacity = 0;
  1406. prgms_count = 0;
  1407. if (labels != NULL)
  1408. free(labels);
  1409. labels = NULL;
  1410. labels_capacity = 0;
  1411. labels_count = 0;
  1412. }
  1413. int clear_prgm(const arg_struct *arg) {
  1414. int prgm_index = NULL;
  1415. int i, j;
  1416. if (arg->type == ARGTYPE_LBLINDEX)
  1417. prgm_index = labels[arg->val.num].prgm;
  1418. else if (arg->type == ARGTYPE_STR) {
  1419. if (arg->length == 0) {
  1420. if (current_prgm < 0 || current_prgm >= prgms_count)
  1421. return ERR_INTERNAL_ERROR;
  1422. prgm_index = current_prgm;
  1423. } else {
  1424. int i;
  1425. for (i = labels_count - 1; i >= 0; i--)
  1426. if (string_equals(arg->val.text, arg->length,
  1427. labels[i].name, labels[i].length))
  1428. goto found;
  1429. return ERR_LABEL_NOT_FOUND;
  1430. found:
  1431. prgm_index = labels[i].prgm;
  1432. }
  1433. }
  1434. clear_all_rtns();
  1435. if (prgm_index == current_prgm)
  1436. pc = -1;
  1437. else if (current_prgm > prgm_index)
  1438. current_prgm--;
  1439. free(prgms[prgm_index].text);
  1440. for (i = prgm_index; i < prgms_count - 1; i++)
  1441. prgms[i] = prgms[i + 1];
  1442. prgms_count--;
  1443. i = j = 0;
  1444. while (j < labels_count) {
  1445. if (j > i)
  1446. labels[i] = labels[j];
  1447. j++;
  1448. if (labels[i].prgm > prgm_index) {
  1449. labels[i].prgm--;
  1450. i++;
  1451. } else if (labels[i].prgm < prgm_index)
  1452. i++;
  1453. }
  1454. labels_count = i;
  1455. if (prgms_count == 0 || prgm_index == prgms_count) {
  1456. int saved_prgm = current_prgm;
  1457. int saved_pc = pc;
  1458. goto_dot_dot();
  1459. current_prgm = saved_prgm;
  1460. pc = saved_pc;
  1461. }
  1462. update_catalog();
  1463. return ERR_NONE;
  1464. }
  1465. void clear_prgm_lines(int4 count) {
  1466. int4 frompc, deleted, i, j;
  1467. if (pc == -1)
  1468. pc = 0;
  1469. frompc = pc;
  1470. while (count > 0) {
  1471. int command;
  1472. arg_struct arg;
  1473. get_next_command(&pc, &command, &arg, 0);
  1474. if (command == CMD_END) {
  1475. pc -= 2;
  1476. break;
  1477. }
  1478. count--;
  1479. }
  1480. deleted = pc - frompc;
  1481. for (i = pc; i < prgms[current_prgm].size; i++)
  1482. prgms[current_prgm].text[i - deleted] = prgms[current_prgm].text[i];
  1483. prgms[current_prgm].size -= deleted;
  1484. pc = frompc;
  1485. i = j = 0;
  1486. while (j < labels_count) {
  1487. if (j > i)
  1488. labels[i] = labels[j];
  1489. j++;
  1490. if (labels[i].prgm == current_prgm) {
  1491. if (labels[i].pc < frompc)
  1492. i++;
  1493. else if (labels[i].pc >= frompc + deleted) {
  1494. labels[i].pc -= deleted;
  1495. i++;
  1496. }
  1497. } else
  1498. i++;
  1499. }
  1500. labels_count = i;
  1501. invalidate_lclbls(current_prgm);
  1502. clear_all_rtns();
  1503. }
  1504. void goto_dot_dot() {
  1505. int command;
  1506. arg_struct arg;
  1507. if (prgms_count != 0) {
  1508. /* Check if last program is empty */
  1509. pc = 0;
  1510. current_prgm = prgms_count - 1;
  1511. get_next_command(&pc, &command, &arg, 0);
  1512. if (command == CMD_END) {
  1513. pc = -1;
  1514. return;
  1515. }
  1516. }
  1517. if (prgms_count == prgms_capacity) {
  1518. prgm_struct *newprgms;
  1519. int i;
  1520. prgms_capacity += 10;
  1521. newprgms = (prgm_struct *) malloc(prgms_capacity * sizeof(prgm_struct));
  1522. // TODO - handle memory allocation failure
  1523. for (i = 0; i < prgms_count; i++)
  1524. newprgms[i] = prgms[i];
  1525. if (prgms != NULL)
  1526. free(prgms);
  1527. prgms = newprgms;
  1528. }
  1529. current_prgm = prgms_count++;
  1530. prgms[current_prgm].capacity = 0;
  1531. prgms[current_prgm].size = 0;
  1532. prgms[current_prgm].lclbl_invalid = 1;
  1533. prgms[current_prgm].text = NULL;
  1534. command = CMD_END;
  1535. arg.type = ARGTYPE_NONE;
  1536. store_command(0, command, &arg);
  1537. pc = -1;
  1538. }
  1539. int mvar_prgms_exist() {
  1540. int i;
  1541. for (i = 0; i < labels_count; i++)
  1542. if (label_has_mvar(i))
  1543. return 1;
  1544. return 0;
  1545. }
  1546. int label_has_mvar(int lblindex) {
  1547. int saved_prgm;
  1548. int4 pc;
  1549. int command;
  1550. arg_struct arg;
  1551. if (labels[lblindex].length == 0)
  1552. return 0;
  1553. saved_prgm = current_prgm;
  1554. current_prgm = labels[lblindex].prgm;
  1555. pc = labels[lblindex].pc;
  1556. pc += get_command_length(current_prgm, pc);
  1557. get_next_command(&pc, &command, &arg, 0);
  1558. current_prgm = saved_prgm;
  1559. return command == CMD_MVAR;
  1560. }
  1561. int get_command_length(int prgm_index, int4 pc) {
  1562. prgm_struct *prgm = prgms + prgm_index;
  1563. int4 pc2 = pc;
  1564. int command = prgm->text[pc2++];
  1565. int argtype = prgm->text[pc2++];
  1566. command |= (argtype & 240) << 4;
  1567. argtype &= 15;
  1568. if (command == CMD_CONVERT) pc2 += 2;
  1569. if ((command == CMD_GTO || command == CMD_XEQ)
  1570. && (argtype == ARGTYPE_NUM || argtype == ARGTYPE_LCLBL))
  1571. pc2 += 4;
  1572. switch (argtype) {
  1573. case ARGTYPE_NUM:
  1574. case ARGTYPE_NEG_NUM:
  1575. case ARGTYPE_IND_NUM: {
  1576. while ((prgm->text[pc2++] & 128) == 0);
  1577. break;
  1578. }
  1579. case ARGTYPE_STK:
  1580. case ARGTYPE_IND_STK:
  1581. case ARGTYPE_COMMAND:
  1582. case ARGTYPE_LCLBL:
  1583. pc2++;
  1584. break;
  1585. case ARGTYPE_STR:
  1586. case ARGTYPE_IND_STR: {
  1587. pc2 += prgm->text[pc2] + 1;
  1588. break;
  1589. }
  1590. case ARGTYPE_DOUBLE:
  1591. pc2 += sizeof(phloat);
  1592. break;
  1593. }
  1594. return pc2 - pc;
  1595. }
  1596. void get_next_command(int4 *pc, int *command, arg_struct *arg, int find_target){
  1597. prgm_struct *prgm = prgms + current_prgm;
  1598. int i;
  1599. int4 target_pc;
  1600. int4 orig_pc = *pc;
  1601. *command = prgm->text[(*pc)++];
  1602. arg->type = prgm->text[(*pc)++];
  1603. *command |= (arg->type & 240) << 4;
  1604. arg->type &= 15;
  1605. if ((*command == CMD_GTO || *command == CMD_XEQ)
  1606. && (arg->type == ARGTYPE_NUM
  1607. || arg->type == ARGTYPE_LCLBL)) {
  1608. if (find_target) {
  1609. target_pc = 0;
  1610. for (i = 0; i < 4; i++)
  1611. target_pc = (target_pc << 8) | prgm->text[(*pc)++];
  1612. if (target_pc != -1) {
  1613. arg->target = target_pc;
  1614. find_target = 0;
  1615. }
  1616. } else
  1617. (*pc) += 4;
  1618. } else {
  1619. find_target = 0;
  1620. arg->target = -1;
  1621. }
  1622. switch (arg->type) {
  1623. case ARGTYPE_NUM:
  1624. case ARGTYPE_NEG_NUM:
  1625. case ARGTYPE_IND_NUM: {
  1626. int4 num = 0;
  1627. unsigned char c;
  1628. do {
  1629. c = prgm->text[(*pc)++];
  1630. num = (num << 7) | (c & 127);
  1631. } while ((c & 128) == 0);
  1632. if (arg->type == ARGTYPE_NEG_NUM) {
  1633. arg->type = ARGTYPE_NUM;
  1634. num = -num;
  1635. }
  1636. arg->val.num = num;
  1637. break;
  1638. }
  1639. case ARGTYPE_STK:
  1640. case ARGTYPE_IND_STK:
  1641. arg->val.stk = prgm->text[(*pc)++];
  1642. break;
  1643. case ARGTYPE_COMMAND:
  1644. arg->val.cmd = prgm->text[(*pc)++];
  1645. break;
  1646. case ARGTYPE_LCLBL:
  1647. arg->val.lclbl = prgm->text[(*pc)++];
  1648. break;
  1649. case ARGTYPE_STR:
  1650. case ARGTYPE_IND_STR: {
  1651. arg->length = prgm->text[(*pc)++];
  1652. for (i = 0; i < arg->length; i++)
  1653. arg->val.text[i] = prgm->text[(*pc)++];
  1654. break;
  1655. }
  1656. case ARGTYPE_DOUBLE: {
  1657. unsigned char *b = (unsigned char *) &arg->val_d;
  1658. for (int i = 0; i < (int) sizeof(phloat); i++)
  1659. *b++ = prgm->text[(*pc)++];
  1660. break;
  1661. }
  1662. }
  1663. if (*command == CMD_NUMBER && arg->type != ARGTYPE_DOUBLE) {
  1664. /* argtype is ARGTYPE_NUM; convert to phloat */
  1665. arg->val_d = arg->val.num;
  1666. arg->type = ARGTYPE_DOUBLE;
  1667. }
  1668. if (find_target) {
  1669. target_pc = find_local_label(arg);
  1670. arg->target = target

Large files files are truncated, but you can click here to view the full file