#include #include #include #define FAIL(var, str, code) if (var == NULL) { \ fprintf(stderr, str"\n"); \ exit(1); \ } unsigned short int detect_command_type(char *command); unsigned short int detect_next_command(char *command, unsigned short int is_searching_for_second_next); unsigned short int detect_command_number(char *command); void interpret(char *command, unsigned short int *next, char *tape, unsigned short int *current_tape_pos); int main(int argc, char *argv[]) { if (argc < 3) return 1; char **stack; /* command stack */ unsigned short int s = 0; /* stack size */ char *_tmp_cell; _tmp_cell = strtok(argv[2], ";"); stack = malloc((s + 1) * sizeof(char*)); FAIL(stack, "error: could not allocate memory for stack variable.", 1) while (_tmp_cell != NULL) { if (s) stack = realloc(stack,(s + 1) * sizeof(char*)); // stack will not be realloced first time FAIL(stack, "error: could not reallocate memory for stack variable.", 1) stack[s] = malloc((strlen(_tmp_cell) + 1) * sizeof(char)); FAIL(stack, "error: could not allocate memory for cell in stack.", 1) strcpy(stack[s], _tmp_cell); s++; _tmp_cell = strtok(NULL, ";"); } unsigned short int next = 1; unsigned short int current_tape_pos = 0; char *tape; tape = malloc((strlen(argv[1]) + 1) * sizeof(char)); strcpy(tape, argv[1]); printf("tape before: \"%s\"\n", tape); while (next) for (int i = 0;i < s;i++) if (detect_command_number(stack[i]) == next) interpret(stack[i], &next, tape, ¤t_tape_pos); printf("tape after: \"%s\"\n", tape); free(stack); free(tape); return 0; } unsigned short int detect_command_type(char *command) { for (int i = 0;i < strlen(command);i++) { switch (command[i]) { case '>': return 1; case '<': return 2; case '^': return 3; case '|': return 4; case '!': return 5; case '?': return 6; } } return 0; } unsigned short int detect_next_command(char *command, unsigned short int is_searching_for_second_next) { unsigned short int type = detect_command_type(command); if (type == 5) return 0; unsigned short int number = 0; char *_command; char *_tmp_number; _command = malloc((strlen(command) + 1) * sizeof(char)); FAIL(_command, "error: could not allocate memory for _command variable.", 1) strcpy(_command, command); _tmp_number = strtok(_command, "><^|!?"); _tmp_number = strtok(NULL, "><^|!?"); if (is_searching_for_second_next) { if (type != 6) return 0; char *__tmp_number; /* it will be second next command number */ char *___tmp_number; /* it will be _tmp_number copy, so we do not hurt original _tmp_number with strtok */ ___tmp_number = malloc((strlen(_tmp_number) + 1) * sizeof(char)); FAIL(___tmp_number, "error: could not allocate memory for ___tmp_number variable.", 1) strcpy(___tmp_number, _tmp_number); __tmp_number = strtok(___tmp_number, ","); sscanf(__tmp_number, "%hd", &number); } else { sscanf(_tmp_number, "%hd", &number); } free(_command); return number; } unsigned short int detect_command_number(char *command) { unsigned short int number = 0; char *_command; char *_number; _command = malloc((strlen(command) + 1) * sizeof(char)); strcpy(_command, command); FAIL(_command, "error: could not allocate memory for _command variable.", 1) _number = strtok(_command, "><^|?!"); sscanf(_number, "%hd", &number); free(_command); return number; } void interpret(char *command, unsigned short int *next, char *tape, unsigned short int *current_tape_pos) { unsigned short int second_next = 0; switch (detect_command_type(command)) { case 1: if (*current_tape_pos == strlen(command)) FAIL(NULL, "erorr: current position is already at the end of the tape.", 1) *current_tape_pos++; break; case 2: if (*current_tape_pos == 0) FAIL(NULL, "erorr: current position is 0, can not move left.", 1) *current_tape_pos--; break; case 3: if (tape[*current_tape_pos] == '1') FAIL(NULL, "error: cell is not empty.", 1) tape[*current_tape_pos] = '1'; break; case 4: if (tape[*current_tape_pos] == '0') FAIL(NULL, "error: cell is already empty.", 1) tape[*current_tape_pos] = '0'; break; case 5: break; case 6: if (tape[*current_tape_pos] != '1') second_next = 1; break; } *next = detect_next_command(command, second_next); }