Add Comments and refactor some code

This commit is contained in:
XOR 2023-02-13 10:28:28 +01:00
parent 244770c125
commit e1c947a455
10 changed files with 140 additions and 45 deletions

View file

@ -1,8 +1,8 @@
#Convert tokens to Machiene code
Check for Errors in the EIPA file (using the tokens)
Check for Errors in the EIPA Assembly (using the tokens)
#Save Machiene code in a file
Add command line options
COMMENTS!
#Add command line options
#COMMENTS!
function return errors + handling of those
Consider using a hashtable for the token array to eliminate the if else ladder in get_target_code

View file

@ -1,6 +1,8 @@
#ifndef _ARGP_COMMONS_H_
#define _ARGP_COMMONS_H_
#include "../header/common.h"
#define ARGUMENT_DOC "INPUT_FILE"
#define LONG_DOC "Argp test"
#define DEFAULT_OUT_FILE "a.eipaimg"

View file

@ -1,18 +1,40 @@
/*
This code is part of the EIPA Platform
Here, common macros are specified
*/
#ifndef _COMMON_H_
#define _COMMON_H_
#define MAX_MEMORY 1000000
// 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"
#define ASCII_TAB 9
#define ASCII_SPACE 32
#define ASCII_NEWLINE 10
#define INSTR_INP 0b0001
#define INSTR_OUT 0b0010
#define INSTR_LDA 0b0011
#define INSTR_STA 0b0100
#define INSTR_INC 0b0101
#define INSTR_DEC 0b0110
#define INSTR_JPP 0b0111
#define INSTR_JPZ 0b1000
#define INSTR_JPN 0b1001
#define INSTR_JPU 0b1010
#define INSTR_EOJ 0b1011
// get the character which the next fgetc() call would return
#define PREFGETC(file) *file->_IO_read_ptr
#endif

View file

@ -1,7 +1,9 @@
#ifndef _IMAGE_SAVER_H_
#define _IMAGE_SAVER_H_
// Save machine code from target_cde to file at out_path
#include <stdio.h>
// Save machine code from target_code to file at out_path. Returns 0 on success
int save_img(char *out_path, __uint32_t *target_code);
#endif

View file

@ -1,8 +1,9 @@
#include "../header/common.h"
#ifndef _LEXER_H_
#define _LEXER_H_
#include "../header/common.h"
#include <stdio.h>
//Convert the input_file into tokens
void lexer(FILE *input_file, char tokens[][MAX_TOKEN_SIZE]);

View file

@ -3,7 +3,7 @@
#ifndef _TAGET_CODE_GENERATOR_H_
#define _TAGET_CODE_GENERATOR_H_
// Get a machine code instruction from opcode and and optional adress
// Get a machine code instruction from opcode and and optional adress. Returns 0 on failure
__uint32_t get_target_instruction(__uint8_t opcode, __uint8_t use_adress, __uint32_t adress);
// Generate the machine code from tokens into target_code

View file

@ -1,6 +1,16 @@
/*
This code is part of the EIPA Platform
This code contains the implementations of all functions related to saving EIPA target code to an EIPA image
*/
#include <stdio.h>
#include <errno.h>
int save_img(char *out_path, __uint32_t *target_code){
FILE *out_file = fopen(out_path, "wb");
if(out_file == NULL) return EIO;
// Count instructions
unsigned int count = 0;
while(target_code[count]!=0)
@ -8,10 +18,11 @@ int save_img(char *out_path, __uint32_t *target_code){
count++;
}
FILE *out_file = fopen(out_path, "wb");
if(out_file == NULL) return -1;
fwrite(target_code, sizeof(__uint32_t), count, out_file);
return 0;
if (fwrite(target_code, sizeof(target_code), count, out_file) != count)
{
// Couldn't save the image
return EIO;
}
return count;
}

View file

