Script.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780
  1. #include <stdarg.h>
  2. #include <stdbool.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include "utils/Functions.h"
  7. #include "vm/Operation.h"
  8. #include "vm/Script.h"
  9. void sError(Script* sc, const char* format, ...) {
  10. va_list args;
  11. va_start(args, format);
  12. vsnprintf(sc->error, SCRIPT_ERROR_SIZE, format, args);
  13. va_end(args);
  14. }
  15. static void sCannotSetValueType(Script* sc) {
  16. sError(sc, "cannot set value type");
  17. }
  18. static bool sRead(Script* sc, void* buffer, int length) {
  19. if(sc->readIndex + length > sc->code->length) {
  20. sError(sc, "cannot read expected %d bytes of data from bytecode",
  21. length);
  22. return true;
  23. }
  24. memcpy(buffer, sc->code->code + sc->readIndex, (size_t)length);
  25. sc->readIndex += length;
  26. return false;
  27. }
  28. static Operation sReadOperation(Script* sc) {
  29. unsigned char c;
  30. if(sRead(sc, &c, 1)) {
  31. return OP_NOTHING;
  32. }
  33. return (Operation)c;
  34. }
  35. static Value* sPeekStack(Script* sc, ValueType type) {
  36. if(sc->stackIndex <= 0) {
  37. sError(sc, "stack underflow");
  38. return NULL;
  39. }
  40. ValueType stackType = vGetType(sc->stack[sc->stackIndex - 1]);
  41. if(stackType != type) {
  42. sError(sc, "expected %s on stack but got %s", vtGetName(type),
  43. vtGetName(stackType));
  44. return NULL;
  45. }
  46. return sc->stack + (sc->stackIndex - 1);
  47. }
  48. bool sPopInt32(Script* sc, int32* i) {
  49. Value* v = sPeekStack(sc, VT_INT);
  50. if(v == NULL) {
  51. return true;
  52. }
  53. *i = v->data.intValue;
  54. sc->stackIndex--;
  55. return false;
  56. }
  57. bool sPopFloat(Script* sc, float* f) {
  58. Value* v = sPeekStack(sc, VT_FLOAT);
  59. if(v == NULL) {
  60. return true;
  61. }
  62. *f = v->data.floatValue;
  63. sc->stackIndex--;
  64. return false;
  65. }
  66. static bool sReadInt32(Script* sc, int32* i) {
  67. return sRead(sc, i, sizeof(int32));
  68. }
  69. static bool sReadFloat(Script* sc, float* f) {
  70. return sRead(sc, f, sizeof(float));
  71. }
  72. static Value* sPushStack(Script* sc, int values) {
  73. if(sc->stackIndex + values > SCRIPT_STACK_SIZE) {
  74. sError(sc, "stack overflow");
  75. return NULL;
  76. }
  77. Value* v = sc->stack + sc->stackIndex;
  78. for(int i = 0; i < values; i++) {
  79. if(vSetType(v + i, VT_NOT_SET)) {
  80. sCannotSetValueType(sc);
  81. return NULL;
  82. }
  83. }
  84. sc->stackIndex += values;
  85. return v;
  86. }
  87. bool sPushInt32(Script* sc, int32 i) {
  88. Value* v = sPushStack(sc, 1);
  89. if(vSetType(v, VT_INT)) {
  90. sCannotSetValueType(sc);
  91. return true;
  92. }
  93. v->data.intValue = i;
  94. return false;
  95. }
  96. bool sPushFloat(Script* sc, float f) {
  97. Value* v = sPushStack(sc, 1);
  98. if(vSetType(v, VT_FLOAT)) {
  99. sCannotSetValueType(sc);
  100. return true;
  101. }
  102. v->data.floatValue = f;
  103. return false;
  104. }
  105. static void sPushInt32Value(Script* sc) {
  106. int32 value = 0;
  107. if(!sReadInt32(sc, &value)) {
  108. sPushInt32(sc, value);
  109. }
  110. }
  111. static void sPushFloatValue(Script* sc) {
  112. float value = 0;
  113. if(!sReadFloat(sc, &value)) {
  114. sPushFloat(sc, value);
  115. }
  116. }
  117. #define ZERO_CHECK(name) \
  118. if(values[0] == 0) { \
  119. sError(sc, name " by 0"); \
  120. return; \
  121. }
  122. #define OP_BASE(type, Type, RType, op, check) \
  123. { \
  124. type values[2]; \
  125. if(!sPop##Type(sc, values) && !sPop##Type(sc, values + 1)) { \
  126. check; \
  127. sPush##RType(sc, values[1] op values[0]); \
  128. } \
  129. }
  130. #define CHECKED_NUMBER_OP(type, Type, op, check) \
  131. OP_BASE(type, Type, Type, op, check)
  132. #define NUMBER_OP(type, Type, op) CHECKED_NUMBER_OP(type, Type, op, )
  133. #define BOOL_OP(type, Type, op) OP_BASE(type, Type, Int32, op, )
  134. #define DIVISION(type, Type) \
  135. CHECKED_NUMBER_OP(type, Type, /, ZERO_CHECK("division"));
  136. #define MODULE(type, Type) \
  137. CHECKED_NUMBER_OP(type, Type, %, ZERO_CHECK("module"));
  138. #define INVERT_SIGN(type, Type) \
  139. { \
  140. type value = 0; \
  141. if(!sPop##Type(sc, &value)) { \
  142. sPush##Type(sc, -value); \
  143. } \
  144. }
  145. static void sReserveBytes(Script* sc) {
  146. int32 values = 0;
  147. int32 offset = 0;
  148. if(sReadInt32(sc, &values) || sReadInt32(sc, &offset)) {
  149. return;
  150. }
  151. int32 oldIndex = sc->stackVarIndex;
  152. sc->stackVarIndex = sc->stackIndex - offset;
  153. sPushStack(sc, values - offset);
  154. sPushInt32(sc, oldIndex);
  155. }
  156. static void sGlobalReserveBytes(Script* sc) {
  157. int32 values = 0;
  158. if(sReadInt32(sc, &values)) {
  159. return;
  160. }
  161. sc->stackVarIndex = sc->stackIndex;
  162. if(values >= 0) {
  163. sPushStack(sc, values);
  164. } else {
  165. sc->stackIndex += values;
  166. if(sc->stackIndex < 0) {
  167. sError(sc, "invalid global free %d", values);
  168. }
  169. }
  170. }
  171. static void sNot(Script* sc) {
  172. int32 value = 0;
  173. if(!sPopInt32(sc, &value)) {
  174. sPushInt32(sc, !value);
  175. }
  176. }
  177. static void sBitNotInt32(Script* sc) {
  178. int32 value = 0;
  179. if(!sPopInt32(sc, &value)) {
  180. sPushInt32(sc, ~value);
  181. }
  182. }
  183. static void sLine(Script* sc) {
  184. sRead(sc, &sc->line, 2);
  185. }
  186. static void sGoTo(Script* sc) {
  187. int32 gotoIndex;
  188. if(!sReadInt32(sc, &gotoIndex)) {
  189. sc->readIndex = gotoIndex;
  190. }
  191. }
  192. static void sGoSub(Script* sc) {
  193. int32 gotoIndex;
  194. int32 offset;
  195. if(sReadInt32(sc, &gotoIndex) || sReadInt32(sc, &offset)) {
  196. return;
  197. }
  198. int index = sc->stackIndex - offset - 1;
  199. if(index < 0 || index >= SCRIPT_STACK_SIZE) {
  200. sError(sc, "invalid gosub offset");
  201. return;
  202. } else if(vGetType(sc->stack[index]) != VT_INT) {
  203. sError(sc, "gosub expects an int got %s",
  204. vtGetName(vGetType(sc->stack[index])));
  205. return;
  206. }
  207. sc->stack[index].data.intValue = sc->readIndex;
  208. sc->readIndex = gotoIndex;
  209. }
  210. static void sReturn(Script* sc) {
  211. int32 values = 0;
  212. int32 varIndex = 0;
  213. if(sReadInt32(sc, &values) || sPopInt32(sc, &varIndex)) {
  214. return;
  215. }
  216. sc->stackVarIndex = varIndex;
  217. if(sc->stackIndex < values) {
  218. sError(sc, "invalid return index");
  219. return;
  220. }
  221. sc->stackIndex -= values;
  222. if(sPopInt32(sc, &sc->readIndex) || sc->readIndex < 0) {
  223. sError(sc, "read index is corrupt");
  224. }
  225. }
  226. static void sReturnPointer(Script* sc) {
  227. Value* v = sPeekStack(sc, VT_ARRAY);
  228. if(v == NULL) {
  229. return;
  230. }
  231. sc->stackIndex--;
  232. sReturn(sc);
  233. Value* p = sPushStack(sc, 1);
  234. if(p != NULL) {
  235. *p = *v;
  236. }
  237. }
  238. #define RETURN(type, Type) \
  239. { \
  240. type value; \
  241. if(!sPop##Type(sc, &value)) { \
  242. sReturn(sc); \
  243. sPush##Type(sc, value); \
  244. } \
  245. }
  246. static void sIfGoTo(Script* sc) {
  247. int32 gotoIndex = 0;
  248. int32 value = false;
  249. if(!sReadInt32(sc, &gotoIndex) && !sPopInt32(sc, &value) && !value) {
  250. sc->readIndex = gotoIndex;
  251. }
  252. }
  253. static void sPeekFalseGoTo(Script* sc) {
  254. int32 gotoIndex = 0;
  255. if(sReadInt32(sc, &gotoIndex)) {
  256. return;
  257. }
  258. Value* v = sPeekStack(sc, VT_INT);
  259. if(v != NULL && v->data.intValue == 0) {
  260. sc->readIndex = gotoIndex;
  261. }
  262. }
  263. static void sPeekTrueGoTo(Script* sc) {
  264. int32 gotoIndex = 0;
  265. if(sReadInt32(sc, &gotoIndex)) {
  266. return;
  267. }
  268. Value* v = sPeekStack(sc, VT_INT);
  269. if(v != NULL && v->data.intValue != 0) {
  270. sc->readIndex = gotoIndex;
  271. }
  272. }
  273. static void sNewArray(Script* sc) {
  274. int32 length = 0;
  275. int32 size = 0;
  276. if(sReadInt32(sc, &size) || sPopInt32(sc, &length)) {
  277. return;
  278. }
  279. Value* p = sPushStack(sc, 1);
  280. if(vSetType(p, VT_ARRAY) || vSetOffset(p, 0)) {
  281. sCannotSetValueType(sc);
  282. return;
  283. }
  284. p->data.intValue = asAllocate(&sc->arrays, size, length);
  285. if(p->data.intValue == -1) {
  286. sError(sc, "out of memory");
  287. } else if(p->data.intValue == -2) {
  288. sError(sc, "bad allocation");
  289. }
  290. }
  291. static void sLength(Script* sc) {
  292. Value* v = sPeekStack(sc, VT_ARRAY);
  293. if(v == NULL) {
  294. return;
  295. }
  296. sc->stackIndex--;
  297. SnuviArray* a = asGet(&sc->arrays, v->data.intValue);
  298. if(a == NULL) {
  299. sError(sc, "invalid heap pointer %d", v->data.intValue);
  300. return;
  301. }
  302. sPushInt32(sc, a->length);
  303. }
  304. static void sDereference(Script* sc) {
  305. int32 address = 0;
  306. if(sReadInt32(sc, &address)) {
  307. return;
  308. }
  309. Value* v = sPushStack(sc, 1);
  310. if(vSetType(v, VT_POINTER) || vSetOffset(v, address + sc->stackVarIndex)) {
  311. sCannotSetValueType(sc);
  312. return;
  313. }
  314. v->data.intValue = -1;
  315. }
  316. static void sGlobalDereference(Script* sc) {
  317. int32 address = 0;
  318. if(sReadInt32(sc, &address)) {
  319. return;
  320. }
  321. Value* v = sPushStack(sc, 1);
  322. if(vSetType(v, VT_POINTER) || vSetOffset(v, address)) {
  323. sCannotSetValueType(sc);
  324. return;
  325. }
  326. v->data.intValue = -1;
  327. }
  328. static void sDuplicateReference(Script* sc) {
  329. Value* v = sPeekStack(sc, VT_POINTER);
  330. if(v != NULL) {
  331. Value* copy = sPushStack(sc, 1);
  332. if(copy != NULL) {
  333. *copy = *v;
  334. }
  335. }
  336. }
  337. static void sAddReference(Script* sc) {
  338. int32 size = 0;
  339. int32 add = 0;
  340. if(sReadInt32(sc, &size) || sPopInt32(sc, &add)) {
  341. return;
  342. }
  343. Value* v = sPeekStack(sc, VT_POINTER);
  344. if(v != NULL) {
  345. if(vSetOffset(v, vGetOffset(*v) + add * size)) {
  346. sCannotSetValueType(sc);
  347. }
  348. } else {
  349. sc->error[0] = '\0';
  350. v = sPeekStack(sc, VT_ARRAY);
  351. if(vSetType(v, VT_POINTER) ||
  352. vSetOffset(v, vGetOffset(*v) + add * size)) {
  353. sCannotSetValueType(sc);
  354. }
  355. }
  356. }
  357. static void sPushStructReference(Script* sc) {
  358. int32 address = 0;
  359. if(sReadInt32(sc, &address)) {
  360. return;
  361. }
  362. Value* v = sPushStack(sc, 1);
  363. if(v != NULL) {
  364. int index = address + sc->stackVarIndex;
  365. if(index < 0 || index >= SCRIPT_STACK_SIZE) {
  366. sError(sc, "invalid struct reference address");
  367. return;
  368. }
  369. *v = sc->stack[index];
  370. }
  371. }
  372. static Value* sLoadFromPointer(Script* sc, Value* p, ValueType wantedType) {
  373. int32 offset = vGetOffset(*p);
  374. if(p->data.intValue < 0) {
  375. if(offset < 0 || offset >= SCRIPT_STACK_SIZE) {
  376. sError(sc, "invalid offset");
  377. return NULL;
  378. }
  379. Value* v = sc->stack + offset;
  380. ValueType type = vGetType(*v);
  381. if(type != wantedType && type != VT_NOT_SET) {
  382. sError(sc, "pointer did not point to %s but %s", vtGetName(type),
  383. vtGetName(type));
  384. return NULL;
  385. }
  386. return v;
  387. }
  388. SnuviArray* a = asGet(&sc->arrays, p->data.intValue);
  389. if(a == NULL) {
  390. sError(sc, "invalid heap pointer %d", p->data.intValue);
  391. return NULL;
  392. }
  393. if(offset >= a->realLength) {
  394. sError(sc, "invalid heap pointer offset %d %d", offset, a->realLength);
  395. return NULL;
  396. }
  397. return a->data + offset;
  398. }
  399. SnuviArray* sGetArray(Script* sc) {
  400. Value* v = sPeekStack(sc, VT_ARRAY);
  401. if(v == NULL) {
  402. return NULL;
  403. }
  404. sc->stackIndex--;
  405. return asGet(&sc->arrays, v->data.intValue);
  406. }
  407. Value* sPopStructPointer(Script* sc, ValueType type) {
  408. Value* v = sPeekStack(sc, VT_POINTER);
  409. if(v == NULL) {
  410. return NULL;
  411. }
  412. sc->stackIndex--;
  413. return sLoadFromPointer(sc, v, type);
  414. }
  415. static void sStoreInt32(Script* sc) {
  416. int32 i = 0;
  417. if(sPopInt32(sc, &i)) {
  418. return;
  419. }
  420. Value* v = sPeekStack(sc, VT_POINTER);
  421. if(v == NULL) {
  422. return;
  423. }
  424. sc->stackIndex--;
  425. v = sLoadFromPointer(sc, v, VT_INT);
  426. if(vSetType(v, VT_INT)) {
  427. sCannotSetValueType(sc);
  428. return;
  429. }
  430. v->data.intValue = i;
  431. }
  432. static void sStoreFloat(Script* sc) {
  433. float f = 0;
  434. if(sPopFloat(sc, &f)) {
  435. return;
  436. }
  437. Value* v = sPeekStack(sc, VT_POINTER);
  438. if(v == NULL) {
  439. return;
  440. }
  441. sc->stackIndex--;
  442. v = sLoadFromPointer(sc, v, VT_FLOAT);
  443. if(vSetType(v, VT_FLOAT)) {
  444. sCannotSetValueType(sc);
  445. return;
  446. }
  447. v->data.floatValue = f;
  448. }
  449. static void sStoreArray(Script* sc) {
  450. Value* array = sPeekStack(sc, VT_ARRAY);
  451. if(array == NULL) {
  452. return;
  453. }
  454. sc->stackIndex--;
  455. Value* v = sPeekStack(sc, VT_POINTER);
  456. if(v == NULL) {
  457. return;
  458. }
  459. sc->stackIndex--;
  460. v = sLoadFromPointer(sc, v, VT_ARRAY);
  461. if(v != NULL) {
  462. *v = *array;
  463. }
  464. }
  465. static void sLoadInt32(Script* sc) {
  466. Value* v = sPeekStack(sc, VT_POINTER);
  467. if(v == NULL) {
  468. return;
  469. }
  470. sc->stackIndex--;
  471. v = sLoadFromPointer(sc, v, VT_INT);
  472. if(v != NULL) {
  473. sPushInt32(sc, v->data.intValue);
  474. }
  475. }
  476. static void sLoadFloat(Script* sc) {
  477. Value* v = sPeekStack(sc, VT_POINTER);
  478. if(v == NULL) {
  479. return;
  480. }
  481. sc->stackIndex--;
  482. v = sLoadFromPointer(sc, v, VT_FLOAT);
  483. if(v != NULL) {
  484. sPushFloat(sc, v->data.floatValue);
  485. }
  486. }
  487. static void sLoadArray(Script* sc) {
  488. Value* v = sPeekStack(sc, VT_POINTER);
  489. if(v == NULL) {
  490. return;
  491. }
  492. sc->stackIndex--;
  493. v = sLoadFromPointer(sc, v, VT_ARRAY);
  494. if(v != NULL) {
  495. Value* array = sPushStack(sc, 1);
  496. if(array != NULL) {
  497. *array = *v;
  498. }
  499. }
  500. }
  501. static void sEqualArrays(Script* sc, bool wanted) {
  502. Value* a = sPeekStack(sc, VT_ARRAY);
  503. if(a == NULL) {
  504. return;
  505. }
  506. sc->stackIndex--;
  507. Value* b = sPeekStack(sc, VT_ARRAY);
  508. if(b == NULL) {
  509. return;
  510. }
  511. sc->stackIndex--;
  512. sPushInt32(sc, (vGetOffset(*a) == vGetOffset(*b) &&
  513. a->data.intValue == b->data.intValue) == wanted);
  514. }
  515. static void sCall(Script* sc) {
  516. int32 function = 0;
  517. if(sReadInt32(sc, &function)) {
  518. return;
  519. }
  520. if(gfsCall(sc, function)) {
  521. sError(sc, "invalid function call");
  522. }
  523. }
  524. static void sPushText(Script* sc) {
  525. int32 length;
  526. if(sReadInt32(sc, &length)) {
  527. return;
  528. }
  529. if(length < 0 || length > 65535) {
  530. sError(sc, "too large string");
  531. return;
  532. }
  533. Value* p = sPushStack(sc, 1);
  534. if(vSetType(p, VT_ARRAY) || vSetOffset(p, 0)) {
  535. sCannotSetValueType(sc);
  536. return;
  537. }
  538. p->data.intValue = asAllocate(&sc->arrays, 1, length);
  539. if(p->data.intValue == -1) {
  540. sError(sc, "out of memory");
  541. return;
  542. } else if(p->data.intValue == -2) {
  543. sError(sc, "bad allocation");
  544. return;
  545. }
  546. SnuviArray* a = asGet(&sc->arrays, p->data.intValue);
  547. if(a == NULL) {
  548. sError(sc, "cannot find text array");
  549. return;
  550. }
  551. for(int i = 0; i < length; i++) {
  552. sReadInt32(sc, &(a->data[i].data.intValue));
  553. if(vSetType(a->data + i, VT_INT)) {
  554. sCannotSetValueType(sc);
  555. return;
  556. }
  557. }
  558. }
  559. static Value* sChangeBase(Script* sc, char* c) {
  560. if(sRead(sc, c, sizeof(char))) {
  561. return NULL;
  562. }
  563. Value* p = sPeekStack(sc, VT_POINTER);
  564. if(p == NULL) {
  565. return NULL;
  566. }
  567. sc->stackIndex--;
  568. return sLoadFromPointer(sc, p, VT_INT);
  569. }
  570. static void sChange(Script* sc) {
  571. char c;
  572. Value* v = sChangeBase(sc, &c);
  573. if(v != NULL) {
  574. v->data.intValue += c;
  575. }
  576. }
  577. static void sPushBeforeChange(Script* sc) {
  578. char c;
  579. Value* v = sChangeBase(sc, &c);
  580. if(v != NULL) {
  581. sPushInt32(sc, v->data.intValue);
  582. v->data.intValue += c;
  583. }
  584. }
  585. static void sPushAfterChange(Script* sc) {
  586. char c;
  587. Value* v = sChangeBase(sc, &c);
  588. if(v != NULL) {
  589. v->data.intValue += c;
  590. sPushInt32(sc, v->data.intValue);
  591. }
  592. }
  593. static void sFloatToInt32(Script* sc) {
  594. Value* v = sPeekStack(sc, VT_FLOAT);
  595. if(vSetType(v, VT_INT)) {
  596. sCannotSetValueType(sc);
  597. return;
  598. }
  599. v->data.intValue = (int)v->data.floatValue;
  600. }
  601. static void sInt32ToFloat(Script* sc) {
  602. Value* v = sPeekStack(sc, VT_INT);
  603. if(vSetType(v, VT_FLOAT)) {
  604. sCannotSetValueType(sc);
  605. return;
  606. }
  607. v->data.floatValue = (float)v->data.intValue;
  608. }
  609. #define CASE_NUMBER_OP(name, op) \
  610. case OP_##name##_INT: NUMBER_OP(int32, Int32, op); return; \
  611. case OP_##name##_FLOAT: \
  612. NUMBER_OP(float, Float, op); \
  613. return;
  614. #define CASE_BOOL_OP(name, op) \
  615. case OP_##name##_INT: BOOL_OP(int32, Int32, op); return; \
  616. case OP_##name##_FLOAT: \
  617. BOOL_OP(float, Float, op); \
  618. return;
  619. #define CASE_TYPE(TYPE, Type, type) \
  620. case OP_RETURN_##TYPE: RETURN(type, Type); return; \
  621. case OP_EQUAL_##TYPE: BOOL_OP(type, Type, ==); return; \
  622. case OP_NOT_EQUAL_##TYPE: BOOL_OP(type, Type, !=); return;
  623. static void sConsumeInstruction(Script* sc) {
  624. Operation op = sReadOperation(sc);
  625. switch(op) {
  626. CASE_NUMBER_OP(ADD, +);
  627. CASE_NUMBER_OP(SUB, -);
  628. CASE_NUMBER_OP(MUL, *);
  629. CASE_BOOL_OP(LESS, <);
  630. CASE_BOOL_OP(LESS_EQUAL, <=);
  631. CASE_BOOL_OP(GREATER, >);
  632. CASE_BOOL_OP(GREATER_EQUAL, >=);
  633. CASE_TYPE(INT, Int32, int32);
  634. #pragma GCC diagnostic push
  635. #pragma GCC diagnostic ignored "-Wfloat-equal"
  636. CASE_TYPE(FLOAT, Float, float);
  637. case OP_DIV_FLOAT: DIVISION(float, Float); return;
  638. #pragma GCC diagnostic pop
  639. case OP_DIV_INT: DIVISION(int32, Int32); return;
  640. case OP_STORE_INT: sStoreInt32(sc); return;
  641. case OP_STORE_FLOAT: sStoreFloat(sc); return;
  642. case OP_LOAD_INT: sLoadInt32(sc); return;
  643. case OP_LOAD_FLOAT: sLoadFloat(sc); return;
  644. case OP_PUSH_PRE_CHANGE_INT: sPushAfterChange(sc); return;
  645. case OP_PUSH_POST_CHANGE_INT: sPushBeforeChange(sc); return;
  646. case OP_CHANGE_INT: sChange(sc); return;
  647. case OP_FLOAT_TO_INT: sFloatToInt32(sc); return;
  648. case OP_INT_TO_FLOAT: sInt32ToFloat(sc); return;
  649. case OP_BIT_AND_INT: NUMBER_OP(int32, Int32, &); return;
  650. case OP_BIT_OR_INT: NUMBER_OP(int32, Int32, |); return;
  651. case OP_BIT_XOR_INT: NUMBER_OP(int32, Int32, ^); return;
  652. case OP_LEFT_SHIFT_INT: NUMBER_OP(int32, Int32, <<); return;
  653. case OP_RIGHT_SHIFT_INT: NUMBER_OP(int32, Int32, >>); return;
  654. case OP_NOTHING: return;
  655. case OP_PUSH_INT: sPushInt32Value(sc); return;
  656. case OP_PUSH_FLOAT: sPushFloatValue(sc); return;
  657. case OP_PUSH_TEXT: sPushText(sc); return;
  658. case OP_MOD_INT: MODULE(int32, Int32); return;
  659. case OP_INVERT_SIGN_INT: INVERT_SIGN(int32, Int32); return;
  660. case OP_INVERT_SIGN_FLOAT: INVERT_SIGN(float, Float); return;
  661. case OP_NOT: sNot(sc); return;
  662. case OP_AND: BOOL_OP(int32, Int32, &&); return;
  663. case OP_OR: BOOL_OP(int32, Int32, ||); return;
  664. case OP_BIT_NOT_INT: sBitNotInt32(sc); return;
  665. case OP_LINE: sLine(sc); return;
  666. case OP_GOTO: sGoTo(sc); return;
  667. case OP_IF_GOTO: sIfGoTo(sc); return;
  668. case OP_PEEK_FALSE_GOTO: sPeekFalseGoTo(sc); return;
  669. case OP_PEEK_TRUE_GOTO: sPeekTrueGoTo(sc); return;
  670. case OP_GOSUB: sGoSub(sc); return;
  671. case OP_RETURN: sReturn(sc); return;
  672. case OP_RETURN_POINTER: sReturnPointer(sc); return;
  673. case OP_RESERVE: sReserveBytes(sc); return;
  674. case OP_GRESERVE: sGlobalReserveBytes(sc); return;
  675. case OP_DEREFERENCE_VAR: sDereference(sc); return;
  676. case OP_DEREFERENCE_GVAR: sGlobalDereference(sc); return;
  677. case OP_LOAD_ARRAY: sLoadArray(sc); return;
  678. case OP_DUPLICATE_REFERENCE: sDuplicateReference(sc); return;
  679. case OP_ADD_REFERENCE: sAddReference(sc); return;
  680. case OP_PUSH_STRUCT_REFERENCE: sPushStructReference(sc); return;
  681. case OP_NEW: sNewArray(sc); return;
  682. case OP_LENGTH: sLength(sc); return;
  683. case OP_STORE_ARRAY: sStoreArray(sc); return;
  684. case OP_EQUAL_POINTER: sEqualArrays(sc, true); return;
  685. case OP_NOT_EQUAL_POINTER: sEqualArrays(sc, false); return;
  686. case OP_CALL: sCall(sc); return;
  687. }
  688. sError(sc, "unknown operation %d", (int)op);
  689. }
  690. static bool sHasData(Script* sc) {
  691. return sc->readIndex < sc->code->length;
  692. }
  693. Script* sInit(ByteCode* code) {
  694. Script* sc = (Script*)malloc(sizeof(Script));
  695. sc->error[0] = '\0';
  696. sc->code = code;
  697. sc->readIndex = 0;
  698. sc->stackIndex = 0;
  699. sc->stackVarIndex = 0;
  700. sc->line = 0;
  701. asInit(&sc->arrays);
  702. return sc;
  703. }
  704. void sDelete(Script* sc) {
  705. bcDelete(sc->code);
  706. asDelete(&sc->arrays);
  707. free(sc);
  708. }
  709. void sRun(Script* sc) {
  710. while(sHasData(sc)) {
  711. sConsumeInstruction(sc);
  712. if(sc->error[0] != '\0') {
  713. return;
  714. }
  715. }
  716. }