PageRenderTime 62ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/free42/common/core_globals.cc

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

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