215 lines
6.5 KiB
C
Executable file
215 lines
6.5 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
|
|
*/
|
|
|
|
#ifndef WIN_COMPILE
|
|
#include <argp.h>
|
|
#else
|
|
#include "../header/argp/argp.h"
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdint.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"
|
|
#include "../header/dyn_buf.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, "rb");
|
|
if (assembly_file == NULL)
|
|
{
|
|
printf("Error: Couldn't open input file\n");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
dynamic_buffer_t label_tokens;
|
|
init_dynamic_buffer(&label_tokens, TABLE_INIT_SIZE * MAX_TOKEN_SIZE, TABLE_GROW_SIZE * MAX_TOKEN_SIZE);
|
|
if (label_tokens.buffer == NULL)
|
|
{
|
|
printf("Error: Could not create 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((char (*)[MAX_TOKEN_SIZE]) label_tokens.buffer, &label_table);
|
|
|
|
dynamic_buffer_t no_label_definition_tokens;
|
|
init_dynamic_buffer(&no_label_definition_tokens, TABLE_INIT_SIZE * MAX_TOKEN_SIZE, TABLE_GROW_SIZE * MAX_TOKEN_SIZE);
|
|
if (no_label_definition_tokens.buffer == NULL)
|
|
{
|
|
printf("Error: Could not allocate memory for the no_label_defintion_tokens array\n");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
remove_label_definition_tokens((char (*)[MAX_TOKEN_SIZE]) label_tokens.buffer, &no_label_definition_tokens);
|
|
free(label_tokens.buffer);
|
|
|
|
// 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((char (*)[MAX_TOKEN_SIZE]) no_label_definition_tokens.buffer, instruction_informations, label_table));
|
|
|
|
// Part II of processing labels
|
|
dynamic_buffer_t tokens;
|
|
init_dynamic_buffer(&tokens, TABLE_INIT_SIZE * MAX_TOKEN_SIZE, TABLE_GROW_SIZE * MAX_TOKEN_SIZE);
|
|
if (tokens.buffer == NULL)
|
|
{
|
|
printf("Error: Could not allocate memory for the tokens array\n");
|
|
return EXIT_FAILURE;
|
|
}
|
|
replace_labels_with_adresses((char (*)[MAX_TOKEN_SIZE]) no_label_definition_tokens.buffer, &tokens, label_table, instruction_informations);
|
|
free(no_label_definition_tokens.buffer);
|
|
|
|
// Generate the target code
|
|
dynamic_buffer_t target_code;
|
|
init_dynamic_buffer(&target_code, TARGET_CODE_INIT * sizeof(uint32_t), TARGET_CODE_GROW * sizeof(uint32_t));
|
|
if (target_code.buffer == NULL)
|
|
{
|
|
printf("Error: Could not allocate memory for the target code\n");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
int error = gen_target_code((char (*)[MAX_TOKEN_SIZE])tokens.buffer, &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, (uint32_t *)target_code.buffer) != 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((char (*)[MAX_TOKEN_SIZE])tokens.buffer);
|
|
if (arguments.print_target_code)
|
|
print_target_code((uint32_t *)target_code.buffer);
|
|
|
|
// Cleanup
|
|
destroy_instruction_information_hashtable(&instruction_informations);
|
|
shash_destroy_hashtable(&label_table);
|
|
free(target_code.buffer);
|
|
free(tokens.buffer);
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|