diff --git a/src/Makefile b/src/Makefile index b174caf..66a3ce7 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,5 +1,6 @@ SOURCES += \ - main.c + main.c \ + ir.c INCLUDES += diff --git a/src/ir.c b/src/ir.c new file mode 100644 index 0000000..6a5462d --- /dev/null +++ b/src/ir.c @@ -0,0 +1,283 @@ +#include "ir.h" + +#include +#include +#include +#include + +operation_t char_to_operation(int c) +{ + switch(c) + { + case '>': + return MEM_POINTER_ADD; + case '<': + return MEM_POINTER_SUB; + case '+': + return MEM_ADD; + case '-': + return MEM_SUB; + case '[': + return JUMP_IF_0; + case ']': + return JUMP_IF_NOT_0; + case '.': + return PRINT_CHAR; + case ',': + return GET_CHAR; + default: + return NONE; + } +} + +int process_operation_into_ir_file(FILE *ir_file, operation_t operation, operation_t *last_operation) +{ + if(operation == NONE) + { + return EXIT_SUCCESS; + } + + switch(operation) + { + case MEM_POINTER_ADD: + case MEM_POINTER_SUB: + case MEM_ADD: + case MEM_SUB: + if(operation == *last_operation) + { + operation++; // Go to advanced version of operation + + if(fseek(ir_file, -1, SEEK_CUR)) + { + fprintf(stderr, "Error seeking file: %d\n", errno); + return EXIT_FAILURE; + } + + if(fwrite(&operation, sizeof(operation_t), 1, ir_file) != 1) + { + fprintf(stderr, "Error writing file: %d\n", errno); + return EXIT_FAILURE; + } + + operand_t nb = 2; + + if(fwrite(&nb, sizeof(operand_t), 1, ir_file) != 1) + { + fprintf(stderr, "Error writing file: %d\n", errno); + return EXIT_FAILURE; + } + } + else if(operation + 1 == *last_operation) + { + operation++; + + operand_t nb; + + if(fseek(ir_file, -sizeof(operand_t), SEEK_CUR)) + { + fprintf(stderr, "Error seeking file: %d\n", errno); + return EXIT_FAILURE; + } + + if(fread(&nb, sizeof(operand_t), 1, ir_file) != 1) + { + fprintf(stderr, "Error reading file: %d\n", errno); + return EXIT_FAILURE; + } + + nb++; + + if(fseek(ir_file, -sizeof(operand_t), SEEK_CUR)) + { + fprintf(stderr, "Error seeking file: %d\n", errno); + return EXIT_FAILURE; + } + + if(fwrite(&nb, sizeof(operand_t), 1, ir_file) != 1) + { + fprintf(stderr, "Error writing file: %d\n", errno); + return EXIT_FAILURE; + } + } + else + { + if(fwrite(&operation, sizeof(operation_t), 1, ir_file) != 1) + { + fprintf(stderr, "Error writing file: %d\n", errno); + return EXIT_FAILURE; + } + } + + break; + + case JUMP_IF_0: + case JUMP_IF_NOT_0: + if(fwrite(&operation, sizeof(operation), 1, ir_file) != 1) + { + fprintf(stderr, "Error writing file: %d\n", errno); + return EXIT_FAILURE; + } + + operand_t jump_pos = 0; + + if(fwrite(&jump_pos, sizeof(operand_t), 1, ir_file) != 1) + { + fprintf(stderr, "Error writing file: %d\n", errno); + return EXIT_FAILURE; + } + + break; + + case PRINT_CHAR: + case GET_CHAR: + if(fwrite(&operation, sizeof(operation), 1, ir_file) != 1) + { + fprintf(stderr, "Error writing file: %d\n", errno); + return EXIT_FAILURE; + } + + break; + + default: + fprintf(stderr, "Error: invalid operation nb.\n"); + return EXIT_FAILURE; + } + + *last_operation = operation; + + return EXIT_SUCCESS; +} + +int calculate_jump_operands(FILE *ir_file) +{ + while(true) + { + operation_t operation; + + if(fread(&operation, sizeof(operation_t), 1, ir_file) != 1) + { + if(feof(ir_file)) + { + break; + } + else + { + fprintf(stderr, "Error reading file: %d\n", ferror(ir_file)); + return EXIT_FAILURE; + } + } + + if(operation == JUMP_IF_0) + { + long bracket_pos = ftell(ir_file); + + if(bracket_pos == -1) + { + fprintf(stderr, "Error getting file pointer: %d\n", errno); + return EXIT_FAILURE; + } + + // Find corresponding closing bracket index + for(size_t bracket_index = 1; bracket_index;) + { + operation_t operation_search; + + if(fread(&operation_search, sizeof(operation_t), 1, ir_file) != 1) + { + if(feof(ir_file)) + { + fprintf(stderr, "Reached end of file before finding closing bracket.\n"); + } + else + { + fprintf(stderr, "Error reading file: %d\n", ferror(ir_file)); + } + + return EXIT_FAILURE; + } + + switch(operation_search) + { + case MEM_POINTER_ADD_NB: + case MEM_POINTER_SUB_NB: + case MEM_ADD_NB: + case MEM_SUB_NB: + case JUMP_IF_NOT_0: + if(fseek(ir_file, sizeof(operand_t), SEEK_CUR)) + { + fprintf(stderr, "Error seeking file: %d\n", errno); + return EXIT_FAILURE; + } + break; + + default: + break; + } + + if(operation_search == JUMP_IF_0) + { + bracket_index++; + } + else if(operation_search == JUMP_IF_NOT_0) + { + bracket_index--; + } + } + + long corresponding_bracket_pos = ftell(ir_file); + + if(corresponding_bracket_pos == -1) + { + fprintf(stderr, "Error getting file pointer: %d\n", errno); + return EXIT_FAILURE; + } + + if(fseek(ir_file, -sizeof(operand_t), SEEK_CUR)) + { + fprintf(stderr, "Error seeking file: %d\n", errno); + return EXIT_FAILURE; + } + + operand_t bracket_pos_operand = (operand_t)bracket_pos + sizeof(operand_t); + + if(fwrite(&bracket_pos_operand, sizeof(operand_t), 1, ir_file) != 1) + { + fprintf(stderr, "Error writing file: %d\n", errno); + return EXIT_FAILURE; + } + + if(fseek(ir_file, bracket_pos, SEEK_SET)) + { + fprintf(stderr, "Error seeking file: %d\n", errno); + return EXIT_FAILURE; + } + + operand_t corresponding_bracket_pos_operand = (operand_t)corresponding_bracket_pos; + if(fwrite(&corresponding_bracket_pos_operand, sizeof(operand_t), 1, ir_file) != 1) + { + fprintf(stderr, "Error writing file: %d\n", errno); + return EXIT_FAILURE; + } + } + + switch(operation) + { + case MEM_POINTER_ADD_NB: + case MEM_POINTER_SUB_NB: + case MEM_ADD_NB: + case MEM_SUB_NB: + case JUMP_IF_NOT_0: + if(fseek(ir_file, sizeof(operand_t), SEEK_CUR)) + { + fprintf(stderr, "Error seeking file: %d\n", errno); + return EXIT_FAILURE; + } + break; + + default: + break; + } + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/src/ir.h b/src/ir.h new file mode 100644 index 0000000..dbd2350 --- /dev/null +++ b/src/ir.h @@ -0,0 +1,34 @@ +#ifndef _IR_H +#define _IR_H + +#include +#include + +// The advanced version of operations always have value = simple version + 1 +enum operations_t { + NONE, + MEM_POINTER_ADD, + MEM_POINTER_ADD_NB, + MEM_POINTER_SUB, + MEM_POINTER_SUB_NB, + MEM_ADD, + MEM_ADD_NB, + MEM_SUB, + MEM_SUB_NB, + JUMP_IF_0, + JUMP_IF_NOT_0, + PRINT_CHAR, + GET_CHAR +}; + +typedef uint8_t operation_t; + +typedef uint32_t operand_t; + +operation_t char_to_operation(int c); + +int process_operation_into_ir_file(FILE *ir_file, operation_t operation, operation_t *last_operation); + +int calculate_jump_operands(FILE *ir_file); + +#endif // _IR_H \ No newline at end of file diff --git a/src/main.c b/src/main.c index dc78e74..610a454 100644 --- a/src/main.c +++ b/src/main.c @@ -3,32 +3,12 @@ #include #include #include +#include "ir.h" #include -#define BRACKETS_NB_MAX 1024 #define DATA_SIZE_MAX 65536 - -// The advanced version of operations should always have value = simple version + 1 -enum operations_t { - NONE, - MEM_POINTER_ADD, - MEM_POINTER_ADD_NB, - MEM_POINTER_SUB, - MEM_POINTER_SUB_NB, - MEM_ADD, - MEM_ADD_NB, - MEM_SUB, - MEM_SUB_NB, - JUMP_IF_0, - JUMP_IF_NOT_0, - PRINT_CHAR, - GET_CHAR -}; - -typedef uint8_t operation_t; - -typedef int operand_t; +#define PROGRAM_SIZE_MAX 65536 int main(int argc, char *argv[]) { @@ -41,7 +21,7 @@ int main(int argc, char *argv[]) } FILE *program_file = NULL; - FILE *intermediate_representation_file = NULL; + FILE *ir_file = NULL; program_file = fopen(argv[1], "r"); if(program_file == NULL) @@ -50,14 +30,14 @@ int main(int argc, char *argv[]) goto end; } - intermediate_representation_file = tmpfile(); - if(intermediate_representation_file == NULL) + ir_file = tmpfile(); + if(ir_file == NULL) { fprintf(stderr, "Error creating tmp file: %d\n", errno); goto end; } - // Strip program file + // Convert into intermediate representation while(true) { int c = fgetc(program_file); @@ -75,326 +55,83 @@ int main(int argc, char *argv[]) break; } - operation_t operation = NONE; static operation_t last_operation = NONE; + operation_t operation = char_to_operation(c); - switch(c) + if(process_operation_into_ir_file(ir_file, operation, &last_operation)) { - case '>': - operation = MEM_POINTER_ADD; - break; - - case '<': - operation = MEM_POINTER_SUB; - break; - - case '+': - operation = MEM_ADD; - break; - - case '-': - operation = MEM_SUB; - break; - - case '[': - operation = JUMP_IF_0; - break; - - case ']': - operation = JUMP_IF_NOT_0; - break; - - case '.': - operation = PRINT_CHAR; - break; - - case ',': - operation = GET_CHAR; - break; - - default: - break; + goto end; } - - if(operation == NONE) - { - continue; - } - - switch(operation) - { - case MEM_POINTER_ADD: - case MEM_POINTER_SUB: - case MEM_ADD: - case MEM_SUB: - if(operation == last_operation) - { - operation++; // Go to advanced version of operation - - if(fseek(intermediate_representation_file, -1, SEEK_CUR)) - { - fprintf(stderr, "Error seeking file: %d\n", errno); - goto end; - } - - if(fwrite(&operation, sizeof(operation_t), 1, intermediate_representation_file) != 1) - { - fprintf(stderr, "Error writing file: %d\n", errno); - goto end; - } - - operand_t nb = 2; - - if(fwrite(&nb, sizeof(operand_t), 1, intermediate_representation_file) != 1) - { - fprintf(stderr, "Error writing file: %d\n", errno); - goto end; - } - } - else if(operation + 1 == last_operation) - { - operation++; - - operand_t nb; - - if(fseek(intermediate_representation_file, -sizeof(operand_t), SEEK_CUR)) - { - fprintf(stderr, "Error seeking file: %d\n", errno); - goto end; - } - - if(fread(&nb, sizeof(operand_t), 1, intermediate_representation_file) != 1) - { - fprintf(stderr, "Error reading file: %d\n", errno); - goto end; - } - - nb++; - - if(fseek(intermediate_representation_file, -sizeof(operand_t), SEEK_CUR)) - { - fprintf(stderr, "Error seeking file: %d\n", errno); - goto end; - } - - if(fwrite(&nb, sizeof(operand_t), 1, intermediate_representation_file) != 1) - { - fprintf(stderr, "Error writing file: %d\n", errno); - goto end; - } - } - else - { - if(fwrite(&operation, sizeof(operation_t), 1, intermediate_representation_file) != 1) - { - fprintf(stderr, "Error writing file: %d\n", errno); - goto end; - } - } - - break; - - case JUMP_IF_0: - case JUMP_IF_NOT_0: - if(fwrite(&operation, sizeof(operation), 1, intermediate_representation_file) != 1) - { - fprintf(stderr, "Error writing file: %d\n", errno); - goto end; - } - - operand_t jump_pos = 0; - - if(fwrite(&jump_pos, sizeof(operand_t), 1, intermediate_representation_file) != 1) - { - fprintf(stderr, "Error writing file: %d\n", errno); - goto end; - } - - break; - - case PRINT_CHAR: - case GET_CHAR: - if(fwrite(&operation, sizeof(operation), 1, intermediate_representation_file) != 1) - { - fprintf(stderr, "Error writing file: %d\n", errno); - goto end; - } - - break; - - default: - break; - } - - last_operation = operation; } if(fclose(program_file) == EOF) { program_file = NULL; - fprintf(stderr, "Error closing program file: %d\n", errno); - goto end; } program_file = NULL; - // Parse brackets - rewind(intermediate_representation_file); - - while(true) + if(fseek(ir_file, 0, SEEK_END)) { - operation_t operation; - size_t nb_read = fread(&operation, sizeof(operation_t), 1, intermediate_representation_file); - - if(nb_read != 1) - { - if(feof(intermediate_representation_file)) - { - break; - } - else - { - fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file)); - goto end; - } - } - - if(operation == JUMP_IF_0) - { - long bracket_pos = ftell(intermediate_representation_file); - - if(bracket_pos == -1) - { - fprintf(stderr, "Error getting file pointer: %d\n", errno); - goto end; - } - - // Find corresponding closing bracket index - for(size_t bracket_index = 1; bracket_index;) - { - operation_t operation_search; - nb_read = fread(&operation_search, sizeof(operation_t), 1, intermediate_representation_file); - - if(nb_read != 1) - { - if(feof(intermediate_representation_file)) - { - fprintf(stderr, "Reached end of file before finding closing bracket.\n"); - } - else - { - fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file)); - } - - goto end; - } - - switch(operation_search) - { - case MEM_POINTER_ADD_NB: - case MEM_POINTER_SUB_NB: - case MEM_ADD_NB: - case MEM_SUB_NB: - case JUMP_IF_NOT_0: - if(fseek(intermediate_representation_file, sizeof(operand_t), SEEK_CUR)) - { - fprintf(stderr, "Error seeking file: %d\n", errno); - goto end; - } - break; - - default: - break; - } - - if(operation_search == JUMP_IF_0) - { - bracket_index++; - } - else if(operation_search == JUMP_IF_NOT_0) - { - bracket_index--; - } - } - - long corresponding_bracket_pos = ftell(intermediate_representation_file); - - if(corresponding_bracket_pos == -1) - { - fprintf(stderr, "Error getting file pointer: %d\n", errno); - goto end; - } - - if(fseek(intermediate_representation_file, -sizeof(operand_t), SEEK_CUR)) - { - fprintf(stderr, "Error seeking file: %d\n", errno); - goto end; - } - - operand_t bracket_pos_operand = (operand_t)bracket_pos + sizeof(operand_t); - - if(fwrite(&bracket_pos_operand, sizeof(operand_t), 1, intermediate_representation_file) != 1) - { - fprintf(stderr, "Error writing file: %d\n", errno); - goto end; - } - - if(fseek(intermediate_representation_file, bracket_pos, SEEK_SET)) - { - fprintf(stderr, "Error seeking file: %d\n", errno); - goto end; - } - - operand_t corresponding_bracket_pos_operand = (operand_t)corresponding_bracket_pos; - if(fwrite(&corresponding_bracket_pos_operand, sizeof(operand_t), 1, intermediate_representation_file) != 1) - { - fprintf(stderr, "Error writing file: %d\n", errno); - goto end; - } - } - - switch(operation) - { - case MEM_POINTER_ADD_NB: - case MEM_POINTER_SUB_NB: - case MEM_ADD_NB: - case MEM_SUB_NB: - case JUMP_IF_NOT_0: - fseek(intermediate_representation_file, sizeof(operand_t), SEEK_CUR); - break; - - default: - break; - } + fprintf(stderr, "Error seeking file: %d\n", errno); + goto end; } - rewind(intermediate_representation_file); + long program_size = ftell(ir_file); + if(program_size == -1) + { + fprintf(stderr, "Error getting file pointer: %d\n", errno); + return EXIT_FAILURE; + } + + if(program_size > PROGRAM_SIZE_MAX) + { + fputs("Program too big.\n", stderr); + goto end; + } + + rewind(ir_file); + + if(calculate_jump_operands(ir_file)) + { + goto end; + } + + rewind(ir_file); + + uint8_t program[PROGRAM_SIZE_MAX]; + + if(fread(program, sizeof(uint8_t), program_size, ir_file) != program_size) + { + fprintf(stderr, "Error reading file: %d\n", errno); + goto end; + } + + if(fclose(ir_file)) + { + ir_file = NULL; + fprintf(stderr, "Error closing ir file: %d\n", errno); + goto end; + } + + ir_file = NULL; - // Program memory uint8_t mem[DATA_SIZE_MAX] = {0}; size_t mem_pointer = 0; - uint8_t nb_read; operand_t operand; + size_t program_pointer = 0; while(true) { - operation_t operation; - nb_read = fread(&operation, sizeof(operation_t), 1, intermediate_representation_file); + operation_t operation = program[program_pointer]; + program_pointer++; - if(nb_read != 1) + if(program_pointer > program_size) { - if(feof(intermediate_representation_file)) - { - break; - } - else - { - fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file)); - goto end; - } + break; } switch(operation) @@ -404,12 +141,8 @@ int main(int argc, char *argv[]) break; case MEM_POINTER_ADD_NB: - nb_read = fread(&operand, sizeof(operand_t), 1, intermediate_representation_file); - if(nb_read != 1) - { - fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file)); - goto end; - } + operand = *(operand_t *)&program[program_pointer]; + program_pointer += sizeof(operand_t); mem_pointer += operand; break; @@ -418,12 +151,8 @@ int main(int argc, char *argv[]) break; case MEM_POINTER_SUB_NB: - nb_read = fread(&operand, sizeof(operand_t), 1, intermediate_representation_file); - if(nb_read != 1) - { - fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file)); - goto end; - } + operand = *(operand_t *)&program[program_pointer]; + program_pointer += sizeof(operand_t); mem_pointer -= operand; break; @@ -432,12 +161,8 @@ int main(int argc, char *argv[]) break; case MEM_ADD_NB: - nb_read = fread(&operand, sizeof(operand_t), 1, intermediate_representation_file); - if(nb_read != 1) - { - fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file)); - goto end; - } + operand = *(operand_t *)&program[program_pointer]; + program_pointer += sizeof(operand_t); mem[mem_pointer] += operand; break; @@ -446,64 +171,21 @@ int main(int argc, char *argv[]) break; case MEM_SUB_NB: - nb_read = fread(&operand, sizeof(operand_t), 1, intermediate_representation_file); - if(nb_read != 1) - { - fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file)); - goto end; - } + operand = *(operand_t *)&program[program_pointer]; + program_pointer += sizeof(operand_t); mem[mem_pointer] -= operand; break; case JUMP_IF_0: - if(mem[mem_pointer] == 0) - { - nb_read = fread(&operand, sizeof(operand_t), 1, intermediate_representation_file); - if(nb_read != 1) - { - fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file)); - goto end; - } - - if(fseek(intermediate_representation_file, operand, SEEK_SET)) - { - fprintf(stderr, "Error seeking file: %d\n", errno); - goto end; - } - } - else - { - if(fseek(intermediate_representation_file, sizeof(operand_t), SEEK_CUR)) - { - fprintf(stderr, "Error seeking file: %d\n", errno); - goto end; - } - } - break; - case JUMP_IF_NOT_0: - if(mem[mem_pointer]) + if(operation == JUMP_IF_0 ? mem[mem_pointer] == 0 : mem[mem_pointer] != 0) { - nb_read = fread(&operand, sizeof(operand_t), 1, intermediate_representation_file); - if(nb_read != 1) - { - fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file)); - goto end; - } - - if(fseek(intermediate_representation_file, operand, SEEK_SET)) - { - fprintf(stderr, "Error seeking file: %d\n", errno); - goto end; - } + operand = *(operand_t *)&program[program_pointer]; + program_pointer = operand; } else { - if(fseek(intermediate_representation_file, sizeof(operand_t), SEEK_CUR)) - { - fprintf(stderr, "Error seeking file: %d\n", errno); - goto end; - } + program_pointer += sizeof(operand_t); } break; @@ -524,9 +206,9 @@ int main(int argc, char *argv[]) status = EXIT_SUCCESS; end: - if(intermediate_representation_file != NULL) + if(ir_file != NULL) { - if(fclose(intermediate_representation_file)) + if(fclose(ir_file)) { fprintf(stderr, "Error closing tmp file: %d\n", errno); }