sf2tab.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /*
  2. * Copyright (c)2005 Cat's Eye Technologies. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. *
  11. * Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in
  13. * the documentation and/or other materials provided with the
  14. * distribution.
  15. *
  16. * Neither the name of Cat's Eye Technologies nor the names of its
  17. * contributors may be used to endorse or promote products derived
  18. * from this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  23. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  24. * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  25. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  26. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  27. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  29. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  30. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  31. * OF THE POSSIBILITY OF SUCH DAMAGE.
  32. */
  33. /*
  34. * sf2tab.c
  35. * Smallfuck to lookup-table compiler.
  36. * $Id$
  37. */
  38. /*
  39. * Modified by Catatonic Porpoise <graue@oceanbase.org>
  40. * to reject program or tape sizes smaller than 1.
  41. */
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include <string.h>
  45. #include <unistd.h>
  46. int prog_size = 256;
  47. int tape_size = 8;
  48. int debug_level = 0;
  49. enum result {
  50. HALT,
  51. HANG,
  52. OFF_LEFT,
  53. OFF_RIGHT
  54. };
  55. struct state_bucket {
  56. struct state_bucket *next;
  57. char *t; /* tape contents */
  58. };
  59. struct state_bucket **state = NULL; /* array of bucket ptrs */
  60. void
  61. clear_state(void)
  62. {
  63. int i;
  64. /* init state if this is first access */
  65. if (state == NULL) {
  66. state = malloc(prog_size * sizeof(struct state_bucket *));
  67. for (i = 0; i < prog_size; i++) {
  68. state[i] = NULL;
  69. }
  70. }
  71. for (i = 0; i < prog_size; i++) {
  72. struct state_bucket *b = state[i];
  73. while (b != NULL) {
  74. struct state_bucket *t = b;
  75. b = b->next;
  76. free(t->t); /* free tape contents */
  77. free(t); /* free bucket itself */
  78. }
  79. state[i] = NULL;
  80. }
  81. }
  82. void
  83. save_state(int pc, char *t)
  84. {
  85. struct state_bucket *b;
  86. if (debug_level >= 2) {
  87. fprintf(stderr, "saving state (%d, '%s')\n", pc, t);
  88. }
  89. b = malloc(sizeof(struct state_bucket));
  90. b->t = strdup(t);
  91. b->next = state[pc];
  92. state[pc] = b;
  93. }
  94. int
  95. check_state(int pc, char *t)
  96. {
  97. struct state_bucket *b = state[pc];
  98. while (b != NULL) {
  99. if (memcmp(t, b->t, tape_size) == 0)
  100. return 1; /* yes, deja vu */
  101. b = b->next;
  102. }
  103. return 0; /* no, this is fresh */
  104. }
  105. enum result
  106. run(char *p, char *t)
  107. {
  108. int hd = 0, pc = 0, bc = 0;
  109. clear_state();
  110. for (;;) {
  111. save_state(pc, t); /* record our state */
  112. if (debug_level >= 3 && p[pc] != '\0') {
  113. fprintf(stderr, "executing '%c'\n", p[pc]);
  114. }
  115. switch (p[pc]) { /* dispatch on instr */
  116. case '\0':
  117. return HALT;
  118. case '>':
  119. hd++;
  120. if (hd > tape_size - 1)
  121. return OFF_RIGHT; /* ran off end of tape */
  122. break;
  123. case '<':
  124. hd--;
  125. if (hd < 0)
  126. return OFF_LEFT; /* ran off beg of tape */
  127. break;
  128. case '*':
  129. if (t[hd] == ' ')
  130. t[hd] = '*';
  131. else
  132. t[hd] = ' ';
  133. break;
  134. case '[':
  135. if (t[hd] == ' ') {
  136. bc = 1;
  137. while (bc > 0) {
  138. pc++;
  139. if (p[pc] == '[') {
  140. bc++;
  141. } else if (p[pc] == ']') {
  142. bc--;
  143. }
  144. }
  145. }
  146. break;
  147. case ']':
  148. bc = 1;
  149. while (bc > 0) {
  150. pc--;
  151. if (p[pc] == '[') {
  152. bc--;
  153. } else if (p[pc] == ']') {
  154. bc++;
  155. }
  156. }
  157. pc--;
  158. break;
  159. default:
  160. break;
  161. }
  162. pc++;
  163. if (check_state(pc, t)) /* total deja vu? */
  164. return HANG;
  165. }
  166. }
  167. void
  168. load(char *filename, char *p)
  169. {
  170. FILE *f;
  171. int pi = 0;
  172. char c;
  173. f = fopen(filename, "r");
  174. if (f == NULL) {
  175. fprintf(stderr, "Error: can't open '%s'\n", filename);
  176. exit(1);
  177. }
  178. for (;;) {
  179. if (feof(f) || pi == (prog_size - 1))
  180. break;
  181. c = (char)fgetc(f);
  182. if (c == '*' || c == '<' || c == '>' || c == '[' || c == ']')
  183. p[pi++] = c;
  184. }
  185. p[pi] = '\0';
  186. if (debug_level >= 2) {
  187. fprintf(stderr, "loaded program: '%s'\n", p);
  188. }
  189. }
  190. void
  191. usage(void)
  192. {
  193. fprintf(stderr, "Usage: sf2tab [-d] [-p progsize] [-t tapesize] filename\n");
  194. exit(1);
  195. }
  196. int
  197. main(int argc, char **argv)
  198. {
  199. char *p; /* program */
  200. char *t, *b; /* tape and backup tape */
  201. int r = 1; /* run # */
  202. int h; /* halt flag */
  203. int i; /* misc counter */
  204. int done = 0; /* all runs done flag */
  205. int ch; /* getopt character */
  206. /* get cmdline args */
  207. while ((ch = getopt(argc, argv, "dp:t:")) != -1) {
  208. switch ((char)ch) {
  209. case 'd':
  210. debug_level++;
  211. break;
  212. case 'p':
  213. prog_size = atoi(optarg);
  214. if (prog_size < 1)
  215. {
  216. fprintf(stderr, "Invalid program size, "
  217. "using 1\n");
  218. prog_size = 1;
  219. }
  220. break;
  221. case 't':
  222. tape_size = atoi(optarg);
  223. if (tape_size < 1)
  224. {
  225. fprintf(stderr, "Invalid tape size, using 1\n");
  226. tape_size = 1;
  227. }
  228. break;
  229. case '?':
  230. default:
  231. usage();
  232. }
  233. }
  234. argv += optind;
  235. argc -= optind;
  236. if (argc <= 0)
  237. usage();
  238. /* set up program */
  239. p = malloc(prog_size);
  240. load(argv[0], p);
  241. /* set up tape and backup tape */
  242. t = malloc(tape_size + 1);
  243. b = malloc(tape_size + 1);
  244. memset(t, ' ', tape_size);
  245. memset(b, ' ', tape_size);
  246. t[tape_size] = '\0';
  247. b[tape_size] = '\0';
  248. while (!done) {
  249. /* back up tape, run program, print result */
  250. memcpy(b, t, tape_size);
  251. if (debug_level >= 1) {
  252. fprintf(stderr, "run #%d, using tape '%s'\n", r, t);
  253. }
  254. h = run(p, t);
  255. printf("{ \"%s\", %d, \"%s\" },\n", b, h, t);
  256. fflush(stdout);
  257. /* restore tape backup and get next tape */
  258. memcpy(t, b, tape_size);
  259. i = tape_size - 1;
  260. loop: if (t[i] == ' ') {
  261. t[i] = '*';
  262. } else {
  263. t[i] = ' ';
  264. i--;
  265. if (i >= 0)
  266. goto loop;
  267. else
  268. done = 1;
  269. }
  270. r++;
  271. }
  272. exit(0);
  273. }