PageRenderTime 24ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/Brainfuck/interpreter/bf.c

https://code.google.com/
C | 150 lines | 129 code | 17 blank | 4 comment | 27 complexity | e6a99c11b57409abc9fce9a6cf821f7c MD5 | raw file
  1. /*
  2. * A nive brainfuck interpreter.
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <assert.h>
  8. char *program(FILE *s)
  9. {
  10. assert(s);
  11. char *p; /* program */
  12. int ps; /* available program size */
  13. int pc; /* program counter */
  14. int inc; /* program size increase amount */
  15. int c; /* current character */
  16. int lb; /* loop balanced flag */
  17. p = NULL;
  18. ps = pc = 0;
  19. inc = 1000;
  20. lb = 0;
  21. while ((c = fgetc(s)) != EOF) {
  22. if (pc >= ps) {
  23. ps += inc;
  24. if ((p = realloc(p, ps)) == NULL) {
  25. perror("realloc");
  26. exit(EXIT_FAILURE);
  27. }
  28. }
  29. switch (c) {
  30. case '>':
  31. case '<':
  32. case '+':
  33. case '-':
  34. case '.':
  35. case ',':
  36. p[pc++] = c;
  37. break;
  38. case '[':
  39. p[pc++] = c;
  40. lb++;
  41. break;
  42. case ']':
  43. p[pc++] = c;
  44. lb--;
  45. break;
  46. default:
  47. /* Comments, ignore them. */
  48. break;
  49. }
  50. }
  51. if (pc >= ps) {
  52. ps++;
  53. if ((p = realloc(p, ps)) == NULL) {
  54. perror("realloc");
  55. exit(EXIT_FAILURE);
  56. }
  57. p[pc] = '\0';
  58. }
  59. assert(!lb || !p);
  60. return p;
  61. }
  62. int main(int argc, char *argv[])
  63. {
  64. FILE *pf; /* program file stream */
  65. char *p; /* program */
  66. int pc; /* program counter */
  67. char ci; /* current instruction */
  68. unsigned char *m; /* memory */
  69. int dc; /* data counter */
  70. int ml; /* memory limit */
  71. if (argc < 2) {
  72. printf("Usage: %s program\n", argv[0]);
  73. exit(EXIT_FAILURE);
  74. }
  75. if ((pf = fopen(argv[1], "r")) == NULL) {
  76. perror("fopen");
  77. exit(EXIT_FAILURE);
  78. }
  79. ml = 1000;
  80. if ((m = malloc(ml)) == NULL) {
  81. perror("malloc");
  82. exit(EXIT_FAILURE);
  83. }
  84. memset(m, '\0', ml);
  85. p = program(pf);
  86. pc = dc = 0;
  87. while ((ci = p[pc++])) {
  88. switch (ci) {
  89. case '>':
  90. dc++;
  91. break;
  92. case '<':
  93. dc--;
  94. break;
  95. case '+':
  96. m[dc]++;
  97. break;
  98. case '-':
  99. m[dc]--;
  100. break;
  101. case '.':
  102. putchar(m[dc]);
  103. break;
  104. case ',':
  105. m[dc] = getchar();
  106. break;
  107. case '[':
  108. if (m[dc] == 0) {
  109. for (int i = pc; p[i]; i++) {
  110. if (p[i] == ']') {
  111. pc = i + 1;
  112. break;
  113. }
  114. }
  115. }
  116. break;
  117. case ']':
  118. if (m[dc] != 0) {
  119. for (int i = pc; i >= 0; i--) {
  120. if (p[i] == '[') {
  121. pc = i + 1;
  122. break;
  123. }
  124. }
  125. }
  126. break;
  127. default:
  128. fprintf(stderr, "Invalid command: %c", ci);
  129. exit(EXIT_FAILURE);
  130. break;
  131. }
  132. }
  133. }