205 lines
5.9 KiB
C
Executable file
205 lines
5.9 KiB
C
Executable file
/*
|
|
This code is part of the EIPA Platform
|
|
|
|
This code is the entry point of the EIPA Assembler and calls the needed functions to create the EIPA Image
|
|
It also is responsible for Argument Parsing
|
|
*/
|
|
|
|
#include <argp.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "../header/argp_commons.h"
|
|
#include "../header/common.h"
|
|
#include "../header/error_analyzer.h"
|
|
#include "../header/image_saver.h"
|
|
#include "../header/instruction_table.h"
|
|
#include "../header/labels.h"
|
|
#include "../header/lexer.h"
|
|
#include "../header/target_code_generator.h"
|
|
|
|
const char *argp_program_version =
|
|
VER_MAJOR "." VER_MINOR "." VER_PATCH " || " TAG;
|
|
|
|
const char *argp_program_bug_address = EIPA_BUG_ADRESS;
|
|
|
|
// Here, the argumets get stored by the parser, so acess them from here
|
|
struct cmd_arguments
|
|
{
|
|
char *input_file;
|
|
char *output_file;
|
|
unsigned short int print_tokens;
|
|
unsigned short int print_target_code;
|
|
};
|
|
|
|
// Parses the command line options & arguments
|
|
static error_t parser_function(int key, char *arg, struct argp_state *state)
|
|
{
|
|
struct cmd_arguments *save_arguments = state->input;
|
|
|
|
switch (key)
|
|
{
|
|
case 'o':
|
|
save_arguments->output_file = arg;
|
|
break;
|
|
case 't':
|
|
save_arguments->print_tokens = 1;
|
|
break;
|
|
case 'b':
|
|
save_arguments->print_target_code = 1;
|
|
break;
|
|
case ARGP_KEY_ARG:
|
|
// If we got more than one non-option argument
|
|
if (state->arg_num >= 1)
|
|
{
|
|
argp_usage(state);
|
|
}
|
|
save_arguments->input_file = arg;
|
|
break;
|
|
case ARGP_KEY_END:
|
|
// If we didn't receive 1 Argument yet
|
|
if (state->arg_num < 1)
|
|
{
|
|
argp_usage(state);
|
|
}
|
|
break;
|
|
default:
|
|
return ARGP_ERR_UNKNOWN;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// This array stores structs containing information about the cli options
|
|
static 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}
|
|
};
|
|
|
|
// Contains the neccesary stuff for argp
|
|
static struct argp argument_parser =
|
|
{
|
|
.options = argp_options,
|
|
.parser = parser_function,
|
|
.args_doc = ARGUMENT_DOC,
|
|
.doc = LONG_DOC};
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
// Parse CLI Arguments
|
|
// set defaults
|
|
struct cmd_arguments arguments;
|
|
arguments.output_file = DEFAULT_OUT_FILE;
|
|
arguments.input_file = "";
|
|
arguments.print_target_code = 0;
|
|
arguments.print_tokens = 0;
|
|
|
|
if (argp_parse(&argument_parser, argc, argv, 0, 0, &arguments) != 0)
|
|
{
|
|
printf("Error: Failed to parse CLI Arguments - Error code\n");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
// Tokenize the EIPA Assembly
|
|
FILE *assembly_file;
|
|
assembly_file = fopen(arguments.input_file, "r");
|
|
if (assembly_file == NULL)
|
|
{
|
|
printf("Error: Couldn't open input file\n");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
char(*label_tokens)[MAX_TOKEN_SIZE] = calloc(MAX_MEMORY, sizeof(*label_tokens));
|
|
if (label_tokens == NULL)
|
|
{
|
|
printf("Error: Could not allocate memory for the label_tokens array\n");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
lexer(assembly_file, label_tokens);
|
|
fclose(assembly_file);
|
|
|
|
// Part I of processing labels
|
|
shash_hashtable_t label_table;
|
|
shash_init_hashtable(&label_table, LABEL_TABLE_SIZE);
|
|
build_label_table(label_tokens, &label_table);
|
|
printf("Built label table\n");
|
|
|
|
char(*no_label_definition_tokens)[MAX_TOKEN_SIZE] = calloc(MAX_MEMORY, sizeof(*no_label_definition_tokens));
|
|
if (no_label_definition_tokens == NULL)
|
|
{
|
|
printf("Error: Could not allocate memory for the no_label_defintion_tokens array\n");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
remove_label_definition_tokens(label_tokens, no_label_definition_tokens);
|
|
printf("Removed label defintions\n");
|
|
free(label_tokens);
|
|
|
|
// Check if the EIPA Assembly contains errors with the no_label_definition_tokens array
|
|
shash_hashtable_t instruction_informations = create_instruction_information_hastable();
|
|
printf("Found %d errors\n", check_token_errors(no_label_definition_tokens, instruction_informations, label_table));
|
|
|
|
// Part II of processing labels
|
|
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;
|
|
}
|
|
replace_labels_with_adresses(no_label_definition_tokens, tokens, label_table, instruction_informations);
|
|
printf("Removed labels\n");
|
|
free(no_label_definition_tokens);
|
|
|
|
// Generate the target code
|
|
__uint32_t *target_code = calloc(MAX_MEMORY, sizeof(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;
|
|
}
|
|
|
|
// Save the target code to a file
|
|
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);
|
|
|
|
// Cleanup
|
|
destroy_instruction_information_hashtable(&instruction_informations);
|
|
shash_destroy_hashtable(&label_table);
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|