Add Comments and refactor some code
This commit is contained in:
parent
244770c125
commit
e1c947a455
10 changed files with 140 additions and 45 deletions
6
TODO.txt
6
TODO.txt
|
@ -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
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
38
src/lexer.c
38
src/lexer.c
|
@ -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);
|
||||
}
|
||||
|
|
20
src/main.c
20
src/main.c
|
@ -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);
|
||||
|
||||
|
|
|
@ -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++;
|
||||
|
|
Loading…
Reference in a new issue