@ -1,3 +1,9 @@
/*
This code is part of the EIPA Platform
This code contains the implementations of all functions related to the lexical analysis of the EIPA Assembly file
*/
#include <stdio.h>
#include <string.h>
@ -5,48 +11,66 @@
void lexer(FILE *input_file, char tokens[][MAX_TOKEN_SIZE])
{
// Stores the current character we are examining
char current_char = 0;
// Stores at which token current_char is
unsigned int token_index = 0;
// Stores wether current_char is the beginning of a line, so that we can skip any indentation at that point
short unsigned int is_pos_line_start = 1;
// Loop trough all characters in the file
while ((current_char = fgetc(input_file)) != EOF)
{
if (is_pos_line_start)
{
is_pos_line_start = 0;
// Loop trough Spaces and Tabs, to make empty lines and Indentation work
is_pos_line_start = 0;
while (current_char != EOF && (current_char == ASCII_SPACE || current_char == ASCII_TAB || current_char == ASCII_NEWLINE))
{
current_char = fgetc(input_file);
}
}
switch (current_char)
{
case EOF:
break;
case ASCII_TAB:
case ASCII_SPACE:
// This is an indice of a new token begining, so we probably need to increase token_index
// Loop to the characters until the next character fgetc() would read is not space or tab
while (PREFGETC(input_file) == ASCII_SPACE || PREFGETC(input_file) == ASCII_TAB) // The character which fgetc will read the next time when its called
while (PREFGETC(input_file) == ASCII_SPACE || PREFGETC(input_file) == ASCII_TAB)
{
current_char = fgetc(input_file);
}
// Between the Adress and the newline in an Instruction is usually no space.
// Therefore the token_index gets increased, whenever a newline is found.
// However, there can also be a space between the Adress and the newline.
// To not increase the token_index 2 times, we need to not increase it here if the next character is a \n
/*
Between the Adress and the newline in an Instruction is usually no space.
Therefore the token_index gets increased, whenever a newline is found.
However, there can also be a space between the Adress and the newline.
To not increase the token_index 2 times, we need to not increase it here if the next character is a \n
*/
if (PREFGETC(input_file) != ';' && PREFGETC(input_file) != ASCII_NEWLINE)
{
token_index++;
}
break;
case ASCII_NEWLINE:
// This is a indice of a new token -> increase token_index
token_index++;
// This also is a indice of a new instruction beginning
// in the tokens array, instructions are seperated by semicolons
tokens[token_index][0] = ';';
// Since the Instruction seperator (';') is also a token, we need to increase token_index again
token_index++;
is_pos_line_start = 1;
break;
case ';':
while (PREFGETC(input_file) != ASCII_NEWLINE) // The character which fgetc will read the next time when its called
// Loop over the comment
while (PREFGETC(input_file) != ASCII_NEWLINE)
{
current_char = fgetc(input_file);
}

View file

@ -1,3 +1,10 @@
/*
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 <stdio.h>
#include <string.h>
#include <stdlib.h>
@ -14,10 +21,11 @@ struct cmd_arguments
{
char *input_file;
char *output_file;
int print_tokens;
int print_target_code;
unsigned short int print_tokens;
unsigned short int print_target_code;
};
// Parses the command line options & arguments
error_t parser_function(int key, char *arg, struct argp_state *state)
{
struct cmd_arguments *save_arguments = state->input;
@ -84,6 +92,7 @@ struct argp_option argp_options[] =
{0}
};
// Contains the neccesary stuff for argp
struct argp argument_parser =
{
.options = argp_options,
@ -94,7 +103,10 @@ struct argp argument_parser =
int main(int argc, char **argv)
{
// stores the CLI options
struct cmd_arguments arguments;
// set defaults
arguments.output_file = DEFAULT_OUT_FILE;
arguments.input_file = "";
arguments.print_target_code = 0;
@ -106,12 +118,14 @@ int main(int argc, char **argv)
FILE *assembly_file = fopen(arguments.input_file, "r");
if (assembly_file == NULL) return 0;
// Stores the generated tokens
char(*tokens)[MAX_TOKEN_SIZE] = malloc(sizeof(*tokens) * MAX_MEMORY);
lexer(assembly_file, tokens);
fclose(assembly_file);
// Stores the generated binary target code
__uint32_t *target_code = malloc(MAX_MEMORY * sizeof(target_code));
gen_target_code(tokens, target_code);
save_img(arguments.output_file, target_code);

View file

@ -1,3 +1,9 @@
/*
This code is part of the EIPA Platform
This code contains the implementations for all the functions related to the target code (binary) generation
*/
#include <stdio.h>
#include <string.h>
@ -5,38 +11,51 @@
__uint32_t get_target_instruction(__uint8_t opcode, __uint8_t use_adress, __uint32_t adress)
{
// stores the value of the instructions
__uint32_t instruction = 0;
instruction = instruction | opcode << 28;
// move the opcode bytes to the left of the instruction
instruction = instruction | opcode << (32-4);
if (!use_adress)
{
return instruction;
}
if (adress >= 268435456)
if (adress >= MAX_MEMORY)
{
return 0;
}
// store the adress without modifing the opcode
instruction = instruction | adress;
return instruction;
}
void 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;
// stores which instruction we are currently looking at
unsigned int instruction_index = 0;
while (tokens[token_index][0] != EOF)
{
if (strcmp(tokens[token_index], ";") == 0)
{
// indice of a new instruction
instruction_index++;
}
else if (strcmp(tokens[token_index], "INP") == 0)
{
// Get adress from stored in next token index
// The address of the instructon is stored at the next token. Read that
token_index++;
__uint32_t adress;
sscanf(tokens[token_index], "%d", &adress);
target_code[instruction_index] = get_target_instruction(0b0001, 1, 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);
@ -44,12 +63,12 @@ void gen_target_code(char tokens[][MAX_TOKEN_SIZE], __uint32_t *target_code)
}
else if (strcmp(tokens[token_index], "OUT") == 0)
{
// Get adress from stored in next token index
// The address of the instructon is stored at the next token. Read that
token_index++;
__uint32_t adress;
sscanf(tokens[token_index], "%d", &adress);
target_code[instruction_index] = get_target_instruction(0b0010, 1, 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);
@ -57,12 +76,12 @@ void gen_target_code(char tokens[][MAX_TOKEN_SIZE], __uint32_t *target_code)
}
else if (strcmp(tokens[token_index], "LDA") == 0)
{
// Get adress from stored in next token index
// The address of the instructon is stored at the next token. Read that
token_index++;
__uint32_t adress;
sscanf(tokens[token_index], "%d", &adress);
target_code[instruction_index] = get_target_instruction(0b0011, 1, 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);
@ -70,12 +89,12 @@ void gen_target_code(char tokens[][MAX_TOKEN_SIZE], __uint32_t *target_code)
}
else if (strcmp(tokens[token_index], "STA") == 0)
{
// Get adress from stored in next token index
// The address of the instructon is stored at the next token. Read that
token_index++;
__uint32_t adress;
sscanf(tokens[token_index], "%d", &adress);
target_code[instruction_index] = get_target_instruction(0b0100, 1, 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);
@ -83,20 +102,20 @@ void gen_target_code(char tokens[][MAX_TOKEN_SIZE], __uint32_t *target_code)
}
else if (strcmp(tokens[token_index], "INC") == 0)
{
target_code[instruction_index] = get_target_instruction(0b0101, 0, 0);
target_code[instruction_index] = get_target_instruction(INSTR_INC, 0, 0);
}
else if (strcmp(tokens[token_index], "DEC") == 0)
{
target_code[instruction_index] = get_target_instruction(0b0110, 0, 0);
target_code[instruction_index] = get_target_instruction(INSTR_DEC, 0, 0);
}
else if (strcmp(tokens[token_index], "JPP") == 0)
{
// Get adress from stored in next token index
// The address of the instructon is stored at the next token. Read that
token_index++;
__uint32_t adress;
sscanf(tokens[token_index], "%d", &adress);
target_code[instruction_index] = get_target_instruction(0b0111, 1, 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);
@ -104,12 +123,12 @@ void gen_target_code(char tokens[][MAX_TOKEN_SIZE], __uint32_t *target_code)
}
else if (strcmp(tokens[token_index], "JPZ") == 0)
{
// Get adress from stored in next token index
// The address of the instructon is stored at the next token. Read that
token_index++;
__uint32_t adress;
sscanf(tokens[token_index], "%d", &adress);
target_code[instruction_index] = get_target_instruction(0b1000, 1, 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);
@ -117,12 +136,12 @@ void gen_target_code(char tokens[][MAX_TOKEN_SIZE], __uint32_t *target_code)
}
else if (strcmp(tokens[token_index], "JPN") == 0)
{
// Get adress from stored in next token index
// The address of the instructon is stored at the next token. Read that
token_index++;
__uint32_t adress;
sscanf(tokens[token_index], "%d", &adress);
target_code[instruction_index] = get_target_instruction(0b0101, 1, 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);
@ -130,12 +149,12 @@ void gen_target_code(char tokens[][MAX_TOKEN_SIZE], __uint32_t *target_code)
}
else if (strcmp(tokens[token_index], "JPU") == 0)
{
// Get adress from stored in next token index
// The address of the instructon is stored at the next token. Read that
token_index++;
__uint32_t adress;
sscanf(tokens[token_index], "%d", &adress);
target_code[instruction_index] = get_target_instruction(0b1010, 1, 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);
@ -143,7 +162,7 @@ void gen_target_code(char tokens[][MAX_TOKEN_SIZE], __uint32_t *target_code)
}
else if (strcmp(tokens[token_index], "EOJ") == 0)
{
target_code[instruction_index] = get_target_instruction(0b1011, 0, 0);
target_code[instruction_index] = get_target_instruction(INSTR_EOJ, 0, 0);
}
token_index++;