worker.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. #include "worker.h"
  2. #include <furi_hal_resources.h>
  3. #include <furi.h>
  4. bool killswitch = false;
  5. int status = 0; //0: idle, 1: running, 2: failure
  6. char* inst = 0;
  7. int instCount = 0;
  8. int instPtr = 0;
  9. int runOpCount = 0;
  10. char* wOutput = 0;
  11. int wOutputPtr = 0;
  12. char* wInput = 0;
  13. int wInputPtr = 0;
  14. uint8_t* bfStack = 0;
  15. int stackPtr = 0;
  16. int stackSize = BF_STACK_INITIAL_SIZE;
  17. int stackSizeReal = 0;
  18. BFApp* wrkrApp = 0;
  19. void killThread() {
  20. killswitch = true;
  21. }
  22. bool validateInstPtr() {
  23. if(instPtr > instCount || instPtr < 0) {
  24. return false;
  25. }
  26. return true;
  27. }
  28. bool validateStackPtr() {
  29. if(stackPtr > stackSize || stackPtr < 0) {
  30. return false;
  31. }
  32. return true;
  33. }
  34. char* workerGetOutput() {
  35. return wOutput;
  36. }
  37. int getStackSize() {
  38. return stackSizeReal;
  39. }
  40. int getOpCount() {
  41. return runOpCount;
  42. }
  43. int getStatus() {
  44. return status;
  45. }
  46. void initWorker(BFApp* app) {
  47. wrkrApp = app;
  48. //rebuild output
  49. if(wOutput) {
  50. free(wOutput);
  51. }
  52. wOutput = (char*)malloc(BF_OUTPUT_SIZE);
  53. wOutputPtr = 0;
  54. //rebuild stack
  55. if(bfStack) {
  56. free(bfStack);
  57. }
  58. bfStack = (uint8_t*)malloc(BF_STACK_INITIAL_SIZE);
  59. memset(bfStack, 0x00, BF_STACK_INITIAL_SIZE);
  60. stackSize = BF_STACK_INITIAL_SIZE;
  61. stackSizeReal = 0;
  62. stackPtr = 0;
  63. //set instructions
  64. inst = wrkrApp->dataBuffer;
  65. instCount = wrkrApp->dataSize;
  66. instPtr = 0;
  67. runOpCount = 0;
  68. //set input
  69. wInput = wrkrApp->inputBuffer;
  70. wInputPtr = 0;
  71. //set status
  72. status = 0;
  73. }
  74. void rShift() {
  75. runOpCount++;
  76. stackPtr++;
  77. if(!validateStackPtr()) {
  78. status = 2;
  79. return;
  80. }
  81. while(stackPtr > stackSize) {
  82. stackSize += BF_STACK_STEP_SIZE;
  83. void* tmp = realloc(bfStack, stackSize);
  84. if(!tmp) {
  85. status = 2;
  86. return;
  87. }
  88. memset((tmp + stackSize) - BF_STACK_STEP_SIZE, 0x00, BF_STACK_STEP_SIZE);
  89. bfStack = (uint8_t*)tmp;
  90. };
  91. if(stackPtr > stackSizeReal) {
  92. stackSizeReal = stackPtr;
  93. }
  94. }
  95. void lShift() {
  96. runOpCount++;
  97. stackPtr--;
  98. if(!validateStackPtr()) {
  99. status = 2;
  100. return;
  101. }
  102. }
  103. void inc() {
  104. runOpCount++;
  105. if(!validateStackPtr()) {
  106. status = 2;
  107. return;
  108. }
  109. bfStack[stackPtr]++;
  110. }
  111. void dec() {
  112. runOpCount++;
  113. if(!validateStackPtr()) {
  114. status = 2;
  115. return;
  116. }
  117. bfStack[stackPtr]--;
  118. }
  119. void print() {
  120. runOpCount++;
  121. wOutput[wOutputPtr] = bfStack[stackPtr];
  122. wOutputPtr++;
  123. if(wOutputPtr > (BF_OUTPUT_SIZE - 1)) {
  124. wOutputPtr = 0;
  125. }
  126. }
  127. void input() {
  128. runOpCount++;
  129. bfStack[stackPtr] = (uint8_t)wInput[wInputPtr];
  130. if(wInput[wInputPtr] == 0x00 || wInputPtr >= 64) {
  131. wInputPtr = 0;
  132. } else {
  133. wInputPtr++;
  134. }
  135. }
  136. void loop() {
  137. runOpCount++;
  138. if(bfStack[stackPtr] == 0) {
  139. int loopCount = 1;
  140. while(loopCount > 0) {
  141. instPtr++;
  142. if(!validateInstPtr()) {
  143. status = 2;
  144. return;
  145. }
  146. if(inst[instPtr] == '[') {
  147. loopCount++;
  148. } else if(inst[instPtr] == ']') {
  149. loopCount--;
  150. }
  151. }
  152. }
  153. }
  154. void endLoop() {
  155. runOpCount++;
  156. if(bfStack[stackPtr] != 0) {
  157. int loopCount = 1;
  158. while(loopCount > 0) {
  159. instPtr--;
  160. if(!validateInstPtr()) {
  161. status = 2;
  162. return;
  163. }
  164. if(inst[instPtr] == ']') {
  165. loopCount++;
  166. } else if(inst[instPtr] == '[') {
  167. loopCount--;
  168. }
  169. }
  170. }
  171. }
  172. static const NotificationSequence led_on = {
  173. &message_blue_255,
  174. &message_do_not_reset,
  175. NULL,
  176. };
  177. static const NotificationSequence led_off = {
  178. &message_blue_0,
  179. NULL,
  180. };
  181. void input_kill(void* _ctx) {
  182. UNUSED(_ctx);
  183. killswitch = true;
  184. }
  185. void beginWorker() {
  186. status = 1;
  187. //redefined from furi_hal_resources.c
  188. const GpioPin gpio_button_back = {.port = GPIOC, .pin = LL_GPIO_PIN_13};
  189. while(inst[instPtr] != 0x00) {
  190. if(runOpCount % 500 == 0) {
  191. text_box_set_text(wrkrApp->text_box, workerGetOutput());
  192. notification_message(wrkrApp->notifications, &led_on);
  193. }
  194. //status 2 indicates failure
  195. if(status == 2) {
  196. status = 0;
  197. break;
  198. }
  199. //read back button directly to avoid weirdness in furi
  200. if(killswitch || !furi_hal_gpio_read(&gpio_button_back)) {
  201. status = 0;
  202. killswitch = false;
  203. break;
  204. }
  205. switch(inst[instPtr]) {
  206. case '>':
  207. rShift();
  208. break;
  209. case '<':
  210. lShift();
  211. break;
  212. case '+':
  213. inc();
  214. break;
  215. case '-':
  216. dec();
  217. break;
  218. case '.':
  219. print();
  220. break;
  221. case ',':
  222. input();
  223. break;
  224. case '[':
  225. loop();
  226. break;
  227. case ']':
  228. endLoop();
  229. break;
  230. default:
  231. break;
  232. }
  233. instPtr++;
  234. if(!validateInstPtr()) {
  235. status = 0;
  236. break;
  237. }
  238. }
  239. notification_message(wrkrApp->notifications, &led_off);
  240. text_box_set_text(wrkrApp->text_box, workerGetOutput());
  241. status = 0;
  242. }