versert.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /*
  2. * TokigunStudio Versert Reference Interpreter
  3. * Copyright (c) 2005, Kang Seonghoon (Tokigun).
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a copy
  6. * of this software and associated documentation files (the "Software"), to deal
  7. * in the Software without restriction, including without limitation the rights
  8. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. * copies of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in all
  13. * copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21. * SOFTWARE.
  22. */
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #define BLOCK_WIDTH 64
  26. #define BLOCK_HEIGHT 64
  27. typedef signed int value_t;
  28. typedef unsigned char cell_t;
  29. typedef cell_t block_t[BLOCK_WIDTH][BLOCK_HEIGHT];
  30. typedef struct {
  31. /* vectors */
  32. value_t x, y, dx, dy, px, py;
  33. /* registers */
  34. value_t a, b;
  35. /* code space */
  36. value_t minx, miny, maxx, maxy;
  37. int nblock[4];
  38. block_t **block[4];
  39. } context_t;
  40. /******************************************************************************/
  41. context_t *context_alloc() {
  42. context_t *ptr;
  43. int i;
  44. ptr = malloc(sizeof(context_t));
  45. if(ptr != NULL) {
  46. ptr->x = 0; ptr->y = 0;
  47. ptr->dx = 1; ptr->dy = 0;
  48. ptr->px = 0; ptr->py = 0;
  49. ptr->a = 0; ptr->b = 0;
  50. ptr->minx = 0; ptr->miny = 0;
  51. ptr->maxx = 1; ptr->maxy = 1;
  52. for(i=0; i<4; i++) {
  53. ptr->block[i] = malloc(sizeof(block_t*));
  54. ptr->block[i][0] = NULL;
  55. ptr->nblock[i] = 1;
  56. }
  57. }
  58. return ptr;
  59. }
  60. void context_free(context_t *context) {
  61. int i, j;
  62. for(i=0; i<4; i++) {
  63. for(j=0; j<context->nblock[i]; j++) {
  64. if(context->block[i][j] != NULL)
  65. free(context->block[i][j]);
  66. }
  67. free(context->block[i]);
  68. }
  69. free(context);
  70. }
  71. int context_findcell(context_t *context, int *sign, int *block, value_t *x, value_t *y) {
  72. int temp;
  73. *sign = 0;
  74. if(*x < 0) { *sign |= 1; *x = ~*x; }
  75. if(*y < 0) { *sign |= 2; *y = ~*y; }
  76. temp = (*x / BLOCK_WIDTH) + (*y / BLOCK_HEIGHT);
  77. *block = temp * (temp + 1) / 2 + (*y / BLOCK_HEIGHT);
  78. *x %= BLOCK_WIDTH;
  79. *y %= BLOCK_HEIGHT;
  80. return (*block < context->nblock[*sign]);
  81. }
  82. cell_t context_getcell(context_t *context, value_t x, value_t y) {
  83. int sign, block;
  84. if(context_findcell(context, &sign, &block, &x, &y)) {
  85. block_t *current = context->block[sign][block];
  86. if(current != NULL) {
  87. return (*current)[x][y];
  88. }
  89. }
  90. return 32;
  91. }
  92. int context_putcell(context_t *context, value_t x, value_t y, cell_t c) {
  93. int sign, block;
  94. value_t realx, realy;
  95. block_t *current;
  96. realx = x; realy = y;
  97. if(!context_findcell(context, &sign, &block, &x, &y)) {
  98. block_t **ptr, **last;
  99. block++;
  100. ptr = realloc(context->block[sign], sizeof(block_t*) * block);
  101. if(ptr == NULL) return 0;
  102. context->block[sign] = ptr;
  103. last = ptr + block;
  104. ptr += context->nblock[sign];
  105. while(ptr < last) *ptr++ = NULL;
  106. context->nblock[sign] = block;
  107. block--;
  108. }
  109. current = context->block[sign][block];
  110. if(current == NULL) {
  111. int i, j;
  112. current = malloc(sizeof(block_t));
  113. if(current == NULL) return 0;
  114. for(i=0; i<BLOCK_WIDTH; i++)
  115. for(j=0; j<BLOCK_HEIGHT; j++)
  116. (*current)[i][j] = 32;
  117. context->block[sign][block] = current;
  118. }
  119. (*current)[x][y] = c;
  120. if(realx < context->minx) context->minx = realx;
  121. if(realx >= context->maxx) context->maxx = realx + 1;
  122. if(realy < context->miny) context->miny = realy;
  123. if(realy >= context->maxy) context->maxy = realy + 1;
  124. return 1;
  125. }
  126. int context_load(context_t *context, FILE *fp) {
  127. value_t x, y;
  128. cell_t ch, prev;
  129. if(fp == NULL) return 0;
  130. x = y = ch = 0;
  131. while(!feof(fp)) {
  132. prev = ch;
  133. ch = fgetc(fp);
  134. if(ch == '\n' && prev == '\r') continue;
  135. if(ch == '\n' || ch == '\r') {
  136. x = 0; y++;
  137. } else {
  138. context_putcell(context, x, y, ch);
  139. x++;
  140. }
  141. }
  142. return 1;
  143. }
  144. int context_step(context_t *context) {
  145. value_t temp;
  146. cell_t cur;
  147. cur = context_getcell(context, context->x, context->y);
  148. switch(cur) {
  149. case '0': case '1': case '2': case '3': case '4':
  150. case '5': case '6': case '7': case '8': case '9':
  151. context->a = cur - '0';
  152. break;
  153. case '+':
  154. context->b += context->a;
  155. break;
  156. case '-':
  157. context->b -= context->a;
  158. break;
  159. case '*':
  160. context->b *= context->a;
  161. break;
  162. case '~':
  163. temp = context->a;
  164. context->a = context->b;
  165. context->b = temp;
  166. break;
  167. case '<':
  168. if(context->a > context->b) {
  169. temp = context->a;
  170. context->a = context->b;
  171. context->b = temp;
  172. }
  173. break;
  174. case '>':
  175. if(context->a < context->b) {
  176. temp = context->a;
  177. context->a = context->b;
  178. context->b = temp;
  179. }
  180. break;
  181. case '/':
  182. temp = -context->dx;
  183. context->dx = -context->dy;
  184. context->dy = temp;
  185. break;
  186. case '\\':
  187. temp = context->dx;
  188. context->dx = context->dy;
  189. context->dy = temp;
  190. break;
  191. case '@':
  192. return 0;
  193. case '#':
  194. if(context->b == 0) {
  195. context->x += context->dx;
  196. context->y += context->dy;
  197. }
  198. break;
  199. case '.':
  200. putchar(context->a & 0xff);
  201. break;
  202. case ':':
  203. printf("%d", context->a);
  204. break;
  205. case ',':
  206. temp = getchar();
  207. if(temp != EOF) context->a = temp;
  208. break;
  209. case ';':
  210. if(scanf("%d", &temp) > 0) context->a = temp;
  211. break;
  212. case '{':
  213. context->b = context_getcell(context, context->px, context->py);
  214. break;
  215. case '|':
  216. context->px += context->a;
  217. context->py += context->b;
  218. break;
  219. case '}':
  220. if(!context_putcell(context, context->px, context->py, (cell_t)(context->b & 0xff))) {
  221. return -1;
  222. }
  223. break;
  224. }
  225. context->x += context->dx;
  226. context->y += context->dy;
  227. if(context->x < context->minx) context->x += context->maxx - context->minx;
  228. if(context->y < context->miny) context->y += context->maxy - context->miny;
  229. if(context->x >= context->maxx) context->x += context->minx - context->maxx;
  230. if(context->y >= context->maxy) context->y += context->miny - context->maxy;
  231. return 1;
  232. }
  233. /******************************************************************************/
  234. int main(int argc, char **argv) {
  235. FILE *fp;
  236. context_t *context;
  237. int goahead;
  238. if(argc != 2) {
  239. printf("TokigunStudio Versert Reference Interpreter\n");
  240. printf("Copyright (c) 2005, Kang Seonghoon (Tokigun).\n\n");
  241. printf("Usage: %s <filename>\n", argv[0]);
  242. return 0;
  243. }
  244. fp = fopen(argv[1], "rb");
  245. if(fp == NULL) {
  246. printf("Fatal Error: cannot open file.\n");
  247. return 1;
  248. }
  249. context = context_alloc();
  250. if(context == NULL) {
  251. printf("Fatal Error: no enough memory.\n");
  252. fclose(fp);
  253. return 2;
  254. }
  255. context_load(context, fp);
  256. fclose(fp);
  257. while(1) {
  258. goahead = context_step(context);
  259. if(goahead == 0) break;
  260. if(goahead == -1) {
  261. printf("Fatal Error: no enough memory.\n");
  262. context_free(context);
  263. return 2;
  264. }
  265. }
  266. context_free(context);
  267. return 0;
  268. }