From 65c54a8986b3519c1949d280e58f46af2eceff85 Mon Sep 17 00:00:00 2001 From: exegete Date: Sat, 17 Oct 2020 16:40:23 +0300 Subject: float, constants, ets --- Makefile | 18 +- common/const.sts | 84 +++++++ enki/smack.c | 579 +++++++++++++++++++++++++++++++++++++++++++++ enki/strans.c | 652 +++++++++++++++++++++++++++++++++++++++++++++++++++ ia32/elf/begin.sts | 1 + ia32/elf/syscall.sts | 41 ++++ ia32/float/float.sts | 37 +++ ia32/ia32.sts | 1 - ia32/math.sts | 6 +- ia32/syscall.sts | 41 ---- smack.c | 579 --------------------------------------------- strans.c | 652 --------------------------------------------------- test.sts | 15 +- 13 files changed, 1415 insertions(+), 1291 deletions(-) create mode 100644 enki/smack.c create mode 100644 enki/strans.c create mode 100644 ia32/elf/syscall.sts create mode 100644 ia32/float/float.sts delete mode 100644 ia32/syscall.sts delete mode 100644 smack.c delete mode 100644 strans.c diff --git a/Makefile b/Makefile index a242d89..823e0f2 100644 --- a/Makefile +++ b/Makefile @@ -1,23 +1,23 @@ all: cryptrobber encrypt test .PHONY: all clean cryptrobber encrypt test -cryptrobber: smack strans - ./smack main.sts | ./strans > $@ +cryptrobber: enki/smack enki/strans + enki/smack main.sts | enki/strans > $@ chmod 0755 $@ -encrypt: smack strans - ./smack encrypt.sts | ./strans > $@ +encrypt: enki/smack enki/strans + enki/smack encrypt.sts | enki/strans > $@ chmod 0755 $@ -test: smack strans - ./smack test.sts | ./strans > $@ +test: enki/smack enki/strans + enki/smack test.sts | enki/strans > $@ chmod 0755 $@ -smack: smack.c +enki/smack: enki/smack.c gcc $< -o $@ -strans: strans.c +enki/strans: enki/strans.c gcc $< -o $@ clean: - rm -f smack strans cryptrobber encrypt test + rm -f enki/smack enki/strans cryptrobber encrypt test diff --git a/common/const.sts b/common/const.sts index b2e9f31..7b20b4d 100644 --- a/common/const.sts +++ b/common/const.sts @@ -1,3 +1,19 @@ +defconst space 20 +defconst '!' 21 +defconst '"' 22 +defconst '#' 23 +defconst '$' 24 +; '%' (25) symbol is reserved by smack +defconst '&' 26 +defconst ''' 27 +defconst '(' 28 +defconst ')' 29 +defconst '*' 2a +defconst '+' 2b +defconst ',' 2c +defconst '-' 2d +defconst '.' 2e +defconst '/' 2f defconst '0' 30 defconst '1' 31 defconst '2' 32 @@ -8,3 +24,71 @@ defconst '6' 36 defconst '7' 37 defconst '8' 38 defconst '9' 39 +defconst ':' 3a +defconst '<' 3c +defconst '=' 3d +defconst '>' 3e +defconst '?' 3f +defconst '@' 40 +defconst 'A' 41 +defconst 'B' 42 +defconst 'C' 43 +defconst 'D' 44 +defconst 'E' 45 +defconst 'F' 46 +defconst 'G' 47 +defconst 'H' 48 +defconst 'I' 49 +defconst 'J' 4a +defconst 'K' 4b +defconst 'L' 4c +defconst 'M' 4d +defconst 'N' 4e +defconst 'O' 4f +defconst 'P' 50 +defconst 'Q' 51 +defconst 'R' 52 +defconst 'S' 53 +defconst 'T' 54 +defconst 'U' 55 +defconst 'V' 56 +defconst 'W' 57 +defconst 'X' 58 +defconst 'Y' 59 +defconst 'Z' 5a +defconst '[' 5b +defconst '\' 5c +defconst ']' 5d +defconst '^' 5e +defconst '_' 5f +defconst '`' 60 +defconst 'a' 61 +defconst 'b' 62 +defconst 'c' 63 +defconst 'd' 64 +defconst 'e' 65 +defconst 'f' 66 +defconst 'g' 67 +defconst 'h' 68 +defconst 'i' 69 +defconst 'j' 6a +defconst 'k' 6b +defconst 'l' 6c +defconst 'm' 6d +defconst 'n' 6e +defconst 'o' 6f +defconst 'p' 70 +defconst 'q' 71 +defconst 'r' 72 +defconst 's' 73 +defconst 't' 74 +defconst 'u' 75 +defconst 'v' 76 +defconst 'w' 77 +defconst 'x' 78 +defconst 'y' 79 +defconst 'z' 7a +defconst '{' 7b +defconst '|' 7c +defconst '}' 7d +defconst '~' 7e diff --git a/enki/smack.c b/enki/smack.c new file mode 100644 index 0000000..f6f9f30 --- /dev/null +++ b/enki/smack.c @@ -0,0 +1,579 @@ +/* + Simple Macro Generator + created by exegete +*/ + +#include +#include +#include + +struct macro +{ + const char *lexem; + unsigned long long param_count; + const char *text; + struct macro *next; +}; + +struct macro_parameter +{ + char *lexem; + struct macro_parameter *next; +}; + +struct input_stream +{ + FILE *fd; + const struct macro *macro; + unsigned long long text_offset; + struct macro_parameter *param_list; + struct input_stream *next; +}; + +struct module +{ + const char *file_name; + struct module *next; +}; + +#define ERROR_STATUS_ARG 1 +#define ERROR_STATUS_OPEN 2 +#define ERROR_STATUS_CHDIR 3 +#define ERROR_STATUS_MALLOC 4 +#define ERROR_STATUS_EMPTY_STREAM_LIST 5 +#define ERROR_STATUS_INVALID_STREAM 6 +#define ERROR_STATUS_INVALID_MACRO 7 +#define ERROR_STATUS_INVALID_PARAMETER 8 +#define ERROR_STATUS_INVALID_CALL 9 +#define ERROR_STATUS_INVALID_INCLUDE 10 +#define ERROR_STATUS_INVALID_SHIELD 11 + +const char *error_msgs[] = +{ + "Please, specify input file", + "Unable to open file: ", + "Unable to change working directory: ", + "Unable to allocate memory", + "Input stream list is empty", + "Input stream is invalid", + "Macro definition is invalid", + "Macro parameter is invalid", + "Macro call is invalid", + "Invalid include/module argument", + "Invalid '#' argument" +}; + +void exit_error(int status, const char *msg) +{ + if(msg) + fprintf(stderr, "Error: %s%s\n", error_msgs[status - 1], msg); + else + fprintf(stderr, "Error: %s\n", error_msgs[status - 1]); + exit(status); +} + +void add_input_stream(struct input_stream **stream_list, + FILE *fd, const struct macro *macro) +{ + struct input_stream *head = *stream_list; + *stream_list = malloc(sizeof(struct input_stream)); + if(!*stream_list) + exit_error(ERROR_STATUS_MALLOC, NULL); + (*stream_list)->fd = fd; + (*stream_list)->macro = macro; + (*stream_list)->text_offset = 0; + (*stream_list)->param_list = NULL; + (*stream_list)->next = head; +} + +int delete_input_stream(struct input_stream **stream_list) +{ + struct input_stream *head = *stream_list; + if(!head) + exit_error(ERROR_STATUS_EMPTY_STREAM_LIST, NULL); + *stream_list = (*stream_list)->next; + if(head->fd) + fclose(head->fd); + while(head->param_list) + { + struct macro_parameter *param_head = head->param_list; + head->param_list = param_head->next; + free(param_head->lexem); + free(param_head); + } + free(head); + return *stream_list != NULL; +} + +void add_input_stream_parameter(struct input_stream *stream_list, char *lexem) +{ + struct macro_parameter **param = &stream_list->param_list; + while(*param) + param = &(*param)->next; + *param = malloc(sizeof(struct macro_parameter)); + if(!*param) + exit_error(ERROR_STATUS_MALLOC, NULL); + (*param)->lexem = lexem; + (*param)->next = NULL; +} + +const char *get_input_stream_parameter(struct input_stream *stream_list, + unsigned long long chosen) +{ + struct macro_parameter *param = stream_list->param_list; + if(!chosen) + return stream_list->macro->lexem; + chosen--; + for(; param && chosen > 0; chosen--) + param = param->next; + if(!param) + exit_error(ERROR_STATUS_INVALID_CALL, NULL); + return param->lexem; +} + +#define BUFFER_INITIAL_SIZE 4 + +int double_buffer(char **buffer, unsigned long long *buffer_size) +{ + char *tmp_pointer = *buffer; + unsigned long long tmp_size = *buffer_size; + + if(*buffer_size == 0) + *buffer_size = BUFFER_INITIAL_SIZE; + else + *buffer_size *= 2; + + *buffer = malloc(*buffer_size); + if(!*buffer) + return 0; + + for(; tmp_size > 0; tmp_size--) + (*buffer)[tmp_size - 1] = tmp_pointer[tmp_size - 1]; + + free(tmp_pointer); + return 1; +} + +int read_symb_from_text(struct input_stream *stream_list) +{ + char symb; + if(!stream_list->macro) + exit_error(ERROR_STATUS_INVALID_STREAM, NULL); + if(!stream_list->macro->text) + exit_error(ERROR_STATUS_INVALID_STREAM, NULL); + symb = stream_list->macro->text[stream_list->text_offset]; + if(!symb) + return EOF; + stream_list->text_offset++; + return symb; +} + +#define COMMENT_SYMB ';' + +int read_real_symb(struct input_stream *stream_list) +{ + int symb; + + if(!stream_list) + exit_error(ERROR_STATUS_EMPTY_STREAM_LIST, NULL); + + if(stream_list->fd) + symb = fgetc(stream_list->fd); + else + symb = read_symb_from_text(stream_list); + + if(symb == COMMENT_SYMB) + { + for(; symb != '\n' && symb != EOF; + symb = fgetc(stream_list->fd)) + {} + } + return symb; +} + +#define SHIELD_SYMB '\\' + +int read_symb(struct input_stream *stream_list, int *shield) +{ + int symb = read_real_symb(stream_list); + if(shield) + { + *shield = 0; + if(symb == SHIELD_SYMB) + { + symb = read_real_symb(stream_list); + *shield = 1; + } + } + return symb; +} + +int is_symb_hex(char symb) +{ + if(symb >= '0' && symb <= '9') + return symb - '0'; + else + if(symb >= 'A' && symb <= 'F') + return symb - 'A' + 10; + else + if(symb >= 'a' && symb <= 'f') + return symb - 'a' + 10; + else + return -1; +} + +int is_lexem_hex(const char *lexem, unsigned long long *dest) +{ + int sign = 0; + unsigned long long hex = 0; + if(*lexem == '-' && *(lexem + 1)) + { + sign = 1; + lexem++; + } + + for(; *lexem; lexem++) + { + int num = is_symb_hex(*lexem); + if(num != -1) + hex = (hex << 4) + num; + else + return 0; + } + hex = sign ? ~hex + 1 : hex; + if(dest) + *dest = hex; + return 1; +} + +int compare_lexems(const char *lexem_one, const char *lexem_two) +{ + for(; *lexem_one && *lexem_two; lexem_one++, lexem_two++) + if(*lexem_one != *lexem_two) + return 0; + return *lexem_one == *lexem_two; +} + +char *copy_lexem(const char *lexem) +{ + char *buffer = NULL; + unsigned long long buffer_size = 0; + unsigned long long index; + + for(index = 0;; index++) + { + if(index == buffer_size) + if(!double_buffer(&buffer, &buffer_size)) + exit_error(ERROR_STATUS_MALLOC, NULL); + buffer[index] = lexem[index]; + if(!lexem[index]) + break; + } + return buffer; +} + +#define EVAL_SYMB '%' + +unsigned long long get_eval_end(const char *lexem) +{ + unsigned long long counter = 0; + + for(; *lexem && *lexem != EVAL_SYMB; lexem++, counter++) + {} + if(!*lexem) + exit_error(ERROR_STATUS_INVALID_CALL, NULL); + return counter; +} + +char *param_eval(struct input_stream *stream_list, char *lexem) +{ + char *input_lexem = lexem; + char *buffer = NULL; + unsigned long long buffer_size = 0; + const char *param = NULL; + unsigned long long index = 0; + + for(;;) + { + char symb = param && *param ? *param : *lexem++; + param = !param || !*param ? NULL : param + 1; + if(symb == EVAL_SYMB) + { + unsigned long long param_offset = get_eval_end(lexem); + unsigned long long param_num; + *(lexem + param_offset) = 0; + if(!is_lexem_hex(lexem, ¶m_num)) + exit_error(ERROR_STATUS_INVALID_CALL, NULL); + lexem += param_offset + 1; + param = get_input_stream_parameter(stream_list, + param_num); + continue; + } + if(index == buffer_size) + if(!double_buffer(&buffer, &buffer_size)) + exit_error(ERROR_STATUS_MALLOC, NULL); + buffer[index] = symb; + if(!symb) + break; + index++; + } + free(input_lexem); + return buffer; +} + +int is_separator(int symb) +{ + return symb == ' ' || symb == '\n' || symb == '\t' || symb == '\r'; +} + +char *read_lexem(struct input_stream *stream_list) +{ + char *buffer = NULL; + unsigned long long buffer_size = 0; + int symb; + int shield; + unsigned long long index; + + for(;;) + { + symb = read_symb(stream_list, &shield); + if(is_separator(symb) && !shield) + continue; + if(symb == EOF) + return NULL; + break; + } + + for(index = 0;; index++) + { + if(index == buffer_size) + if(!double_buffer(&buffer, &buffer_size)) + exit_error(ERROR_STATUS_MALLOC, NULL); + if(symb == EOF || (is_separator(symb) && !shield)) + { + buffer[index] = 0; + break; + } + buffer[index] = symb; + symb = read_symb(stream_list, &shield); + } + buffer = param_eval(stream_list, buffer); + return buffer; +} + +#define MACRO_END_SYMB ']' + +const char *read_macro_text(struct input_stream *stream_list) +{ + char *buffer = NULL; + unsigned long long buffer_size = 0; + unsigned long long index; + + for(index = 0;; index++) + { + int shield; + int symb = read_symb(stream_list, &shield); + if(index == buffer_size) + if(!double_buffer(&buffer, &buffer_size)) + exit_error(ERROR_STATUS_MALLOC, NULL); + if(symb == EOF || (symb == MACRO_END_SYMB && !shield)) + { + buffer[index] = 0; + break; + } + buffer[index] = symb; + } + return buffer; +} + +void create_macro(struct input_stream *stream_list, struct macro **macro_list) +{ + char *param_count_lexem; + struct macro *head = *macro_list; + *macro_list = malloc(sizeof(struct macro)); + if(!*macro_list) + exit_error(ERROR_STATUS_MALLOC, NULL); + (*macro_list)->lexem = read_lexem(stream_list); + if(!(*macro_list)->lexem) + exit_error(ERROR_STATUS_INVALID_MACRO, NULL); + param_count_lexem = read_lexem(stream_list); + if(!param_count_lexem || !is_lexem_hex(param_count_lexem, + &(*macro_list)->param_count)) + exit_error(ERROR_STATUS_INVALID_MACRO, NULL); + free(param_count_lexem); + (*macro_list)->text = read_macro_text(stream_list); + (*macro_list)->next = head; +} + +int find_module(struct module *module_list, const char *file_name) +{ + for(; module_list; module_list = module_list->next) + if(compare_lexems(module_list->file_name, file_name)) + return 1; + return 0; +} + +void add_module(struct module **module_list, const char *file_name) +{ + struct module *head = *module_list; + *module_list = malloc(sizeof(struct module)); + if(!*module_list) + exit_error(ERROR_STATUS_MALLOC, NULL); + (*module_list)->file_name = file_name; + (*module_list)->next = head; +} + +void include_file(struct input_stream **stream_list, + struct module **module_list) +{ + char *file_name = read_lexem(*stream_list); + FILE *fd; + if(!file_name) + exit_error(ERROR_STATUS_INVALID_INCLUDE, NULL); + if(module_list && find_module(*module_list, file_name)) + { + free(file_name); + return; + } + fd = fopen(file_name, "r"); + if(!fd) + exit_error(ERROR_STATUS_OPEN, file_name); + if(module_list) + add_module(module_list, file_name); + else + free(file_name); + add_input_stream(stream_list, fd, NULL); +} + +void push_parameter(struct input_stream *input_stream, + struct input_stream *actual_stream) +{ + char *lexem = read_lexem(input_stream); + if(!lexem) + exit_error(ERROR_STATUS_INVALID_PARAMETER, NULL); + add_input_stream_parameter(actual_stream, lexem); +} + +int find_macro(struct input_stream **stream_list, struct macro *macro_list, + const char *lexem) +{ + for(; macro_list; macro_list = macro_list->next) + { + if(compare_lexems(macro_list->lexem, lexem)) + { + struct input_stream *old_stream = *stream_list; + unsigned long long param_count = + macro_list->param_count; + add_input_stream(stream_list, NULL, macro_list); + for(; param_count > 0; param_count--) + push_parameter(old_stream, *stream_list); + return 1; + } + } + return 0; +} + +#define DIRECTORY_SEPARATOR_SYMB '/' + +unsigned long long find_last_dir_separator_pos(const char *file_name) +{ + const char *orig_file_name = file_name; + unsigned long long pos = 0; + for(; *file_name; file_name++) + if(*file_name == DIRECTORY_SEPARATOR_SYMB) + pos = file_name - orig_file_name; + return pos; +} + +void initialize_stream(struct input_stream **stream_list, + const char *file_name) +{ + char *dir_path = copy_lexem(file_name); + unsigned long long dir_sep_pos = find_last_dir_separator_pos(dir_path); + FILE *fd = fopen(file_name, "r"); + if(!fd) + exit_error(ERROR_STATUS_OPEN, file_name); + add_input_stream(stream_list, fd, NULL); + if(dir_sep_pos) + { + dir_path[dir_sep_pos] = 0; + if(chdir(dir_path) == -1) + exit_error(ERROR_STATUS_CHDIR, NULL); + } + free(dir_path); +} + +void print_lexem(const char *lexem) +{ + printf("%s ", lexem); +} + +#define MACRO_SHIELD_LEXEM "#" +#define MACRO_START_LEXEM "[" +#define MACRO_INCLUDE_LEXEM "include" +#define MACRO_MODULE_LEXEM "module" +#define MACRO_LIT_LEXEM "literal" + +int main(int argc, char **argv) +{ + struct input_stream *stream_list = NULL; + struct macro *macro_list = NULL; + struct module *module_list = NULL; + char *lexem; + + if(argc <= 1) + exit_error(ERROR_STATUS_ARG, NULL); + else + initialize_stream(&stream_list, argv[1]); + + for(;; free(lexem)) + { + lexem = read_lexem(stream_list); + if(!lexem) + { + if(delete_input_stream(&stream_list)) + continue; + else + break; + } + if(compare_lexems(lexem, MACRO_SHIELD_LEXEM)) + { + free(lexem); + lexem = read_lexem(stream_list); + if(!lexem) + exit_error(ERROR_STATUS_INVALID_SHIELD, NULL); + print_lexem(lexem); + continue; + } + if(compare_lexems(lexem, MACRO_START_LEXEM)) + { + create_macro(stream_list, ¯o_list); + continue; + } + if(compare_lexems(lexem, MACRO_INCLUDE_LEXEM)) + { + include_file(&stream_list, NULL); + continue; + } + if(compare_lexems(lexem, MACRO_MODULE_LEXEM)) + { + include_file(&stream_list, &module_list); + continue; + } + if(is_lexem_hex(lexem, NULL)) + { + if(find_macro(&stream_list, macro_list, + MACRO_LIT_LEXEM)) + { + add_input_stream_parameter(stream_list, + copy_lexem(lexem)); + continue; + } + } + if(find_macro(&stream_list, macro_list, lexem)) + continue; + print_lexem(lexem); + } + + return 0; +} diff --git a/enki/strans.c b/enki/strans.c new file mode 100644 index 0000000..e3d834d --- /dev/null +++ b/enki/strans.c @@ -0,0 +1,652 @@ +/* + Simple Stack Translator + created by exegete +*/ + +#include +#include + +struct stack_elem +{ + unsigned long long value; + struct stack_elem *next; +}; + +struct identifier +{ + const char *lexem; + unsigned long long value; + struct identifier *next; +}; + +struct segment +{ + char *buffer; + unsigned long long real_size; + unsigned long long size; + unsigned long long pointer_address; + unsigned long long base_address; + unsigned long long base_offset; + int data_size; + int data_endianness; + struct segment *next; +}; + +struct environment +{ + struct stack_elem *stack; + struct identifier *id_list; + struct segment *seg_list; + unsigned long long chosen_segment; +}; + +struct operator +{ + void (*func)(struct environment *env); + const char *lexem; +}; + +#define ERROR_STATUS_STACK_OVERFLOW 1 +#define ERROR_STATUS_STACK_EMPTY 2 +#define ERROR_STATUS_ID_LIST_OVERFLOW 3 +#define ERROR_STATUS_SEG_LIST_OVERFLOW 4 +#define ERROR_STATUS_INVALID_SEGMENT 5 +#define ERROR_STATUS_WORD_BUFFER_OVERFLOW 6 +#define ERROR_STATUS_LEXEM_OVERFLOW 7 +#define ERROR_STATUS_UNDEFINED 8 +#define ERROR_STATUS_INVALID_ACCESS 9 +#define ERROR_STATUS_INVALID_WORD_SIZE 10 +#define ERROR_STATUS_WORD_ENDIANNESS_INVALID 11 + +const char *error_msgs[] = +{ + "Stack overflow", + "Stack is empty", + "Identifier list overflow", + "Segment list overflow", + "Invalid chosen segment", + "Word buffer overflow", + "Lexem is too big", + "Undefined lexem: ", + "Invalid segment access", + "Invalid segment data size", + "Invalid segment data endianness" +}; + +void exit_error(int status, const char *lexem) +{ + if(lexem) + fprintf(stderr, "Error: %s%s\n", error_msgs[status - 1], + lexem); + else + fprintf(stderr, "Error: %s\n", error_msgs[status - 1]); + exit(status); +} + +unsigned long long create_segment(struct environment *env) +{ + struct segment **chosen_segment = &env->seg_list; + unsigned long long segment_counter = 0; + for(; *chosen_segment; chosen_segment = &(*chosen_segment)->next) + segment_counter++; + *chosen_segment = malloc(sizeof(struct segment)); + if(!*chosen_segment) + exit_error(ERROR_STATUS_SEG_LIST_OVERFLOW, NULL); + (*chosen_segment)->buffer = NULL; + (*chosen_segment)->real_size = 0; + (*chosen_segment)->size = 0; + (*chosen_segment)->pointer_address = 0; + (*chosen_segment)->base_address = 0; + (*chosen_segment)->base_offset = 0; + (*chosen_segment)->data_size = 1; + (*chosen_segment)->data_endianness = 0; + (*chosen_segment)->next = NULL; + return segment_counter; +} + +struct segment *get_segment(struct environment *env) +{ + struct segment *chosen_segment = env->seg_list; + unsigned long long segment_counter = env->chosen_segment; + while(chosen_segment && segment_counter--) + chosen_segment = chosen_segment->next; + if(!chosen_segment) + exit_error(ERROR_STATUS_INVALID_SEGMENT, NULL); + return chosen_segment; +} + +void initialize_environment(struct environment *env) +{ + env->stack = NULL; + env->id_list = NULL; + env->seg_list = NULL; + env->chosen_segment = 0; +} + +int is_separator(int symb) +{ + return symb == ' ' || symb == '\n' || symb == '\t' || symb == '\r'; +} + +#define BUFFER_INITIAL_SIZE 4 + +int double_buffer(char **buffer, unsigned long long *buffer_size) +{ + char *tmp_pointer = *buffer; + unsigned long long tmp_size = *buffer_size; + + if(*buffer_size == 0) + *buffer_size = BUFFER_INITIAL_SIZE; + else + *buffer_size *= 2; + + *buffer = malloc(*buffer_size); + if(!*buffer) + return 0; + + for(; tmp_size > 0; tmp_size--) + (*buffer)[tmp_size - 1] = tmp_pointer[tmp_size - 1]; + + free(tmp_pointer); + return 1; +} + +char *read_lexem() +{ + char *buffer = NULL; + unsigned long long buffer_size = 0; + int symb; + unsigned long long index; + + while(is_separator(symb = getchar())) + {} + + if(symb == EOF) + return NULL; + + for(index = 0;; index++) + { + if(index == buffer_size) + if(!double_buffer(&buffer, &buffer_size)) + exit_error(ERROR_STATUS_LEXEM_OVERFLOW, NULL); + if(symb == EOF || is_separator(symb)) + { + buffer[index] = 0; + break; + } + buffer[index] = symb; + symb = getchar(); + } + return buffer; +} + +void push_stack_elem(struct stack_elem **stack, unsigned long long value) +{ + struct stack_elem *head = *stack; + *stack = malloc(sizeof(struct stack_elem)); + if(!*stack) + exit_error(ERROR_STATUS_STACK_OVERFLOW, NULL); + (*stack)->value = value; + (*stack)->next = head; +} + +unsigned long long pop_stack_elem(struct stack_elem **stack) +{ + struct stack_elem *head = *stack; + unsigned long long value; + if(!head) + exit_error(ERROR_STATUS_STACK_EMPTY, NULL); + value = head->value; + *stack = head->next; + free(head); + return value; +} + +int is_symb_hex(char symb) +{ + if(symb >= '0' && symb <= '9') + return symb - '0'; + else + if(symb >= 'A' && symb <= 'F') + return symb - 'A' + 10; + else + if(symb >= 'a' && symb <= 'f') + return symb - 'a' + 10; + else + return -1; +} + +int is_lexem_hex(struct environment *env, const char *lexem) +{ + int sign = 0; + unsigned long long hex = 0; + if(*lexem == '-' && *(lexem + 1)) + { + sign = 1; + lexem++; + } + + for(; *lexem; lexem++) + { + int num = is_symb_hex(*lexem); + if(num != -1) + hex = (hex << 4) + num; + else + return 0; + } + hex = sign ? ~hex + 1 : hex; + push_stack_elem(&env->stack, hex); + return 1; +} + +int compare_lexems(const char *lexem_one, const char *lexem_two) +{ + for(; *lexem_one && *lexem_two; lexem_one++, lexem_two++) + if(*lexem_one != *lexem_two) + return 0; + return *lexem_one == *lexem_two; +} + +void add_identifier(struct identifier **id_list, const char *lexem, + unsigned long long value) +{ + struct identifier *head = *id_list; + *id_list = malloc(sizeof(struct identifier)); + if(!id_list) + exit_error(ERROR_STATUS_ID_LIST_OVERFLOW, NULL); + (*id_list)->lexem = lexem; + (*id_list)->value = value; + (*id_list)->next = head; +} + +int find_identifier(struct environment *env, const char *lexem) +{ + struct identifier *id_list = env->id_list; + for(; id_list; id_list = id_list->next) + { + if(compare_lexems(lexem, id_list->lexem)) + { + push_stack_elem(&env->stack, id_list->value); + return 1; + } + } + return 0; +} + +void segment_compile_byte(struct environment *env, char byte) +{ + unsigned long long index = get_segment(env)->size; + if(index == get_segment(env)->real_size) + if(!double_buffer(&get_segment(env)->buffer, + &get_segment(env)->real_size)) + exit_error(ERROR_STATUS_WORD_BUFFER_OVERFLOW, NULL); + get_segment(env)->buffer[index] = byte; + get_segment(env)->size++; + get_segment(env)->pointer_address++; +} + +void segment_compile(struct environment *env, unsigned long long value, + int size) +{ + int dir = get_segment(env)->data_endianness ? -1 : 1; + int index = get_segment(env)->data_endianness * (size - 1); + for(; index < size && index >= 0; index += dir) + segment_compile_byte(env, value >> index * 8); +} + +unsigned long long convert_address(struct environment *env, + unsigned long long address, int size) +{ + unsigned long long pointer_address = + get_segment(env)->pointer_address; + unsigned long long base_address = get_segment(env)->base_address; + unsigned long long base_offset = get_segment(env)->base_offset; + if(address < base_address || address + size > pointer_address) + exit_error(ERROR_STATUS_INVALID_ACCESS, NULL); + return address - base_address + base_offset; +} + +unsigned long long segment_read(struct environment *env, + unsigned long long address, int size) +{ + unsigned long long value = 0; + int dir = get_segment(env)->data_endianness ? 1 : -1; + int index = get_segment(env)->data_endianness ? 0 : (size - 1); + address = convert_address(env, address, size); + for(; index < size && index >= 0; index += dir) + value = (value << 8) + + (get_segment(env)->buffer[address + index] & 0xFF); + return value; +} + +void segment_write(struct environment *env, unsigned long long value, + unsigned long long address, int size) +{ + int dir = get_segment(env)->data_endianness ? -1 : 1; + int index = get_segment(env)->data_endianness * (size - 1); + address = convert_address(env, address, size); + for(; index < size && index >= 0; index += dir) + { + get_segment(env)->buffer[address + index] = value; + value >>= 8; + } +} + +void translator_drop(struct environment *env) +{ + pop_stack_elem(&env->stack); +} + +void translator_dup(struct environment *env) +{ + unsigned long long value = pop_stack_elem(&env->stack); + push_stack_elem(&env->stack, value); + push_stack_elem(&env->stack, value); +} + +void translator_over(struct environment *env) +{ + unsigned long long value_one = pop_stack_elem(&env->stack); + unsigned long long value_two = pop_stack_elem(&env->stack); + push_stack_elem(&env->stack, value_two); + push_stack_elem(&env->stack, value_one); + push_stack_elem(&env->stack, value_two); +} + +void translator_swap(struct environment *env) +{ + unsigned long long value_one = pop_stack_elem(&env->stack); + unsigned long long value_two = pop_stack_elem(&env->stack); + push_stack_elem(&env->stack, value_one); + push_stack_elem(&env->stack, value_two); +} + +void translator_add(struct environment *env) +{ + unsigned long long first = pop_stack_elem(&env->stack); + unsigned long long second = pop_stack_elem(&env->stack); + push_stack_elem(&env->stack, second + first); +} + +void translator_sub(struct environment *env) +{ + unsigned long long first = pop_stack_elem(&env->stack); + unsigned long long second = pop_stack_elem(&env->stack); + push_stack_elem(&env->stack, second - first); +} + +void translator_mul(struct environment *env) +{ + unsigned long long first = pop_stack_elem(&env->stack); + unsigned long long second = pop_stack_elem(&env->stack); + push_stack_elem(&env->stack, second * first); +} + +void translator_div(struct environment *env) +{ + unsigned long long first = pop_stack_elem(&env->stack); + unsigned long long second = pop_stack_elem(&env->stack); + push_stack_elem(&env->stack, second / first); +} + +void translator_mod(struct environment *env) +{ + unsigned long long first = pop_stack_elem(&env->stack); + unsigned long long second = pop_stack_elem(&env->stack); + push_stack_elem(&env->stack, second % first); +} + +void translator_define_identifier(struct environment *env) +{ + unsigned long long value = pop_stack_elem(&env->stack); + add_identifier(&env->id_list, read_lexem(), value); +} + +void translator_compile_one(struct environment *env) +{ + unsigned long long value = pop_stack_elem(&env->stack); + segment_compile(env, value, 1); +} + +void translator_compile_two(struct environment *env) +{ + unsigned long long value = pop_stack_elem(&env->stack); + segment_compile(env, value, 2); +} + +void translator_compile_four(struct environment *env) +{ + unsigned long long value = pop_stack_elem(&env->stack); + segment_compile(env, value, 4); +} + +void translator_compile_eight(struct environment *env) +{ + unsigned long long value = pop_stack_elem(&env->stack); + segment_compile(env, value, 8); +} + +void translator_compile(struct environment *env) +{ + unsigned long long value = pop_stack_elem(&env->stack); + segment_compile(env, value, get_segment(env)->data_size); +} + +void translator_reserve(struct environment *env) +{ + unsigned long long count = pop_stack_elem(&env->stack); + while(count--) + segment_compile(env, 0, 1); +} + +void translator_read_one(struct environment *env) +{ + unsigned long long value = segment_read(env, + pop_stack_elem(&env->stack), 1); + push_stack_elem(&env->stack, value); +} + +void translator_read_two(struct environment *env) +{ + unsigned long long value = segment_read(env, + pop_stack_elem(&env->stack), 2); + push_stack_elem(&env->stack, value); +} + +void translator_read_four(struct environment *env) +{ + unsigned long long value = segment_read(env, + pop_stack_elem(&env->stack), 4); + push_stack_elem(&env->stack, value); +} + +void translator_read_eight(struct environment *env) +{ + unsigned long long value = segment_read(env, + pop_stack_elem(&env->stack), 8); + push_stack_elem(&env->stack, value); +} + +void translator_read(struct environment *env) +{ + unsigned long long value = segment_read(env, + pop_stack_elem(&env->stack), get_segment(env)->data_size); + push_stack_elem(&env->stack, value); +} + +void translator_write_one(struct environment *env) +{ + unsigned long long address = pop_stack_elem(&env->stack); + unsigned long long value = pop_stack_elem(&env->stack); + segment_write(env, value, address, 1); +} + +void translator_write_two(struct environment *env) +{ + unsigned long long address = pop_stack_elem(&env->stack); + unsigned long long value = pop_stack_elem(&env->stack); + segment_write(env, value, address, 2); +} + +void translator_write_four(struct environment *env) +{ + unsigned long long address = pop_stack_elem(&env->stack); + unsigned long long value = pop_stack_elem(&env->stack); + segment_write(env, value, address, 4); +} + +void translator_write_eight(struct environment *env) +{ + unsigned long long address = pop_stack_elem(&env->stack); + unsigned long long value = pop_stack_elem(&env->stack); + segment_write(env, value, address, 8); +} + +void translator_write(struct environment *env) +{ + unsigned long long address = pop_stack_elem(&env->stack); + unsigned long long value = pop_stack_elem(&env->stack); + segment_write(env, value, address, get_segment(env)->data_size); +} + +void translator_create_segment(struct environment *env) +{ + push_stack_elem(&env->stack, create_segment(env)); +} + +void translator_choose_segment(struct environment *env) +{ + env->chosen_segment = pop_stack_elem(&env->stack); +} + +void translator_set_base(struct environment *env) +{ + get_segment(env)->base_address = pop_stack_elem(&env->stack); + get_segment(env)->pointer_address = get_segment(env)->base_address; + get_segment(env)->base_offset = get_segment(env)->size; +} + +#define WORD_SIZE_MAX 8 + +void translator_set_data_size(struct environment *env) +{ + int target_size = pop_stack_elem(&env->stack); + if(target_size <= 0 || target_size > WORD_SIZE_MAX) + exit_error(ERROR_STATUS_INVALID_WORD_SIZE, NULL); + get_segment(env)->data_size = target_size; +} + +void translator_set_data_endianness(struct environment *env) +{ + int endianness = pop_stack_elem(&env->stack); + if(endianness > 1) + exit_error(ERROR_STATUS_WORD_ENDIANNESS_INVALID, NULL); + get_segment(env)->data_endianness = endianness; +} + +void translator_get_offset(struct environment *env) +{ + push_stack_elem(&env->stack, get_segment(env)->pointer_address); +} + +void translator_get_base(struct environment *env) +{ + push_stack_elem(&env->stack, get_segment(env)->base_address); +} + +void translator_print(struct environment *env) +{ + unsigned long long value = pop_stack_elem(&env->stack); + fprintf(stderr, "%llx\n", value); +} + +const struct operator translator_operators[] = +{ + { &translator_drop, "?drop" }, + { &translator_dup, "?dup" }, + { &translator_over, "?over" }, + { &translator_swap, "?swap" }, + { &translator_add, "?+" }, + { &translator_sub, "?-" }, + { &translator_mul, "?*" }, + { &translator_div, "?/" }, + { &translator_mod, "?mod" }, + { &translator_define_identifier, "??" }, + { &translator_compile_one, "?'" }, + { &translator_compile_one, "?1." }, + { &translator_compile_two, "?2." }, + { &translator_compile_four, "?4." }, + { &translator_compile_eight, "?8." }, + { &translator_compile, "?." }, + { &translator_reserve, "?res" }, + { &translator_read_one, "?1@" }, + { &translator_read_two, "?2@" }, + { &translator_read_four, "?4@" }, + { &translator_read_eight, "?8@" }, + { &translator_read, "?@" }, + { &translator_write_one, "?1!" }, + { &translator_write_two, "?2!" }, + { &translator_write_four, "?4!" }, + { &translator_write_eight, "?8!" }, + { &translator_write, "?!" }, + { &translator_create_segment, "?create" }, + { &translator_choose_segment, "?choose" }, + { &translator_set_base, "?org" }, + { &translator_set_data_size, "?size" }, + { &translator_set_data_endianness, "?endianness" }, + { &translator_get_offset, "?$" }, + { &translator_get_base, "?$$" }, + { &translator_print, "?print" }, +}; + +int execute_operator(struct environment *env, const char *lexem) +{ + int operators_count = + sizeof(translator_operators) / sizeof(*translator_operators); + int index; + + for(index = 0; index < operators_count; index++) + { + if(compare_lexems(lexem, translator_operators[index].lexem)) + { + (*translator_operators[index].func)(env); + break; + } + } + + return index != operators_count; +} + +void print_target_buffer(struct environment *env) +{ + struct segment *seg_list; + unsigned long long index; + for(seg_list = env->seg_list; seg_list; seg_list = seg_list->next) + for(index = 0; index < seg_list->size; index++) + putchar(seg_list->buffer[index]); +} + +int main() +{ + struct environment env; + char *lexem; + + initialize_environment(&env); + + for(;; free(lexem)) + { + lexem = read_lexem(); + if(!lexem) + break; + if(find_identifier(&env, lexem)) + continue; + if(is_lexem_hex(&env, lexem)) + continue; + if(!execute_operator(&env, lexem)) + exit_error(ERROR_STATUS_UNDEFINED, lexem); + } + + print_target_buffer(&env); + + return 0; +} diff --git a/ia32/elf/begin.sts b/ia32/elf/begin.sts index 27b4714..8dab930 100644 --- a/ia32/elf/begin.sts +++ b/ia32/elf/begin.sts @@ -125,4 +125,5 @@ _return_stack ?. # ff ?' # 20 ?' module ia32/ia32.sts +module ia32/elf/syscall.sts module common/common.sts diff --git a/ia32/elf/syscall.sts b/ia32/elf/syscall.sts new file mode 100644 index 0000000..3acfef2 --- /dev/null +++ b/ia32/elf/syscall.sts @@ -0,0 +1,41 @@ +defasm sys_exit + # b8 ?' # 1 ?. ; mov eax, 1 + # 31 ?' # db ?' ; xor ebx, ebx + # cd ?' # 80 ?' ; int 0x80 +; no need in next since this is the last instruction + +_data_segment ?choose + ?$ ?? _iobuf # 0 ?. +_code_segment ?choose + +defasm sys_read + # b8 ?' # 3 ?. ; mov eax, 3 + # 31 ?' # db ?' ; xor ebx, ebx + # b9 ?' _iobuf ?. ; mov ecx, _iobuf + # ba ?' # 1 ?. ; mov edx, 1 + # cd ?' # 80 ?' ; int 0x80 + # 31 ?' # db ?' ; xor ebx, ebx + # 8a ?' # 1d ?' _iobuf ?. ; mov bl, [_iobuf] + # 53 ?' ; push ebx + # 50 ?' ; push eax +next + +defasm sys_write + # 58 ?' ; pop eax + # a2 ?' _iobuf ?. ; mov [_iobuf], al + # b8 ?' # 4 ?. ; mov eax, 4 + # bb ?' # 1 ?. ; mov ebx, 1 + # b9 ?' _iobuf ?. ; mov ecx, _iobuf + # ba ?' # 1 ?. ; mov edx, 1 + # cd ?' # 80 ?' ; int 0x80 +next + +defasm sys_write_err + # 58 ?' ; pop eax + # a2 ?' _iobuf ?. ; mov [_iobuf], al + # b8 ?' # 4 ?. ; mov eax, 4 + # bb ?' # 2 ?. ; mov ebx, 2 + # b9 ?' _iobuf ?. ; mov ecx, _iobuf + # ba ?' # 1 ?. ; mov edx, 1 + # cd ?' # 80 ?' ; int 0x80 +next diff --git a/ia32/float/float.sts b/ia32/float/float.sts new file mode 100644 index 0000000..158781c --- /dev/null +++ b/ia32/float/float.sts @@ -0,0 +1,37 @@ +defasm float_init + # 9b ?' ; wait + # db ?' # e3 ?' ; fninit +next + +defasm float_fload + # d9 ?' # 04 ?' # 24 ?' ; fld dword [esp] + # 58 ?' ; pop eax +next + +defasm float_iload + # db ?' # 04 ?' # 24 ?' ; fild dword [esp] + # 58 ?' ; pop eax +next + +defasm float_fstore + # 50 ?' ; push eax + # d9 ?' # 1c ?' # 24 ?' ; fstp dword [esp] +next + +defasm float_istore + # 50 ?' ; push eax + # db ?' # 1c ?' # 24 ?' ; fistp dword [esp] +next + +defasm float_status + # de ?' # f9 ?' ; fnstsw ax + # 50 ?' ; push eax +next + +defasm float_add + # de ?' # c1 ?' ; faddp st1, st0 +next + +defasm float_div + # de ?' # f9 ?' ; fdivp st1, st0 +next diff --git a/ia32/ia32.sts b/ia32/ia32.sts index 0d8a9f5..38b5919 100644 --- a/ia32/ia32.sts +++ b/ia32/ia32.sts @@ -6,4 +6,3 @@ module ia32/branch.sts module ia32/memory.sts module ia32/math.sts module ia32/bitwise.sts -module ia32/syscall.sts diff --git a/ia32/math.sts b/ia32/math.sts index fefe1d4..609a21a 100644 --- a/ia32/math.sts +++ b/ia32/math.sts @@ -8,12 +8,10 @@ defasm - # 29 ?' # 04 ?' # 24 ?' ; sub [esp], eax next -defasm / +defasm mul # 5b ?' ; pop ebx # 58 ?' ; pop eax - # 31 ?' # d2 ?' ; xor edx, edx - # f7 ?' # f3 ?' ; div ebx - # 52 ?' ; push edx + # f7 ?' # e3 ?' ; mul ebx # 50 ?' ; push eax next diff --git a/ia32/syscall.sts b/ia32/syscall.sts deleted file mode 100644 index 3acfef2..0000000 --- a/ia32/syscall.sts +++ /dev/null @@ -1,41 +0,0 @@ -defasm sys_exit - # b8 ?' # 1 ?. ; mov eax, 1 - # 31 ?' # db ?' ; xor ebx, ebx - # cd ?' # 80 ?' ; int 0x80 -; no need in next since this is the last instruction - -_data_segment ?choose - ?$ ?? _iobuf # 0 ?. -_code_segment ?choose - -defasm sys_read - # b8 ?' # 3 ?. ; mov eax, 3 - # 31 ?' # db ?' ; xor ebx, ebx - # b9 ?' _iobuf ?. ; mov ecx, _iobuf - # ba ?' # 1 ?. ; mov edx, 1 - # cd ?' # 80 ?' ; int 0x80 - # 31 ?' # db ?' ; xor ebx, ebx - # 8a ?' # 1d ?' _iobuf ?. ; mov bl, [_iobuf] - # 53 ?' ; push ebx - # 50 ?' ; push eax -next - -defasm sys_write - # 58 ?' ; pop eax - # a2 ?' _iobuf ?. ; mov [_iobuf], al - # b8 ?' # 4 ?. ; mov eax, 4 - # bb ?' # 1 ?. ; mov ebx, 1 - # b9 ?' _iobuf ?. ; mov ecx, _iobuf - # ba ?' # 1 ?. ; mov edx, 1 - # cd ?' # 80 ?' ; int 0x80 -next - -defasm sys_write_err - # 58 ?' ; pop eax - # a2 ?' _iobuf ?. ; mov [_iobuf], al - # b8 ?' # 4 ?. ; mov eax, 4 - # bb ?' # 2 ?. ; mov ebx, 2 - # b9 ?' _iobuf ?. ; mov ecx, _iobuf - # ba ?' # 1 ?. ; mov edx, 1 - # cd ?' # 80 ?' ; int 0x80 -next diff --git a/smack.c b/smack.c deleted file mode 100644 index f6f9f30..0000000 --- a/smack.c +++ /dev/null @@ -1,579 +0,0 @@ -/* - Simple Macro Generator - created by exegete -*/ - -#include -#include -#include - -struct macro -{ - const char *lexem; - unsigned long long param_count; - const char *text; - struct macro *next; -}; - -struct macro_parameter -{ - char *lexem; - struct macro_parameter *next; -}; - -struct input_stream -{ - FILE *fd; - const struct macro *macro; - unsigned long long text_offset; - struct macro_parameter *param_list; - struct input_stream *next; -}; - -struct module -{ - const char *file_name; - struct module *next; -}; - -#define ERROR_STATUS_ARG 1 -#define ERROR_STATUS_OPEN 2 -#define ERROR_STATUS_CHDIR 3 -#define ERROR_STATUS_MALLOC 4 -#define ERROR_STATUS_EMPTY_STREAM_LIST 5 -#define ERROR_STATUS_INVALID_STREAM 6 -#define ERROR_STATUS_INVALID_MACRO 7 -#define ERROR_STATUS_INVALID_PARAMETER 8 -#define ERROR_STATUS_INVALID_CALL 9 -#define ERROR_STATUS_INVALID_INCLUDE 10 -#define ERROR_STATUS_INVALID_SHIELD 11 - -const char *error_msgs[] = -{ - "Please, specify input file", - "Unable to open file: ", - "Unable to change working directory: ", - "Unable to allocate memory", - "Input stream list is empty", - "Input stream is invalid", - "Macro definition is invalid", - "Macro parameter is invalid", - "Macro call is invalid", - "Invalid include/module argument", - "Invalid '#' argument" -}; - -void exit_error(int status, const char *msg) -{ - if(msg) - fprintf(stderr, "Error: %s%s\n", error_msgs[status - 1], msg); - else - fprintf(stderr, "Error: %s\n", error_msgs[status - 1]); - exit(status); -} - -void add_input_stream(struct input_stream **stream_list, - FILE *fd, const struct macro *macro) -{ - struct input_stream *head = *stream_list; - *stream_list = malloc(sizeof(struct input_stream)); - if(!*stream_list) - exit_error(ERROR_STATUS_MALLOC, NULL); - (*stream_list)->fd = fd; - (*stream_list)->macro = macro; - (*stream_list)->text_offset = 0; - (*stream_list)->param_list = NULL; - (*stream_list)->next = head; -} - -int delete_input_stream(struct input_stream **stream_list) -{ - struct input_stream *head = *stream_list; - if(!head) - exit_error(ERROR_STATUS_EMPTY_STREAM_LIST, NULL); - *stream_list = (*stream_list)->next; - if(head->fd) - fclose(head->fd); - while(head->param_list) - { - struct macro_parameter *param_head = head->param_list; - head->param_list = param_head->next; - free(param_head->lexem); - free(param_head); - } - free(head); - return *stream_list != NULL; -} - -void add_input_stream_parameter(struct input_stream *stream_list, char *lexem) -{ - struct macro_parameter **param = &stream_list->param_list; - while(*param) - param = &(*param)->next; - *param = malloc(sizeof(struct macro_parameter)); - if(!*param) - exit_error(ERROR_STATUS_MALLOC, NULL); - (*param)->lexem = lexem; - (*param)->next = NULL; -} - -const char *get_input_stream_parameter(struct input_stream *stream_list, - unsigned long long chosen) -{ - struct macro_parameter *param = stream_list->param_list; - if(!chosen) - return stream_list->macro->lexem; - chosen--; - for(; param && chosen > 0; chosen--) - param = param->next; - if(!param) - exit_error(ERROR_STATUS_INVALID_CALL, NULL); - return param->lexem; -} - -#define BUFFER_INITIAL_SIZE 4 - -int double_buffer(char **buffer, unsigned long long *buffer_size) -{ - char *tmp_pointer = *buffer; - unsigned long long tmp_size = *buffer_size; - - if(*buffer_size == 0) - *buffer_size = BUFFER_INITIAL_SIZE; - else - *buffer_size *= 2; - - *buffer = malloc(*buffer_size); - if(!*buffer) - return 0; - - for(; tmp_size > 0; tmp_size--) - (*buffer)[tmp_size - 1] = tmp_pointer[tmp_size - 1]; - - free(tmp_pointer); - return 1; -} - -int read_symb_from_text(struct input_stream *stream_list) -{ - char symb; - if(!stream_list->macro) - exit_error(ERROR_STATUS_INVALID_STREAM, NULL); - if(!stream_list->macro->text) - exit_error(ERROR_STATUS_INVALID_STREAM, NULL); - symb = stream_list->macro->text[stream_list->text_offset]; - if(!symb) - return EOF; - stream_list->text_offset++; - return symb; -} - -#define COMMENT_SYMB ';' - -int read_real_symb(struct input_stream *stream_list) -{ - int symb; - - if(!stream_list) - exit_error(ERROR_STATUS_EMPTY_STREAM_LIST, NULL); - - if(stream_list->fd) - symb = fgetc(stream_list->fd); - else - symb = read_symb_from_text(stream_list); - - if(symb == COMMENT_SYMB) - { - for(; symb != '\n' && symb != EOF; - symb = fgetc(stream_list->fd)) - {} - } - return symb; -} - -#define SHIELD_SYMB '\\' - -int read_symb(struct input_stream *stream_list, int *shield) -{ - int symb = read_real_symb(stream_list); - if(shield) - { - *shield = 0; - if(symb == SHIELD_SYMB) - { - symb = read_real_symb(stream_list); - *shield = 1; - } - } - return symb; -} - -int is_symb_hex(char symb) -{ - if(symb >= '0' && symb <= '9') - return symb - '0'; - else - if(symb >= 'A' && symb <= 'F') - return symb - 'A' + 10; - else - if(symb >= 'a' && symb <= 'f') - return symb - 'a' + 10; - else - return -1; -} - -int is_lexem_hex(const char *lexem, unsigned long long *dest) -{ - int sign = 0; - unsigned long long hex = 0; - if(*lexem == '-' && *(lexem + 1)) - { - sign = 1; - lexem++; - } - - for(; *lexem; lexem++) - { - int num = is_symb_hex(*lexem); - if(num != -1) - hex = (hex << 4) + num; - else - return 0; - } - hex = sign ? ~hex + 1 : hex; - if(dest) - *dest = hex; - return 1; -} - -int compare_lexems(const char *lexem_one, const char *lexem_two) -{ - for(; *lexem_one && *lexem_two; lexem_one++, lexem_two++) - if(*lexem_one != *lexem_two) - return 0; - return *lexem_one == *lexem_two; -} - -char *copy_lexem(const char *lexem) -{ - char *buffer = NULL; - unsigned long long buffer_size = 0; - unsigned long long index; - - for(index = 0;; index++) - { - if(index == buffer_size) - if(!double_buffer(&buffer, &buffer_size)) - exit_error(ERROR_STATUS_MALLOC, NULL); - buffer[index] = lexem[index]; - if(!lexem[index]) - break; - } - return buffer; -} - -#define EVAL_SYMB '%' - -unsigned long long get_eval_end(const char *lexem) -{ - unsigned long long counter = 0; - - for(; *lexem && *lexem != EVAL_SYMB; lexem++, counter++) - {} - if(!*lexem) - exit_error(ERROR_STATUS_INVALID_CALL, NULL); - return counter; -} - -char *param_eval(struct input_stream *stream_list, char *lexem) -{ - char *input_lexem = lexem; - char *buffer = NULL; - unsigned long long buffer_size = 0; - const char *param = NULL; - unsigned long long index = 0; - - for(;;) - { - char symb = param && *param ? *param : *lexem++; - param = !param || !*param ? NULL : param + 1; - if(symb == EVAL_SYMB) - { - unsigned long long param_offset = get_eval_end(lexem); - unsigned long long param_num; - *(lexem + param_offset) = 0; - if(!is_lexem_hex(lexem, ¶m_num)) - exit_error(ERROR_STATUS_INVALID_CALL, NULL); - lexem += param_offset + 1; - param = get_input_stream_parameter(stream_list, - param_num); - continue; - } - if(index == buffer_size) - if(!double_buffer(&buffer, &buffer_size)) - exit_error(ERROR_STATUS_MALLOC, NULL); - buffer[index] = symb; - if(!symb) - break; - index++; - } - free(input_lexem); - return buffer; -} - -int is_separator(int symb) -{ - return symb == ' ' || symb == '\n' || symb == '\t' || symb == '\r'; -} - -char *read_lexem(struct input_stream *stream_list) -{ - char *buffer = NULL; - unsigned long long buffer_size = 0; - int symb; - int shield; - unsigned long long index; - - for(;;) - { - symb = read_symb(stream_list, &shield); - if(is_separator(symb) && !shield) - continue; - if(symb == EOF) - return NULL; - break; - } - - for(index = 0;; index++) - { - if(index == buffer_size) - if(!double_buffer(&buffer, &buffer_size)) - exit_error(ERROR_STATUS_MALLOC, NULL); - if(symb == EOF || (is_separator(symb) && !shield)) - { - buffer[index] = 0; - break; - } - buffer[index] = symb; - symb = read_symb(stream_list, &shield); - } - buffer = param_eval(stream_list, buffer); - return buffer; -} - -#define MACRO_END_SYMB ']' - -const char *read_macro_text(struct input_stream *stream_list) -{ - char *buffer = NULL; - unsigned long long buffer_size = 0; - unsigned long long index; - - for(index = 0;; index++) - { - int shield; - int symb = read_symb(stream_list, &shield); - if(index == buffer_size) - if(!double_buffer(&buffer, &buffer_size)) - exit_error(ERROR_STATUS_MALLOC, NULL); - if(symb == EOF || (symb == MACRO_END_SYMB && !shield)) - { - buffer[index] = 0; - break; - } - buffer[index] = symb; - } - return buffer; -} - -void create_macro(struct input_stream *stream_list, struct macro **macro_list) -{ - char *param_count_lexem; - struct macro *head = *macro_list; - *macro_list = malloc(sizeof(struct macro)); - if(!*macro_list) - exit_error(ERROR_STATUS_MALLOC, NULL); - (*macro_list)->lexem = read_lexem(stream_list); - if(!(*macro_list)->lexem) - exit_error(ERROR_STATUS_INVALID_MACRO, NULL); - param_count_lexem = read_lexem(stream_list); - if(!param_count_lexem || !is_lexem_hex(param_count_lexem, - &(*macro_list)->param_count)) - exit_error(ERROR_STATUS_INVALID_MACRO, NULL); - free(param_count_lexem); - (*macro_list)->text = read_macro_text(stream_list); - (*macro_list)->next = head; -} - -int find_module(struct module *module_list, const char *file_name) -{ - for(; module_list; module_list = module_list->next) - if(compare_lexems(module_list->file_name, file_name)) - return 1; - return 0; -} - -void add_module(struct module **module_list, const char *file_name) -{ - struct module *head = *module_list; - *module_list = malloc(sizeof(struct module)); - if(!*module_list) - exit_error(ERROR_STATUS_MALLOC, NULL); - (*module_list)->file_name = file_name; - (*module_list)->next = head; -} - -void include_file(struct input_stream **stream_list, - struct module **module_list) -{ - char *file_name = read_lexem(*stream_list); - FILE *fd; - if(!file_name) - exit_error(ERROR_STATUS_INVALID_INCLUDE, NULL); - if(module_list && find_module(*module_list, file_name)) - { - free(file_name); - return; - } - fd = fopen(file_name, "r"); - if(!fd) - exit_error(ERROR_STATUS_OPEN, file_name); - if(module_list) - add_module(module_list, file_name); - else - free(file_name); - add_input_stream(stream_list, fd, NULL); -} - -void push_parameter(struct input_stream *input_stream, - struct input_stream *actual_stream) -{ - char *lexem = read_lexem(input_stream); - if(!lexem) - exit_error(ERROR_STATUS_INVALID_PARAMETER, NULL); - add_input_stream_parameter(actual_stream, lexem); -} - -int find_macro(struct input_stream **stream_list, struct macro *macro_list, - const char *lexem) -{ - for(; macro_list; macro_list = macro_list->next) - { - if(compare_lexems(macro_list->lexem, lexem)) - { - struct input_stream *old_stream = *stream_list; - unsigned long long param_count = - macro_list->param_count; - add_input_stream(stream_list, NULL, macro_list); - for(; param_count > 0; param_count--) - push_parameter(old_stream, *stream_list); - return 1; - } - } - return 0; -} - -#define DIRECTORY_SEPARATOR_SYMB '/' - -unsigned long long find_last_dir_separator_pos(const char *file_name) -{ - const char *orig_file_name = file_name; - unsigned long long pos = 0; - for(; *file_name; file_name++) - if(*file_name == DIRECTORY_SEPARATOR_SYMB) - pos = file_name - orig_file_name; - return pos; -} - -void initialize_stream(struct input_stream **stream_list, - const char *file_name) -{ - char *dir_path = copy_lexem(file_name); - unsigned long long dir_sep_pos = find_last_dir_separator_pos(dir_path); - FILE *fd = fopen(file_name, "r"); - if(!fd) - exit_error(ERROR_STATUS_OPEN, file_name); - add_input_stream(stream_list, fd, NULL); - if(dir_sep_pos) - { - dir_path[dir_sep_pos] = 0; - if(chdir(dir_path) == -1) - exit_error(ERROR_STATUS_CHDIR, NULL); - } - free(dir_path); -} - -void print_lexem(const char *lexem) -{ - printf("%s ", lexem); -} - -#define MACRO_SHIELD_LEXEM "#" -#define MACRO_START_LEXEM "[" -#define MACRO_INCLUDE_LEXEM "include" -#define MACRO_MODULE_LEXEM "module" -#define MACRO_LIT_LEXEM "literal" - -int main(int argc, char **argv) -{ - struct input_stream *stream_list = NULL; - struct macro *macro_list = NULL; - struct module *module_list = NULL; - char *lexem; - - if(argc <= 1) - exit_error(ERROR_STATUS_ARG, NULL); - else - initialize_stream(&stream_list, argv[1]); - - for(;; free(lexem)) - { - lexem = read_lexem(stream_list); - if(!lexem) - { - if(delete_input_stream(&stream_list)) - continue; - else - break; - } - if(compare_lexems(lexem, MACRO_SHIELD_LEXEM)) - { - free(lexem); - lexem = read_lexem(stream_list); - if(!lexem) - exit_error(ERROR_STATUS_INVALID_SHIELD, NULL); - print_lexem(lexem); - continue; - } - if(compare_lexems(lexem, MACRO_START_LEXEM)) - { - create_macro(stream_list, ¯o_list); - continue; - } - if(compare_lexems(lexem, MACRO_INCLUDE_LEXEM)) - { - include_file(&stream_list, NULL); - continue; - } - if(compare_lexems(lexem, MACRO_MODULE_LEXEM)) - { - include_file(&stream_list, &module_list); - continue; - } - if(is_lexem_hex(lexem, NULL)) - { - if(find_macro(&stream_list, macro_list, - MACRO_LIT_LEXEM)) - { - add_input_stream_parameter(stream_list, - copy_lexem(lexem)); - continue; - } - } - if(find_macro(&stream_list, macro_list, lexem)) - continue; - print_lexem(lexem); - } - - return 0; -} diff --git a/strans.c b/strans.c deleted file mode 100644 index e3d834d..0000000 --- a/strans.c +++ /dev/null @@ -1,652 +0,0 @@ -/* - Simple Stack Translator - created by exegete -*/ - -#include -#include - -struct stack_elem -{ - unsigned long long value; - struct stack_elem *next; -}; - -struct identifier -{ - const char *lexem; - unsigned long long value; - struct identifier *next; -}; - -struct segment -{ - char *buffer; - unsigned long long real_size; - unsigned long long size; - unsigned long long pointer_address; - unsigned long long base_address; - unsigned long long base_offset; - int data_size; - int data_endianness; - struct segment *next; -}; - -struct environment -{ - struct stack_elem *stack; - struct identifier *id_list; - struct segment *seg_list; - unsigned long long chosen_segment; -}; - -struct operator -{ - void (*func)(struct environment *env); - const char *lexem; -}; - -#define ERROR_STATUS_STACK_OVERFLOW 1 -#define ERROR_STATUS_STACK_EMPTY 2 -#define ERROR_STATUS_ID_LIST_OVERFLOW 3 -#define ERROR_STATUS_SEG_LIST_OVERFLOW 4 -#define ERROR_STATUS_INVALID_SEGMENT 5 -#define ERROR_STATUS_WORD_BUFFER_OVERFLOW 6 -#define ERROR_STATUS_LEXEM_OVERFLOW 7 -#define ERROR_STATUS_UNDEFINED 8 -#define ERROR_STATUS_INVALID_ACCESS 9 -#define ERROR_STATUS_INVALID_WORD_SIZE 10 -#define ERROR_STATUS_WORD_ENDIANNESS_INVALID 11 - -const char *error_msgs[] = -{ - "Stack overflow", - "Stack is empty", - "Identifier list overflow", - "Segment list overflow", - "Invalid chosen segment", - "Word buffer overflow", - "Lexem is too big", - "Undefined lexem: ", - "Invalid segment access", - "Invalid segment data size", - "Invalid segment data endianness" -}; - -void exit_error(int status, const char *lexem) -{ - if(lexem) - fprintf(stderr, "Error: %s%s\n", error_msgs[status - 1], - lexem); - else - fprintf(stderr, "Error: %s\n", error_msgs[status - 1]); - exit(status); -} - -unsigned long long create_segment(struct environment *env) -{ - struct segment **chosen_segment = &env->seg_list; - unsigned long long segment_counter = 0; - for(; *chosen_segment; chosen_segment = &(*chosen_segment)->next) - segment_counter++; - *chosen_segment = malloc(sizeof(struct segment)); - if(!*chosen_segment) - exit_error(ERROR_STATUS_SEG_LIST_OVERFLOW, NULL); - (*chosen_segment)->buffer = NULL; - (*chosen_segment)->real_size = 0; - (*chosen_segment)->size = 0; - (*chosen_segment)->pointer_address = 0; - (*chosen_segment)->base_address = 0; - (*chosen_segment)->base_offset = 0; - (*chosen_segment)->data_size = 1; - (*chosen_segment)->data_endianness = 0; - (*chosen_segment)->next = NULL; - return segment_counter; -} - -struct segment *get_segment(struct environment *env) -{ - struct segment *chosen_segment = env->seg_list; - unsigned long long segment_counter = env->chosen_segment; - while(chosen_segment && segment_counter--) - chosen_segment = chosen_segment->next; - if(!chosen_segment) - exit_error(ERROR_STATUS_INVALID_SEGMENT, NULL); - return chosen_segment; -} - -void initialize_environment(struct environment *env) -{ - env->stack = NULL; - env->id_list = NULL; - env->seg_list = NULL; - env->chosen_segment = 0; -} - -int is_separator(int symb) -{ - return symb == ' ' || symb == '\n' || symb == '\t' || symb == '\r'; -} - -#define BUFFER_INITIAL_SIZE 4 - -int double_buffer(char **buffer, unsigned long long *buffer_size) -{ - char *tmp_pointer = *buffer; - unsigned long long tmp_size = *buffer_size; - - if(*buffer_size == 0) - *buffer_size = BUFFER_INITIAL_SIZE; - else - *buffer_size *= 2; - - *buffer = malloc(*buffer_size); - if(!*buffer) - return 0; - - for(; tmp_size > 0; tmp_size--) - (*buffer)[tmp_size - 1] = tmp_pointer[tmp_size - 1]; - - free(tmp_pointer); - return 1; -} - -char *read_lexem() -{ - char *buffer = NULL; - unsigned long long buffer_size = 0; - int symb; - unsigned long long index; - - while(is_separator(symb = getchar())) - {} - - if(symb == EOF) - return NULL; - - for(index = 0;; index++) - { - if(index == buffer_size) - if(!double_buffer(&buffer, &buffer_size)) - exit_error(ERROR_STATUS_LEXEM_OVERFLOW, NULL); - if(symb == EOF || is_separator(symb)) - { - buffer[index] = 0; - break; - } - buffer[index] = symb; - symb = getchar(); - } - return buffer; -} - -void push_stack_elem(struct stack_elem **stack, unsigned long long value) -{ - struct stack_elem *head = *stack; - *stack = malloc(sizeof(struct stack_elem)); - if(!*stack) - exit_error(ERROR_STATUS_STACK_OVERFLOW, NULL); - (*stack)->value = value; - (*stack)->next = head; -} - -unsigned long long pop_stack_elem(struct stack_elem **stack) -{ - struct stack_elem *head = *stack; - unsigned long long value; - if(!head) - exit_error(ERROR_STATUS_STACK_EMPTY, NULL); - value = head->value; - *stack = head->next; - free(head); - return value; -} - -int is_symb_hex(char symb) -{ - if(symb >= '0' && symb <= '9') - return symb - '0'; - else - if(symb >= 'A' && symb <= 'F') - return symb - 'A' + 10; - else - if(symb >= 'a' && symb <= 'f') - return symb - 'a' + 10; - else - return -1; -} - -int is_lexem_hex(struct environment *env, const char *lexem) -{ - int sign = 0; - unsigned long long hex = 0; - if(*lexem == '-' && *(lexem + 1)) - { - sign = 1; - lexem++; - } - - for(; *lexem; lexem++) - { - int num = is_symb_hex(*lexem); - if(num != -1) - hex = (hex << 4) + num; - else - return 0; - } - hex = sign ? ~hex + 1 : hex; - push_stack_elem(&env->stack, hex); - return 1; -} - -int compare_lexems(const char *lexem_one, const char *lexem_two) -{ - for(; *lexem_one && *lexem_two; lexem_one++, lexem_two++) - if(*lexem_one != *lexem_two) - return 0; - return *lexem_one == *lexem_two; -} - -void add_identifier(struct identifier **id_list, const char *lexem, - unsigned long long value) -{ - struct identifier *head = *id_list; - *id_list = malloc(sizeof(struct identifier)); - if(!id_list) - exit_error(ERROR_STATUS_ID_LIST_OVERFLOW, NULL); - (*id_list)->lexem = lexem; - (*id_list)->value = value; - (*id_list)->next = head; -} - -int find_identifier(struct environment *env, const char *lexem) -{ - struct identifier *id_list = env->id_list; - for(; id_list; id_list = id_list->next) - { - if(compare_lexems(lexem, id_list->lexem)) - { - push_stack_elem(&env->stack, id_list->value); - return 1; - } - } - return 0; -} - -void segment_compile_byte(struct environment *env, char byte) -{ - unsigned long long index = get_segment(env)->size; - if(index == get_segment(env)->real_size) - if(!double_buffer(&get_segment(env)->buffer, - &get_segment(env)->real_size)) - exit_error(ERROR_STATUS_WORD_BUFFER_OVERFLOW, NULL); - get_segment(env)->buffer[index] = byte; - get_segment(env)->size++; - get_segment(env)->pointer_address++; -} - -void segment_compile(struct environment *env, unsigned long long value, - int size) -{ - int dir = get_segment(env)->data_endianness ? -1 : 1; - int index = get_segment(env)->data_endianness * (size - 1); - for(; index < size && index >= 0; index += dir) - segment_compile_byte(env, value >> index * 8); -} - -unsigned long long convert_address(struct environment *env, - unsigned long long address, int size) -{ - unsigned long long pointer_address = - get_segment(env)->pointer_address; - unsigned long long base_address = get_segment(env)->base_address; - unsigned long long base_offset = get_segment(env)->base_offset; - if(address < base_address || address + size > pointer_address) - exit_error(ERROR_STATUS_INVALID_ACCESS, NULL); - return address - base_address + base_offset; -} - -unsigned long long segment_read(struct environment *env, - unsigned long long address, int size) -{ - unsigned long long value = 0; - int dir = get_segment(env)->data_endianness ? 1 : -1; - int index = get_segment(env)->data_endianness ? 0 : (size - 1); - address = convert_address(env, address, size); - for(; index < size && index >= 0; index += dir) - value = (value << 8) + - (get_segment(env)->buffer[address + index] & 0xFF); - return value; -} - -void segment_write(struct environment *env, unsigned long long value, - unsigned long long address, int size) -{ - int dir = get_segment(env)->data_endianness ? -1 : 1; - int index = get_segment(env)->data_endianness * (size - 1); - address = convert_address(env, address, size); - for(; index < size && index >= 0; index += dir) - { - get_segment(env)->buffer[address + index] = value; - value >>= 8; - } -} - -void translator_drop(struct environment *env) -{ - pop_stack_elem(&env->stack); -} - -void translator_dup(struct environment *env) -{ - unsigned long long value = pop_stack_elem(&env->stack); - push_stack_elem(&env->stack, value); - push_stack_elem(&env->stack, value); -} - -void translator_over(struct environment *env) -{ - unsigned long long value_one = pop_stack_elem(&env->stack); - unsigned long long value_two = pop_stack_elem(&env->stack); - push_stack_elem(&env->stack, value_two); - push_stack_elem(&env->stack, value_one); - push_stack_elem(&env->stack, value_two); -} - -void translator_swap(struct environment *env) -{ - unsigned long long value_one = pop_stack_elem(&env->stack); - unsigned long long value_two = pop_stack_elem(&env->stack); - push_stack_elem(&env->stack, value_one); - push_stack_elem(&env->stack, value_two); -} - -void translator_add(struct environment *env) -{ - unsigned long long first = pop_stack_elem(&env->stack); - unsigned long long second = pop_stack_elem(&env->stack); - push_stack_elem(&env->stack, second + first); -} - -void translator_sub(struct environment *env) -{ - unsigned long long first = pop_stack_elem(&env->stack); - unsigned long long second = pop_stack_elem(&env->stack); - push_stack_elem(&env->stack, second - first); -} - -void translator_mul(struct environment *env) -{ - unsigned long long first = pop_stack_elem(&env->stack); - unsigned long long second = pop_stack_elem(&env->stack); - push_stack_elem(&env->stack, second * first); -} - -void translator_div(struct environment *env) -{ - unsigned long long first = pop_stack_elem(&env->stack); - unsigned long long second = pop_stack_elem(&env->stack); - push_stack_elem(&env->stack, second / first); -} - -void translator_mod(struct environment *env) -{ - unsigned long long first = pop_stack_elem(&env->stack); - unsigned long long second = pop_stack_elem(&env->stack); - push_stack_elem(&env->stack, second % first); -} - -void translator_define_identifier(struct environment *env) -{ - unsigned long long value = pop_stack_elem(&env->stack); - add_identifier(&env->id_list, read_lexem(), value); -} - -void translator_compile_one(struct environment *env) -{ - unsigned long long value = pop_stack_elem(&env->stack); - segment_compile(env, value, 1); -} - -void translator_compile_two(struct environment *env) -{ - unsigned long long value = pop_stack_elem(&env->stack); - segment_compile(env, value, 2); -} - -void translator_compile_four(struct environment *env) -{ - unsigned long long value = pop_stack_elem(&env->stack); - segment_compile(env, value, 4); -} - -void translator_compile_eight(struct environment *env) -{ - unsigned long long value = pop_stack_elem(&env->stack); - segment_compile(env, value, 8); -} - -void translator_compile(struct environment *env) -{ - unsigned long long value = pop_stack_elem(&env->stack); - segment_compile(env, value, get_segment(env)->data_size); -} - -void translator_reserve(struct environment *env) -{ - unsigned long long count = pop_stack_elem(&env->stack); - while(count--) - segment_compile(env, 0, 1); -} - -void translator_read_one(struct environment *env) -{ - unsigned long long value = segment_read(env, - pop_stack_elem(&env->stack), 1); - push_stack_elem(&env->stack, value); -} - -void translator_read_two(struct environment *env) -{ - unsigned long long value = segment_read(env, - pop_stack_elem(&env->stack), 2); - push_stack_elem(&env->stack, value); -} - -void translator_read_four(struct environment *env) -{ - unsigned long long value = segment_read(env, - pop_stack_elem(&env->stack), 4); - push_stack_elem(&env->stack, value); -} - -void translator_read_eight(struct environment *env) -{ - unsigned long long value = segment_read(env, - pop_stack_elem(&env->stack), 8); - push_stack_elem(&env->stack, value); -} - -void translator_read(struct environment *env) -{ - unsigned long long value = segment_read(env, - pop_stack_elem(&env->stack), get_segment(env)->data_size); - push_stack_elem(&env->stack, value); -} - -void translator_write_one(struct environment *env) -{ - unsigned long long address = pop_stack_elem(&env->stack); - unsigned long long value = pop_stack_elem(&env->stack); - segment_write(env, value, address, 1); -} - -void translator_write_two(struct environment *env) -{ - unsigned long long address = pop_stack_elem(&env->stack); - unsigned long long value = pop_stack_elem(&env->stack); - segment_write(env, value, address, 2); -} - -void translator_write_four(struct environment *env) -{ - unsigned long long address = pop_stack_elem(&env->stack); - unsigned long long value = pop_stack_elem(&env->stack); - segment_write(env, value, address, 4); -} - -void translator_write_eight(struct environment *env) -{ - unsigned long long address = pop_stack_elem(&env->stack); - unsigned long long value = pop_stack_elem(&env->stack); - segment_write(env, value, address, 8); -} - -void translator_write(struct environment *env) -{ - unsigned long long address = pop_stack_elem(&env->stack); - unsigned long long value = pop_stack_elem(&env->stack); - segment_write(env, value, address, get_segment(env)->data_size); -} - -void translator_create_segment(struct environment *env) -{ - push_stack_elem(&env->stack, create_segment(env)); -} - -void translator_choose_segment(struct environment *env) -{ - env->chosen_segment = pop_stack_elem(&env->stack); -} - -void translator_set_base(struct environment *env) -{ - get_segment(env)->base_address = pop_stack_elem(&env->stack); - get_segment(env)->pointer_address = get_segment(env)->base_address; - get_segment(env)->base_offset = get_segment(env)->size; -} - -#define WORD_SIZE_MAX 8 - -void translator_set_data_size(struct environment *env) -{ - int target_size = pop_stack_elem(&env->stack); - if(target_size <= 0 || target_size > WORD_SIZE_MAX) - exit_error(ERROR_STATUS_INVALID_WORD_SIZE, NULL); - get_segment(env)->data_size = target_size; -} - -void translator_set_data_endianness(struct environment *env) -{ - int endianness = pop_stack_elem(&env->stack); - if(endianness > 1) - exit_error(ERROR_STATUS_WORD_ENDIANNESS_INVALID, NULL); - get_segment(env)->data_endianness = endianness; -} - -void translator_get_offset(struct environment *env) -{ - push_stack_elem(&env->stack, get_segment(env)->pointer_address); -} - -void translator_get_base(struct environment *env) -{ - push_stack_elem(&env->stack, get_segment(env)->base_address); -} - -void translator_print(struct environment *env) -{ - unsigned long long value = pop_stack_elem(&env->stack); - fprintf(stderr, "%llx\n", value); -} - -const struct operator translator_operators[] = -{ - { &translator_drop, "?drop" }, - { &translator_dup, "?dup" }, - { &translator_over, "?over" }, - { &translator_swap, "?swap" }, - { &translator_add, "?+" }, - { &translator_sub, "?-" }, - { &translator_mul, "?*" }, - { &translator_div, "?/" }, - { &translator_mod, "?mod" }, - { &translator_define_identifier, "??" }, - { &translator_compile_one, "?'" }, - { &translator_compile_one, "?1." }, - { &translator_compile_two, "?2." }, - { &translator_compile_four, "?4." }, - { &translator_compile_eight, "?8." }, - { &translator_compile, "?." }, - { &translator_reserve, "?res" }, - { &translator_read_one, "?1@" }, - { &translator_read_two, "?2@" }, - { &translator_read_four, "?4@" }, - { &translator_read_eight, "?8@" }, - { &translator_read, "?@" }, - { &translator_write_one, "?1!" }, - { &translator_write_two, "?2!" }, - { &translator_write_four, "?4!" }, - { &translator_write_eight, "?8!" }, - { &translator_write, "?!" }, - { &translator_create_segment, "?create" }, - { &translator_choose_segment, "?choose" }, - { &translator_set_base, "?org" }, - { &translator_set_data_size, "?size" }, - { &translator_set_data_endianness, "?endianness" }, - { &translator_get_offset, "?$" }, - { &translator_get_base, "?$$" }, - { &translator_print, "?print" }, -}; - -int execute_operator(struct environment *env, const char *lexem) -{ - int operators_count = - sizeof(translator_operators) / sizeof(*translator_operators); - int index; - - for(index = 0; index < operators_count; index++) - { - if(compare_lexems(lexem, translator_operators[index].lexem)) - { - (*translator_operators[index].func)(env); - break; - } - } - - return index != operators_count; -} - -void print_target_buffer(struct environment *env) -{ - struct segment *seg_list; - unsigned long long index; - for(seg_list = env->seg_list; seg_list; seg_list = seg_list->next) - for(index = 0; index < seg_list->size; index++) - putchar(seg_list->buffer[index]); -} - -int main() -{ - struct environment env; - char *lexem; - - initialize_environment(&env); - - for(;; free(lexem)) - { - lexem = read_lexem(); - if(!lexem) - break; - if(find_identifier(&env, lexem)) - continue; - if(is_lexem_hex(&env, lexem)) - continue; - if(!execute_operator(&env, lexem)) - exit_error(ERROR_STATUS_UNDEFINED, lexem); - } - - print_target_buffer(&env); - - return 0; -} diff --git a/test.sts b/test.sts index 950a517..9158c49 100644 --- a/test.sts +++ b/test.sts @@ -1,11 +1,16 @@ module ia32/elf/begin.sts +module ia32/float/float.sts set_entry -'2' -'1' -top as what -what @ sys_write -what word_size + @ sys_write_err +float_init +8 float_iload +3 float_iload +float_div +float_istore '0' + sys_write +21 float_iload +4 float_iload +float_div +float_istore '0' + sys_write sys_exit module ia32/elf/end.sts -- cgit v1.2.3