bcci.c 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /* bcci.c -- Brainfuck Component Competition interpreter :)
  2. Version 1.2, 12/19/04
  3. Daniel B Cristofani
  4. email cristofdathevanetdotcom
  5. http://www.hevanet.com/cristofd/brainfuck/ */
  6. /*Make any use you like of this software. I can't stop you anyway. :)*/
  7. /* This interpreter uses byte cells, and gives an error on overflow or
  8. underflow, or if the pointer is moved out of the array (whose size
  9. is defined in ARRAYSIZE). It translates newlines, and leaves cell
  10. values unchanged on end-of-file. It also reports the pointer's final
  11. location and the final values of all cells visited during execution,
  12. plus the number of brainfuck commands in the program, the number of
  13. commands executed (using Faase's [] semantics), and the amount of
  14. memory used, plus a composite score which is the product of these
  15. last three numbers.
  16. The pseudo-command '#' will zero all three numbers; this is to avoid
  17. scoring any framework which is needed to set things up before the
  18. execution of the component being tested, in the competition. */
  19. #include <stdio.h>
  20. #include <float.h>
  21. #include <math.h>
  22. #define ARRAYSIZE 65536
  23. #define CODESIZE 65536
  24. unsigned long stackp=CODESIZE, targets[CODESIZE];
  25. unsigned char array[ARRAYSIZE], code[CODESIZE];
  26. long p=0, q=0, length, c, max;
  27. unsigned long census[256];
  28. char *filename="";
  29. FILE *prog;
  30. double count=0, maxcount;
  31. void err(char *s){
  32. fprintf(stderr, "Error detected at byte %d of %s: %s!\n", q,filename,s);
  33. exit(1);
  34. }
  35. int main(int argc, char **argv){
  36. if (argc > 2) err("Too many arguments");
  37. if (argc < 2) err("I need a program filename");
  38. if(!(prog = fopen(argv[1], "r"))) err("Can't open that file");
  39. filename=argv[1];
  40. length = fread(code, 1, CODESIZE, prog);
  41. fclose(prog);
  42. maxcount=pow(FLT_RADIX, DBL_MANT_DIG);
  43. for(q=0; q<length; q++){
  44. ++census[code[q]];
  45. if (code[q]=='[') targets[--stackp]=q;
  46. if (code[q]==']'){
  47. if(stackp<CODESIZE) targets[targets[q]=targets[stackp++]]=q;
  48. else err("Unmatched ']'");
  49. }
  50. if (code[q]=='#') for (p='+'; p<=']'; p++) census[p]=0;
  51. }
  52. if(stackp<CODESIZE) q=targets[stackp], err("Unmatched '['");
  53. for(q=0,p=0;q<length;q++){
  54. switch(code[q]){
  55. case '+': if(array[p]++>=255) err("Overflow"); break;
  56. case '-': if(array[p]--<=0) err("Underflow"); break;
  57. case '<': p--; if(p<0) err("Too far left"); break;
  58. case '>': if(++p>max)max=p;if(p>=ARRAYSIZE)err("Too far right");
  59. break;
  60. #if '\n' == 10
  61. case ',': if((c=getchar())!= EOF) array[p]=c; break;
  62. case '.': putchar(array[p]); break;
  63. #else
  64. case ',': if((c=getchar())!=EOF) array[p]=c=='\n'?10:c; break;
  65. case '.': putchar(array[p]==10?'\n':array[p]); break;
  66. #endif
  67. case '[': if(!array[p]) q=targets[q]; break;
  68. case ']': if(array[p]) q=targets[q]; break;
  69. case '#': count=-1; max=0; break;
  70. default: count--;
  71. }
  72. if(count++>=maxcount) err("Command count overflow");
  73. }
  74. printf("Pointer: %ld\nFinal memory state:\n", p);
  75. for (p=0; p<=max;++p) printf(" %3d", array[p]);
  76. printf("\n\n");
  77. length=census['+']+census['-']+census['<']+census['>'];
  78. length+=census[',']+census['.']+census['[']+census[']'];
  79. printf("Program length: %ld.\nCommands executed: %.0f.\n", length,count);
  80. printf("Memory used: %ld.\nScore: %.0f.\n", max+1, length*count*(max+1));
  81. exit(0);
  82. }