diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..08958a8 --- /dev/null +++ b/.clang-format @@ -0,0 +1,15 @@ +#BasedOnStyle: None +AlignTrailingComments: true +BreakBeforeBraces: Allman +ColumnLimit: 0 +IndentWidth: 4 +KeepEmptyLinesAtTheStartOfBlocks: false +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true +PointerBindsToType: false +SpacesBeforeTrailingComments: 1 +TabWidth: 4 +UseTab: Never + +AlignArrayOfStructures: Right +SpaceBeforeSquareBrackets: false diff --git a/.gitignore b/.gitignore index 374114a..29d9f46 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,7 @@ dkms.conf #Code editor .vscode/* compile_commands.json +.cache/* + +#Code analysis +softwipe*.* \ No newline at end of file diff --git a/TODO.txt b/TODO.txt index 309cae8..70f1c1f 100644 --- a/TODO.txt +++ b/TODO.txt @@ -4,5 +4,6 @@ Check for Errors in the EIPA Assembly (using the tokens) #Add command line options #COMMENTS! function return errors + handling of those +Consider what happens when the input file contains too many instructions or one token is too long -Consider using a hashtable for the token array to eliminate the if else ladder in get_target_code \ No newline at end of file +Consider using a hashtable for the token array to eliminate the if else ladder in get_target_code diff --git a/header/argp_commons.h b/header/argp_commons.h index 14fdb73..3c5fa76 100644 --- a/header/argp_commons.h +++ b/header/argp_commons.h @@ -11,6 +11,6 @@ const char *argp_program_version = VER_MAJOR "." VER_MINOR "." VER_PATCH " || " TAG; -const char *argp_program_bug_address = "eipabugs@outlook.com"; +const char *argp_program_bug_address = EIPA_BUG_ADRESS; #endif \ No newline at end of file diff --git a/header/common.h b/header/common.h index d1d6352..8caa831 100644 --- a/header/common.h +++ b/header/common.h @@ -9,12 +9,14 @@ Here, common macros are specified // Maximum Memory Adresses #define MAX_MEMORY 268435456 + // Maximum size (charachters) of one token #define MAX_TOKEN_SIZE 10 #define VER_MAJOR "0" #define VER_MINOR "1" #define VER_PATCH "0" + // alpha, beta or stable #define TAG "alpha" @@ -37,4 +39,7 @@ Here, common macros are specified // get the character which the next fgetc() call would return #define PREFGETC(file) *file->_IO_read_ptr +// const char *argp_program_bug_address = "eipabugs@outlook.com"; +#define EIPA_BUG_ADRESS "eipabugs@outlook.com" + #endif diff --git a/header/target_code_generator.h b/header/target_code_generator.h index fd9aafb..e4a6dee 100644 --- a/header/target_code_generator.h +++ b/header/target_code_generator.h @@ -3,13 +3,15 @@ #ifndef _TAGET_CODE_GENERATOR_H_ #define _TAGET_CODE_GENERATOR_H_ -// Get a machine code instruction from opcode and and optional adress. Returns 0 on failure +#include + +// Get a machine code instruction from opcode and and optional adress. Returns 0 if the provides adress is too big __uint32_t get_target_instruction(__uint8_t opcode, __uint8_t use_adress, __uint32_t adress); -// Generate the machine code from tokens into target_code -void gen_target_code(char tokens[][MAX_TOKEN_SIZE], __uint32_t *target_code); +// Generate the machine code from tokens into target_code. Returns 0 on success, errno integer on failure +int gen_target_code(char tokens[][MAX_TOKEN_SIZE], __uint32_t *target_code); //Print out the machine code in target_code void print_target_code(__uint32_t *target_code); -#endif \ No newline at end of file +#endif diff --git a/src/image_saver.c b/src/image_saver.c index 197beed..57c7df7 100644 --- a/src/image_saver.c +++ b/src/image_saver.c @@ -23,6 +23,6 @@ int save_img(char *out_path, __uint32_t *target_code){ // Couldn't save the image return EIO; } - return count; + return 0; } \ No newline at end of file diff --git a/src/lexer.c b/src/lexer.c index fe5e1e6..135891a 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -70,7 +70,7 @@ void lexer(FILE *input_file, char tokens[][MAX_TOKEN_SIZE]) break; case ';': // Loop over the comment - while (PREFGETC(input_file) != ASCII_NEWLINE) + while (PREFGETC(input_file) != ASCII_NEWLINE && PREFGETC(input_file) != '\0') { current_char = fgetc(input_file); } diff --git a/src/main.c b/src/main.c index 5a0705a..1bd1236 100644 --- a/src/main.c +++ b/src/main.c @@ -5,18 +5,18 @@ This code is the entry point of the EIPA Assembler and calls the needed function It also is responsible for Argument Parsing */ -#include -#include -#include #include +#include +#include +#include +#include "../header/argp_commons.h" #include "../header/common.h" +#include "../header/image_saver.h" #include "../header/lexer.h" #include "../header/target_code_generator.h" -#include "../header/image_saver.h" -#include "../header/argp_commons.h" -//Here, the argumets get stored by the parser, so acess them from here +// Here, the argumets get stored by the parser, so acess them from here struct cmd_arguments { char *input_file; @@ -50,7 +50,7 @@ error_t parser_function(int key, char *arg, struct argp_state *state) save_arguments->input_file = arg; break; case ARGP_KEY_END: - //If we didn't receive 1 Argument yet + // If we didn't receive 1 Argument yet if (state->arg_num < 1) { argp_usage(state); @@ -63,43 +63,36 @@ error_t parser_function(int key, char *arg, struct argp_state *state) } // This array stores structs containing information about the cli options -struct argp_option argp_options[] = -{ +struct argp_option argp_options[] = { - .name = "output", - .key = 'o', - .arg = "FILE", - .flags = 0, - .doc = "Output file", - .group = 0 - }, - { - .name = "print_tokens", - .key = 't', - .arg = 0, - .flags = 0, - .doc = "Print the tokens generated by the Lexer to stdout", - .group = 0 - }, - { - .name = "print_target_code", - .key = 'b', - .arg = 0, - .flags = 0, - .doc = "Print the (Binary) target code generated to stdout", - .group = 0 - }, - {0} + {.name = "output", + .key = 'o', + .arg = "FILE", + .flags = 0, + .doc = "Output file", + .group = 0}, + {.name = "print_tokens", + .key = 't', + .arg = 0, + .flags = 0, + .doc = "Print the tokens generated by the Lexer to stdout", + .group = 0}, + {.name = "print_target_code", + .key = 'b', + .arg = 0, + .flags = 0, + .doc = "Print the (Binary) target code generated to stdout", + .group = 0}, + {0} }; // Contains the neccesary stuff for argp struct argp argument_parser = -{ + { .options = argp_options, .parser = parser_function, .args_doc = ARGUMENT_DOC, - .doc = LONG_DOC -}; + .doc = LONG_DOC}; int main(int argc, char **argv) { @@ -112,26 +105,56 @@ int main(int argc, char **argv) arguments.print_target_code = 0; arguments.print_tokens = 0; - argp_parse(&argument_parser, argc, argv, 0, 0, &arguments); + if (argp_parse(&argument_parser, argc, argv, 0, 0, &arguments) != 0) + { + printf("Error: Failed to parse CLI Arguments - Error code\n"); + return EXIT_FAILURE; + } + FILE *assembly_file; + assembly_file = fopen(arguments.input_file, "r"); - FILE *assembly_file = fopen(arguments.input_file, "r"); - if (assembly_file == NULL) return 0; - + if (assembly_file == NULL) + return EXIT_FAILURE; + // Stores the generated tokens - char(*tokens)[MAX_TOKEN_SIZE] = malloc(sizeof(*tokens) * MAX_MEMORY); + char(*tokens)[MAX_TOKEN_SIZE] = calloc(MAX_MEMORY, sizeof(*tokens)); + + if(tokens == NULL){ + printf("Error: Could not allocate memory for the tokens array\n"); + return EXIT_FAILURE; + } + lexer(assembly_file, tokens); fclose(assembly_file); // Stores the generated binary target code - __uint32_t *target_code = malloc(MAX_MEMORY * sizeof(target_code)); + __uint32_t *target_code = calloc(MAX_MEMORY, sizeof(target_code)); - gen_target_code(tokens, target_code); - save_img(arguments.output_file, target_code); + if(target_code == NULL) + { + printf("Error: Could not allocate memory for the target code\n"); + return EXIT_FAILURE; + } + + int error = gen_target_code(tokens, target_code); + if (error != 0) + { + printf("Error: Could not generate target code - Error %s\n", strerror(error)); + return EXIT_FAILURE; + } + + if (save_img(arguments.output_file, target_code) != 0) + { + printf("Couldn't save the output file\n"); + exit(EXIT_FAILURE); + } // If the requested, we print the tokens and/or the target code - if (arguments.print_tokens) print_tokens(tokens); - if (arguments.print_target_code) print_target_code(target_code); + if (arguments.print_tokens) + print_tokens(tokens); + if (arguments.print_target_code) + print_target_code(target_code); - return 0; -} \ No newline at end of file + return EXIT_SUCCESS; +} diff --git a/src/target_code_generator.c b/src/target_code_generator.c index 09da3ca..7e51bf9 100644 --- a/src/target_code_generator.c +++ b/src/target_code_generator.c @@ -6,6 +6,8 @@ This code contains the implementations for all the functions related to the targ #include #include +#include +#include #include "../header/common.h" @@ -32,7 +34,7 @@ __uint32_t get_target_instruction(__uint8_t opcode, __uint8_t use_adress, __uint return instruction; } -void gen_target_code(char tokens[][MAX_TOKEN_SIZE], __uint32_t *target_code) +int gen_target_code(char tokens[][MAX_TOKEN_SIZE], __uint32_t *target_code) { // stores which token we are currently looking at unsigned int token_index = 0; @@ -56,9 +58,9 @@ void gen_target_code(char tokens[][MAX_TOKEN_SIZE], __uint32_t *target_code) sscanf(tokens[token_index], "%d", &adress); target_code[instruction_index] = get_target_instruction(INSTR_INP, 1, adress); - if (!target_code) - { - printf("Adress in %d. Instruction is too large\n", instruction_index); + if(target_code[instruction_index] == 0){ + printf("Error: Received andress bigger than %d\nThis error shoudn't occur! Please report at %s\n", MAX_MEMORY, EIPA_BUG_ADRESS); + return EOVERFLOW; } } else if (strcmp(tokens[token_index], "OUT") == 0) @@ -69,9 +71,9 @@ void gen_target_code(char tokens[][MAX_TOKEN_SIZE], __uint32_t *target_code) sscanf(tokens[token_index], "%d", &adress); target_code[instruction_index] = get_target_instruction(INSTR_OUT, 1, adress); - if (!target_code) - { - printf("Adress in %d. Instruction is too large\n", instruction_index); + if(target_code[instruction_index] == 0){ + printf("Error: Received andress bigger than %d\nThis error shoudn't occur! Please report at %s\n", MAX_MEMORY, EIPA_BUG_ADRESS); + return EOVERFLOW; } } else if (strcmp(tokens[token_index], "LDA") == 0) @@ -82,9 +84,9 @@ void gen_target_code(char tokens[][MAX_TOKEN_SIZE], __uint32_t *target_code) sscanf(tokens[token_index], "%d", &adress); target_code[instruction_index] = get_target_instruction(INSTR_LDA, 1, adress); - if (!target_code) - { - printf("Adress in %d. Instruction is too large\n", instruction_index); + if(target_code[instruction_index] == 0){ + printf("Error: Received andress bigger than %d\nThis error shoudn't occur! Please report at %s\n", MAX_MEMORY, EIPA_BUG_ADRESS); + return EOVERFLOW; } } else if (strcmp(tokens[token_index], "STA") == 0) @@ -95,18 +97,28 @@ void gen_target_code(char tokens[][MAX_TOKEN_SIZE], __uint32_t *target_code) sscanf(tokens[token_index], "%d", &adress); target_code[instruction_index] = get_target_instruction(INSTR_STA, 1, adress); - if (!target_code) - { - printf("Adress in %d. Instruction is too large\n", instruction_index); + if(target_code[instruction_index] == 0){ + printf("Error: Received andress bigger than %d\nThis error shoudn't occur! Please report at %s\n", MAX_MEMORY, EIPA_BUG_ADRESS); + return EOVERFLOW; } } else if (strcmp(tokens[token_index], "INC") == 0) { target_code[instruction_index] = get_target_instruction(INSTR_INC, 0, 0); + if(target_code[instruction_index] == 0){ + printf("Error: Received andress bigger than %d\nThis error shoudn't occur! Please report at %s\n", MAX_MEMORY, EIPA_BUG_ADRESS); + return EOVERFLOW; + } + } else if (strcmp(tokens[token_index], "DEC") == 0) { target_code[instruction_index] = get_target_instruction(INSTR_DEC, 0, 0); + if(target_code[instruction_index] == 0){ + printf("Error: Received andress bigger than %d\nThis error shoudn't occur! Please report at %s\n", MAX_MEMORY, EIPA_BUG_ADRESS); + return EOVERFLOW; + } + } else if (strcmp(tokens[token_index], "JPP") == 0) { @@ -116,9 +128,9 @@ void gen_target_code(char tokens[][MAX_TOKEN_SIZE], __uint32_t *target_code) sscanf(tokens[token_index], "%d", &adress); target_code[instruction_index] = get_target_instruction(INSTR_JPP, 1, adress); - if (!target_code) - { - printf("Adress in %d. Instruction is too large\n", instruction_index); + if(target_code[instruction_index] == 0){ + printf("Error: Received andress bigger than %d\nThis error shoudn't occur! Please report at %s\n", MAX_MEMORY, EIPA_BUG_ADRESS); + return EOVERFLOW; } } else if (strcmp(tokens[token_index], "JPZ") == 0) @@ -129,9 +141,9 @@ void gen_target_code(char tokens[][MAX_TOKEN_SIZE], __uint32_t *target_code) sscanf(tokens[token_index], "%d", &adress); target_code[instruction_index] = get_target_instruction(INSTR_JPZ, 1, adress); - if (!target_code) - { - printf("Adress in %d. Instruction is too large\n", instruction_index); + if(target_code[instruction_index] == 0){ + printf("Error: Received andress bigger than %d\nThis error shoudn't occur! Please report at %s\n", MAX_MEMORY, EIPA_BUG_ADRESS); + return EOVERFLOW; } } else if (strcmp(tokens[token_index], "JPN") == 0) @@ -142,9 +154,9 @@ void gen_target_code(char tokens[][MAX_TOKEN_SIZE], __uint32_t *target_code) sscanf(tokens[token_index], "%d", &adress); target_code[instruction_index] = get_target_instruction(INSTR_JPN, 1, adress); - if (!target_code) - { - printf("Adress in %d. Instruction is too large\n", instruction_index); + if(target_code[instruction_index] == 0){ + printf("Error: Received andress bigger than %d\nThis error shoudn't occur! Please report at %s\n", MAX_MEMORY, EIPA_BUG_ADRESS); + return EOVERFLOW; } } else if (strcmp(tokens[token_index], "JPU") == 0) @@ -155,18 +167,24 @@ void gen_target_code(char tokens[][MAX_TOKEN_SIZE], __uint32_t *target_code) sscanf(tokens[token_index], "%d", &adress); target_code[instruction_index] = get_target_instruction(INSTR_JPU, 1, adress); - if (!target_code) - { - printf("Adress in %d. Instruction is too large\n", instruction_index); - }; + if(target_code[instruction_index] == 0){ + printf("Error: Received andress bigger than %d\nThis error shoudn't occur! Please report at %s\n", MAX_MEMORY, EIPA_BUG_ADRESS); + return EOVERFLOW; + } } else if (strcmp(tokens[token_index], "EOJ") == 0) { target_code[instruction_index] = get_target_instruction(INSTR_EOJ, 0, 0); + if(target_code[instruction_index] == 0){ + printf("Error: Received andress bigger than %d\nThis error shoudn't occur! Please report at %s\n", MAX_MEMORY, EIPA_BUG_ADRESS); + return EOVERFLOW; + } + } token_index++; } + return EXIT_SUCCESS; } void print_target_code(__uint32_t *target_code) diff --git a/test/test_addr_to_big.eipa b/test/test_addr_to_big.eipa new file mode 100644 index 0000000..e2bb90b --- /dev/null +++ b/test/test_addr_to_big.eipa @@ -0,0 +1 @@ +INP 268435457; This adress is too big \ No newline at end of file