Script.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781
  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) ||
  311. vSetOffset(v, (uint32)(address + sc->stackVarIndex))) {
  312. sCannotSetValueType(sc);
  313. return;
  314. }
  315. v->data.intValue = -1;
  316. }
  317. static void sGlobalDereference(Script* sc) {
  318. int32 address = 0;
  319. if(sReadInt32(sc, &address)) {
  320. return;
  321. }
  322. Value* v = sPushStack(sc, 1);
  323. if(vSetType(v, VT_POINTER) || vSetOffset(v, (uint32)address)) {
  324. sCannotSetValueType(sc);
  325. return;
  326. }
  327. v->data.intValue = -1;
  328. }
  329. static void sDuplicateReference(Script* sc) {
  330. Value* v = sPeekStack(sc, VT_POINTER);
  331. if(v != NULL) {
  332. Value* copy = sPushStack(sc, 1);
  333. if(copy != NULL) {
  334. *copy = *v;
  335. }
  336. }
  337. }
  338. static void sAddReference(Script* sc) {
  339. int32 size = 0;
  340. int32 add = 0;
  341. if(sReadInt32(sc, &size) || sPopInt32(sc, &add)) {
  342. return;
  343. }
  344. Value* v = sPeekStack(sc, VT_POINTER);
  345. if(v != NULL) {
  346. if(vSetOffset(v, vGetOffset(*v) + (uint32)(add * size))) {
  347. sCannotSetValueType(sc);
  348. }
  349. } else {
  350. sc->error[0] = '\0';
  351. v = sPeekStack(sc, VT_ARRAY);
  352. if(vSetType(v, VT_POINTER) ||
  353. vSetOffset(v, vGetOffset(*v) + (uint32)(add * size))) {
  354. sCannotSetValueType(sc);
  355. }
  356. }
  357. }
  358. static void sPushStructReference(Script* sc) {
  359. int32 address = 0;
  360. if(sReadInt32(sc, &address)) {
  361. return;
  362. }
  363. Value* v = sPushStack(sc, 1);
  364. if(v != NULL) {
  365. int index = address + sc->stackVarIndex;
  366. if(index < 0 || index >= SCRIPT_STACK_SIZE) {
  367. sError(sc, "invalid struct reference address");
  368. return;
  369. }
  370. *v = sc->stack[index];
  371. }
  372. }
  373. static Value* sLoadFromPointer(Script* sc, Value* p, ValueType wantedType) {
  374. uint32 offset = vGetOffset(*p);
  375. if(p->data.intValue < 0) {
  376. if(offset >= SCRIPT_STACK_SIZE) {
  377. sError(sc, "load offset overflow");
  378. return NULL;
  379. }
  380. Value* v = sc->stack + offset;
  381. ValueType type = vGetType(*v);
  382. if(type != wantedType && type != VT_NOT_SET) {
  383. sError(sc, "pointer did not point to %s but %s", vtGetName(type),
  384. vtGetName(type));
  385. return NULL;
  386. }
  387. return v;
  388. }
  389. SnuviArray* a = asGet(&sc->arrays, p->data.intValue);
  390. if(a == NULL) {
  391. sError(sc, "invalid heap pointer %d", p->data.intValue);
  392. return NULL;
  393. }
  394. if((int32)offset >= a->realLength) {
  395. sError(sc, "invalid heap pointer offset %u %d", offset, a->realLength);
  396. return NULL;
  397. }
  398. return a->data + offset;
  399. }
  400. SnuviArray* sGetArray(Script* sc) {
  401. Value* v = sPeekStack(sc, VT_ARRAY);
  402. if(v == NULL) {
  403. return NULL;
  404. }
  405. sc->stackIndex--;
  406. return asGet(&sc->arrays, v->data.intValue);
  407. }
  408. Value* sPopStructPointer(Script* sc, ValueType type) {
  409. Value* v = sPeekStack(sc, VT_POINTER);
  410. if(v == NULL) {
  411. return NULL;
  412. }
  413. sc->stackIndex--;
  414. return sLoadFromPointer(sc, v, type);
  415. }
  416. static void sStoreInt32(Script* sc) {
  417. int32 i = 0;
  418. if(sPopInt32(sc, &i)) {
  419. return;
  420. }
  421. Value* v = sPeekStack(sc, VT_POINTER);
  422. if(v == NULL) {
  423. return;
  424. }
  425. sc->stackIndex--;
  426. v = sLoadFromPointer(sc, v, VT_INT);
  427. if(vSetType(v, VT_INT)) {
  428. sCannotSetValueType(sc);
  429. return;
  430. }
  431. v->data.intValue = i;
  432. }
  433. static void sStoreFloat(Script* sc) {
  434. float f = 0;
  435. if(sPopFloat(sc, &f)) {
  436. return;
  437. }
  438. Value* v = sPeekStack(sc, VT_POINTER);
  439. if(v == NULL) {
  440. return;
  441. }
  442. sc->stackIndex--;
  443. v = sLoadFromPointer(sc, v, VT_FLOAT);
  444. if(vSetType(v, VT_FLOAT)) {
  445. sCannotSetValueType(sc);
  446. return;
  447. }
  448. v->data.floatValue = f;
  449. }
  450. static void sStoreArray(Script* sc) {
  451. Value* array = sPeekStack(sc, VT_ARRAY);
  452. if(array == NULL) {
  453. return;
  454. }
  455. sc->stackIndex--;
  456. Value* v = sPeekStack(sc, VT_POINTER);
  457. if(v == NULL) {
  458. return;
  459. }
  460. sc->stackIndex--;
  461. v = sLoadFromPointer(sc, v, VT_ARRAY);
  462. if(v != NULL) {
  463. *v = *array;
  464. }
  465. }
  466. static void sLoadInt32(Script* sc) {
  467. Value* v = sPeekStack(sc, VT_POINTER);
  468. if(v == NULL) {
  469. return;
  470. }
  471. sc->stackIndex--;
  472. v = sLoadFromPointer(sc, v, VT_INT);
  473. if(v != NULL) {
  474. sPushInt32(sc, v->data.intValue);
  475. }
  476. }
  477. static void sLoadFloat(Script* sc) {
  478. Value* v = sPeekStack(sc, VT_POINTER);
  479. if(v == NULL) {
  480. return;
  481. }
  482. sc->stackIndex--;
  483. v = sLoadFromPointer(sc, v, VT_FLOAT);
  484. if(v != NULL) {
  485. sPushFloat(sc, v->data.floatValue);
  486. }
  487. }
  488. static void sLoadArray(Script* sc) {
  489. Value* v = sPeekStack(sc, VT_POINTER);
  490. if(v == NULL) {
  491. return;
  492. }
  493. sc->stackIndex--;
  494. v = sLoadFromPointer(sc, v, VT_ARRAY);
  495. if(v != NULL) {
  496. Value* array = sPushStack(sc, 1);
  497. if(array != NULL) {
  498. *array = *v;
  499. }
  500. }
  501. }
  502. static void sEqualArrays(Script* sc, bool wanted) {
  503. Value* a = sPeekStack(sc, VT_ARRAY);
  504. if(a == NULL) {
  505. return;
  506. }
  507. sc->stackIndex--;
  508. Value* b = sPeekStack(sc, VT_ARRAY);
  509. if(b == NULL) {
  510. return;
  511. }
  512. sc->stackIndex--;
  513. sPushInt32(sc, (vGetOffset(*a) == vGetOffset(*b) &&
  514. a->data.intValue == b->data.intValue) == wanted);
  515. }
  516. static void sCall(Script* sc) {
  517. int32 function = 0;
  518. if(sReadInt32(sc, &function)) {
  519. return;
  520. }
  521. if(gfsCall(sc, function)) {
  522. sError(sc, "invalid function call");
  523. }
  524. }
  525. static void sPushText(Script* sc) {
  526. int32 length;
  527. if(sReadInt32(sc, &length)) {
  528. return;
  529. }
  530. if(length < 0 || length > 65535) {
  531. sError(sc, "too large string");
  532. return;
  533. }
  534. Value* p = sPushStack(sc, 1);
  535. if(vSetType(p, VT_ARRAY) || vSetOffset(p, 0)) {
  536. sCannotSetValueType(sc);
  537. return;
  538. }
  539. p->data.intValue = asAllocate(&sc->arrays, 1, length);
  540. if(p->data.intValue == -1) {
  541. sError(sc, "out of memory");
  542. return;
  543. } else if(p->data.intValue == -2) {
  544. sError(sc, "bad allocation");
  545. return;
  546. }
  547. SnuviArray* a = asGet(&sc->arrays, p->data.intValue);
  548. if(a == NULL) {
  549. sError(sc, "cannot find text array");
  550. return;
  551. }
  552. for(int i = 0; i < length; i++) {
  553. sReadInt32(sc, &(a->data[i].data.intValue));
  554. if(vSetType(a->data + i, VT_INT)) {
  555. sCannotSetValueType(sc);
  556. return;
  557. }
  558. }
  559. }
  560. static Value* sChangeBase(Script* sc, char* c) {
  561. if(sRead(sc, c, sizeof(char))) {
  562. return NULL;
  563. }
  564. Value* p = sPeekStack(sc, VT_POINTER);
  565. if(p == NULL) {
  566. return NULL;
  567. }
  568. sc->stackIndex--;
  569. return sLoadFromPointer(sc, p, VT_INT);
  570. }
  571. static void sChange(Script* sc) {
  572. char c;
  573. Value* v = sChangeBase(sc, &c);
  574. if(v != NULL) {
  575. v->data.intValue += c;
  576. }
  577. }
  578. static void sPushBeforeChange(Script* sc) {
  579. char c;
  580. Value* v = sChangeBase(sc, &c);
  581. if(v != NULL) {
  582. sPushInt32(sc, v->data.intValue);
  583. v->data.intValue += c;
  584. }
  585. }
  586. static void sPushAfterChange(Script* sc) {
  587. char c;
  588. Value* v = sChangeBase(sc, &c);
  589. if(v != NULL) {
  590. v->data.intValue += c;
  591. sPushInt32(sc, v->data.intValue);
  592. }
  593. }
  594. static void sFloatToInt32(Script* sc) {
  595. Value* v = sPeekStack(sc, VT_FLOAT);
  596. if(vSetType(v, VT_INT)) {
  597. sCannotSetValueType(sc);
  598. return;
  599. }
  600. v->data.intValue = (int)v->data.floatValue;
  601. }
  602. static void sInt32ToFloat(Script* sc) {
  603. Value* v = sPeekStack(sc, VT_INT);
  604. if(vSetType(v, VT_FLOAT)) {
  605. sCannotSetValueType(sc);
  606. return;
  607. }
  608. v->data.floatValue = (float)v->data.intValue;
  609. }
  610. #define CASE_NUMBER_OP(name, op) \
  611. case OP_##name##_INT: NUMBER_OP(int32, Int32, op); return; \
  612. case OP_##name##_FLOAT: \
  613. NUMBER_OP(float, Float, op); \
  614. return;
  615. #define CASE_BOOL_OP(name, op) \
  616. case OP_##name##_INT: BOOL_OP(int32, Int32, op); return; \
  617. case OP_##name##_FLOAT: \
  618. BOOL_OP(float, Float, op); \
  619. return;
  620. #define CASE_TYPE(TYPE, Type, type) \
  621. case OP_RETURN_##TYPE: RETURN(type, Type); return; \
  622. case OP_EQUAL_##TYPE: BOOL_OP(type, Type, ==); return; \
  623. case OP_NOT_EQUAL_##TYPE: BOOL_OP(type, Type, !=); return;
  624. static void sConsumeInstruction(Script* sc) {
  625. Operation op = sReadOperation(sc);
  626. switch(op) {
  627. CASE_NUMBER_OP(ADD, +);
  628. CASE_NUMBER_OP(SUB, -);
  629. CASE_NUMBER_OP(MUL, *);
  630. CASE_BOOL_OP(LESS, <);
  631. CASE_BOOL_OP(LESS_EQUAL, <=);
  632. CASE_BOOL_OP(GREATER, >);
  633. CASE_BOOL_OP(GREATER_EQUAL, >=);
  634. CASE_TYPE(INT, Int32, int32);
  635. #pragma GCC diagnostic push
  636. #pragma GCC diagnostic ignored "-Wfloat-equal"
  637. CASE_TYPE(FLOAT, Float, float);
  638. case OP_DIV_FLOAT: DIVISION(float, Float); return;
  639. #pragma GCC diagnostic pop
  640. case OP_DIV_INT: DIVISION(int32, Int32); return;
  641. case OP_STORE_INT: sStoreInt32(sc); return;
  642. case OP_STORE_FLOAT: sStoreFloat(sc); return;
  643. case OP_LOAD_INT: sLoadInt32(sc); return;
  644. case OP_LOAD_FLOAT: sLoadFloat(sc); return;
  645. case OP_PUSH_PRE_CHANGE_INT: sPushAfterChange(sc); return;
  646. case OP_PUSH_POST_CHANGE_INT: sPushBeforeChange(sc); return;
  647. case OP_CHANGE_INT: sChange(sc); return;
  648. case OP_FLOAT_TO_INT: sFloatToInt32(sc); return;
  649. case OP_INT_TO_FLOAT: sInt32ToFloat(sc); return;
  650. case OP_BIT_AND_INT: NUMBER_OP(int32, Int32, &); return;
  651. case OP_BIT_OR_INT: NUMBER_OP(int32, Int32, |); return;
  652. case OP_BIT_XOR_INT: NUMBER_OP(int32, Int32, ^); return;
  653. case OP_LEFT_SHIFT_INT: NUMBER_OP(int32, Int32, <<); return;
  654. case OP_RIGHT_SHIFT_INT: NUMBER_OP(int32, Int32, >>); return;
  655. case OP_NOTHING: return;
  656. case OP_PUSH_INT: sPushInt32Value(sc); return;
  657. case OP_PUSH_FLOAT: sPushFloatValue(sc); return;
  658. case OP_PUSH_TEXT: sPushText(sc); return;
  659. case OP_MOD_INT: MODULE(int32, Int32); return;
  660. case OP_INVERT_SIGN_INT: INVERT_SIGN(int32, Int32); return;
  661. case OP_INVERT_SIGN_FLOAT: INVERT_SIGN(float, Float); return;
  662. case OP_NOT: sNot(sc); return;
  663. case OP_AND: BOOL_OP(int32, Int32, &&); return;
  664. case OP_OR: BOOL_OP(int32, Int32, ||); return;
  665. case OP_BIT_NOT_INT: sBitNotInt32(sc); return;
  666. case OP_LINE: sLine(sc); return;
  667. case OP_GOTO: sGoTo(sc); return;
  668. case OP_IF_GOTO: sIfGoTo(sc); return;
  669. case OP_PEEK_FALSE_GOTO: sPeekFalseGoTo(sc); return;
  670. case OP_PEEK_TRUE_GOTO: sPeekTrueGoTo(sc); return;
  671. case OP_GOSUB: sGoSub(sc); return;
  672. case OP_RETURN: sReturn(sc); return;
  673. case OP_RETURN_POINTER: sReturnPointer(sc); return;
  674. case OP_RESERVE: sReserveBytes(sc); return;
  675. case OP_GRESERVE: sGlobalReserveBytes(sc); return;
  676. case OP_DEREFERENCE_VAR: sDereference(sc); return;
  677. case OP_DEREFERENCE_GVAR: sGlobalDereference(sc); return;
  678. case OP_LOAD_ARRAY: sLoadArray(sc); return;
  679. case OP_DUPLICATE_REFERENCE: sDuplicateReference(sc); return;
  680. case OP_ADD_REFERENCE: sAddReference(sc); return;
  681. case OP_PUSH_STRUCT_REFERENCE: sPushStructReference(sc); return;
  682. case OP_NEW: sNewArray(sc); return;
  683. case OP_LENGTH: sLength(sc); return;
  684. case OP_STORE_ARRAY: sStoreArray(sc); return;
  685. case OP_EQUAL_POINTER: sEqualArrays(sc, true); return;
  686. case OP_NOT_EQUAL_POINTER: sEqualArrays(sc, false); return;
  687. case OP_CALL: sCall(sc); return;
  688. }
  689. sError(sc, "unknown operation %d", (int)op);
  690. }
  691. static bool sHasData(Script* sc) {
  692. return sc->readIndex < sc->code->length;
  693. }
  694. Script* sInit(ByteCode* code) {
  695. Script* sc = (Script*)malloc(sizeof(Script));
  696. sc->error[0] = '\0';
  697. sc->code = code;
  698. sc->readIndex = 0;
  699. sc->stackIndex = 0;
  700. sc->stackVarIndex = 0;
  701. sc->line = 0;
  702. asInit(&sc->arrays);
  703. return sc;
  704. }
  705. void sDelete(Script* sc) {
  706. bcDelete(sc->code);
  707. asDelete(&sc->arrays);
  708. free(sc);
  709. }
  710. void sRun(Script* sc) {
  711. while(sHasData(sc)) {
  712. sConsumeInstruction(sc);
  713. if(sc->error[0] != '\0') {
  714. return;
  715. }
  716. }
  717. }