Guest User

Untitled

a guest
Feb 26th, 2026
287
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.20 KB | None | 0 0
  1. #include <stdint.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <unistd.h>
  6.  
  7. // dont change cuz we rely on wrap around of tape_idx(uint16_t)
  8. #define TAPE_SIZE 65536
  9.  
  10. char *get_ops(FILE *f) {
  11.   if (!f) {
  12.     return NULL;
  13.   }
  14.  
  15.   size_t capacity = 64;
  16.   size_t idx = 0;
  17.  
  18.   char *ops = malloc(capacity);
  19.   if (!ops) {
  20.     perror("malloc");
  21.     return NULL;
  22.   }
  23.  
  24.   for (int ch = fgetc(f); ch != EOF; ch = fgetc(f)) {
  25.     switch (ch) {
  26.     case '>':
  27.     case '<':
  28.     case '+':
  29.     case '-':
  30.     case '.':
  31.     case ',':
  32.     case '[':
  33.     case ']': {
  34.       if (idx + 1 >= capacity) {
  35.         capacity *= 2;
  36.         char *tmp = realloc(ops, capacity);
  37.         if (!tmp) {
  38.           free(ops);
  39.           perror("realloc");
  40.           return NULL;
  41.         }
  42.         ops = tmp;
  43.       }
  44.       ops[idx++] = (char)ch;
  45.       break;
  46.     }
  47.     default:
  48.       break;
  49.     }
  50.   }
  51.  
  52.   ops[idx] = '\0';
  53.   return ops;
  54. }
  55.  
  56. int64_t *calculate_offsets(const char *code) {
  57.   size_t len = strlen(code);
  58.  
  59.   int64_t *offsets = calloc(len, sizeof(int64_t));
  60.   if (!offsets) {
  61.     perror("calloc");
  62.     return NULL;
  63.   }
  64.  
  65.   size_t *stack = malloc(len * sizeof *stack);
  66.   if (!stack) {
  67.     perror("malloc");
  68.     free(offsets);
  69.     return NULL;
  70.   }
  71.  
  72.   size_t stack_top = 0;
  73.  
  74.   for (size_t i = 0; i < len; i++) {
  75.  
  76.     if (code[i] == '[') {
  77.       stack[stack_top++] = i;
  78.     } else if (code[i] == ']') {
  79.       if (stack_top == 0) {
  80.         fprintf(stderr, "Error: unmatched ']'\n");
  81.         free(stack);
  82.         free(offsets);
  83.         return NULL;
  84.       }
  85.  
  86.       size_t open = stack[--stack_top];
  87.       offsets[open] = i;
  88.       offsets[i] = open;
  89.  
  90.     } else if (code[i] == '>' || code[i] == '<' ||
  91.                code[i] == '+' || code[i] == '-') {
  92.  
  93.       char op = code[i];
  94.       int64_t count = 0;
  95.       size_t j;
  96.  
  97.       for (j = i; j < len && code[j] == op; j++) {
  98.         count++;
  99.       }
  100.  
  101.       offsets[i] = count;
  102.       i = j - 1;
  103.     }
  104.   }
  105.  
  106.   if (stack_top != 0) {
  107.     fprintf(stderr, "Error: unmatched '['\n");
  108.     free(stack);
  109.     free(offsets);
  110.     return NULL;
  111.   }
  112.  
  113.   free(stack);
  114.   return offsets;
  115. }
  116.  
  117. int execute_code(char *code) {
  118.   uint8_t *tape = calloc(TAPE_SIZE, sizeof(uint8_t));
  119.   if (!tape) {
  120.     perror("calloc");
  121.     return 1;
  122.   }
  123.  
  124.   int64_t *offsets = calculate_offsets(code);
  125.   if (!offsets) {
  126.     free(tape);
  127.     return 1;
  128.   }
  129.  
  130.   uint16_t tape_idx = 0;
  131.  
  132.   for (size_t code_idx = 0; code[code_idx] != '\0';) {
  133.  
  134.     switch (code[code_idx]) {
  135.  
  136.     case '>': {
  137.       int64_t count = offsets[code_idx];
  138.       tape_idx += (uint16_t)count;
  139.       code_idx += count;
  140.       break;
  141.     }
  142.  
  143.     case '<': {
  144.       int64_t count = offsets[code_idx];
  145.       tape_idx -= (uint16_t)count;
  146.       code_idx += count;
  147.       break;
  148.     }
  149.  
  150.     case '+': {
  151.       int64_t count = offsets[code_idx];
  152.       tape[tape_idx] += (uint8_t)count;
  153.       code_idx += count;
  154.       break;
  155.     }
  156.  
  157.     case '-': {
  158.       int64_t count = offsets[code_idx];
  159.       tape[tape_idx] -= (uint8_t)count;
  160.       code_idx += count;
  161.       break;
  162.     }
  163.  
  164.     case '.': {
  165.       write(STDOUT_FILENO, &tape[tape_idx], 1);
  166.       code_idx++;
  167.       break;
  168.     }
  169.  
  170.     case ',': {
  171.       fflush(stdout);
  172.       int input = getchar();
  173.       tape[tape_idx] = (input == EOF) ? 0 : (uint8_t)input;
  174.       code_idx++;
  175.       break;
  176.     }
  177.  
  178.     case '[': {
  179.       if (tape[tape_idx] == 0) {
  180.         code_idx = offsets[code_idx] + 1;
  181.       } else {
  182.         code_idx++;
  183.       }
  184.       break;
  185.     }
  186.  
  187.     case ']': {
  188.       if (tape[tape_idx] != 0) {
  189.         code_idx = offsets[code_idx] + 1;
  190.       } else {
  191.         code_idx++;
  192.       }
  193.       break;
  194.     }
  195.  
  196.     default:
  197.       code_idx++;
  198.       break;
  199.     }
  200.   }
  201.  
  202.   free(offsets);
  203.   free(tape);
  204.   return 0;
  205. }
  206.  
  207. int main(int argc, char *argv[]) {
  208.   if (argc < 2) {
  209.     fprintf(stderr, "Usage: %s /path/to/file\n", argv[0]);
  210.     return EXIT_FAILURE;
  211.   }
  212.  
  213.   FILE *f = fopen(argv[1], "r");
  214.   if (!f) {
  215.     perror("fopen");
  216.     return EXIT_FAILURE;
  217.   }
  218.  
  219.   char *code = get_ops(f);
  220.   fclose(f);
  221.  
  222.   if (!code) {
  223.     return EXIT_FAILURE;
  224.   }
  225.  
  226.   int res = execute_code(code);
  227.  
  228.   free(code);
  229.   return res;
  230. }
  231.  
Advertisement
Add Comment
Please, Sign In to add comment