From 426a92ab0907bb50b90e17919c98b3ada8653b7e Mon Sep 17 00:00:00 2001 From: Jeremiah Orians Date: Fri, 23 Feb 2018 21:18:23 -0500 Subject: [PATCH] Finally became self-hosting --- cc.c | 141 ++++---- cc.h | 2 + cc_core.c | 316 ++++++------------ cc_strings.c | 34 +- cc_types.c | 8 +- functions/require_match.c | 27 ++ libc.c | 72 ---- makefile | 49 ++- test/common_x86/ELF-i386.hex2 | 31 +- test/common_x86/x86_defs.M1 | 13 +- test/functions/calloc.c | 38 +++ test/functions/exit.c | 25 ++ test/functions/file.c | 90 +++++ test/functions/file_print.c | 26 ++ test/functions/getchar.c | 30 ++ .../libc.M1 => functions/libc-core.M1} | 48 --- test/functions/malloc.c | 37 ++ test/functions/match.c | 35 ++ test/functions/numerate_number.c | 58 ++++ test/functions/putchar.c | 24 ++ test/functions/string.c | 64 ++++ test/test.answers | 36 +- test/test00/hello.sh | 12 +- test/test01/hello.sh | 14 +- test/test01/library_call.c | 2 - test/test02/hello.sh | 14 +- test/test02/if.c | 6 +- test/test03/constant.c | 6 +- test/test03/hello.sh | 14 +- test/test04/call.c | 6 +- test/test04/hello.sh | 14 +- test/test05/hello.sh | 14 +- test/test05/string.c | 5 +- test/test06/for.c | 1 - test/test06/hello.sh | 13 +- test/test07/do.c | 6 +- test/test07/hello.sh | 14 +- test/test08/hello.sh | 15 +- test/test08/struct.c | 6 +- test/test09/goto.c | 6 +- test/test09/hello.sh | 14 +- test/test10/hello.sh | 15 +- test/test10/nested_struct.c | 7 +- test/test100/.gitignore | 7 + test/test100/cleanup.sh | 5 + test/test100/hello.sh | 59 ++++ test/test100/proof.answer | 1 + test/test11/break-do.c | 6 +- test/test11/hello.sh | 14 +- test/test12/break-for.c | 6 +- test/test12/hello.sh | 14 +- test/test13/break-while.c | 6 +- test/test13/hello.sh | 14 +- test/test14/.gitignore | 7 + test/test14/basic_args.c | 39 +++ test/test14/cleanup.sh | 5 + test/test14/hello.sh | 27 ++ test/test14/proof.answer | 1 + test/test15/.gitignore | 7 + test/test15/cleanup.sh | 5 + test/test15/file_read.c | 37 ++ test/test15/hello.sh | 28 ++ test/test15/proof.answer | 1 + test/test16/.gitignore | 7 + test/test16/cleanup.sh | 5 + test/test16/file_write.c | 44 +++ test/test16/hello.sh | 28 ++ test/test16/proof.answer | 1 + test/test17/.gitignore | 7 + test/test17/cleanup.sh | 5 + test/test17/hello.sh | 29 ++ test/test17/memset.c | 49 +++ test/test17/proof.answer | 1 + test/test18/.gitignore | 7 + test/test18/cleanup.sh | 5 + test/test18/hello.sh | 29 ++ test/test18/math.c | 76 +++++ test/test18/proof.answer | 1 + test/test19/.gitignore | 7 + test/test19/cleanup.sh | 5 + test/test19/getopt.c | 107 ++++++ test/test19/hello.sh | 32 ++ test/test19/input | 1 + test/test19/proof.answer | 1 + test/test99/hello.sh | 16 +- 85 files changed, 1648 insertions(+), 512 deletions(-) create mode 100644 functions/require_match.c delete mode 100644 libc.c create mode 100644 test/functions/calloc.c create mode 100644 test/functions/exit.c create mode 100644 test/functions/file.c create mode 100644 test/functions/file_print.c create mode 100644 test/functions/getchar.c rename test/{common_x86/libc.M1 => functions/libc-core.M1} (52%) create mode 100644 test/functions/malloc.c create mode 100644 test/functions/match.c create mode 100644 test/functions/numerate_number.c create mode 100644 test/functions/putchar.c create mode 100644 test/functions/string.c create mode 100644 test/test100/.gitignore create mode 100755 test/test100/cleanup.sh create mode 100755 test/test100/hello.sh create mode 100644 test/test100/proof.answer create mode 100644 test/test14/.gitignore create mode 100644 test/test14/basic_args.c create mode 100755 test/test14/cleanup.sh create mode 100755 test/test14/hello.sh create mode 100644 test/test14/proof.answer create mode 100644 test/test15/.gitignore create mode 100755 test/test15/cleanup.sh create mode 100644 test/test15/file_read.c create mode 100755 test/test15/hello.sh create mode 100644 test/test15/proof.answer create mode 100644 test/test16/.gitignore create mode 100755 test/test16/cleanup.sh create mode 100644 test/test16/file_write.c create mode 100755 test/test16/hello.sh create mode 100644 test/test16/proof.answer create mode 100644 test/test17/.gitignore create mode 100755 test/test17/cleanup.sh create mode 100755 test/test17/hello.sh create mode 100644 test/test17/memset.c create mode 100644 test/test17/proof.answer create mode 100644 test/test18/.gitignore create mode 100755 test/test18/cleanup.sh create mode 100755 test/test18/hello.sh create mode 100644 test/test18/math.c create mode 100644 test/test18/proof.answer create mode 100644 test/test19/.gitignore create mode 100755 test/test19/cleanup.sh create mode 100644 test/test19/getopt.c create mode 100755 test/test19/hello.sh create mode 100644 test/test19/input create mode 100644 test/test19/proof.answer diff --git a/cc.c b/cc.c index 98b4595..a4a7f37 100644 --- a/cc.c +++ b/cc.c @@ -14,9 +14,10 @@ * You should have received a copy of the GNU General Public License * along with stage0. If not, see . */ - -#include "cc.h" -#include +#include +#include +#include +#include"cc.h" /* The core functions */ void initialize_types(); @@ -24,84 +25,77 @@ struct token_list* read_all_tokens(FILE* a, struct token_list* current); struct token_list* reverse_list(struct token_list* head); struct token_list* program(struct token_list* out); void recursive_output(struct token_list* i, FILE* out); +int match(char* a, char* b); +void file_print(char* s, FILE* f); +char* parse_string(char* string); -#if !__MESC__ -static -#endif -struct option long_options[] = { - {"file", required_argument, 0, 'f'}, - {"output", required_argument, 0, 'o'}, - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - {0, 0, 0, 0} -}; - - -/* Our essential organizer */ -int main(int argc, char **argv) +void test0(struct token_list* l, FILE* o) { - global_token = NULL; - - int c; - FILE* source_file; - FILE* destination_file = stdout; - int option_index = 0; - while ((c = getopt_long(argc, argv, "f:h:o:V", long_options, &option_index)) != -1) + while(NULL != l) { - switch(c) + if(l->s[0] == 34) { - case 0: break; - case 'h': - { - file_print("Usage: M2-Planet -f FILENAME1 {-f FILENAME2} -o OUTPUT\n", stderr); - exit(EXIT_SUCCESS); - } - case 'f': - { - #if __MESC__ - source_file = open(optarg, O_RDONLY); - #else - source_file = fopen(optarg, "r"); - #endif + file_print(parse_string(l->s), o); + } + else + { + file_print(l->s, o); + } + fputc(10, o); + l = l->next; + } +} - if(NULL == source_file) - { - file_print("The file: ", stderr); - file_print(optarg, stderr); - file_print(" can not be opened!\n", stderr); - exit(EXIT_FAILURE); - } - - global_token = read_all_tokens(source_file, global_token); - break; - } - case 'o': +int main(int argc, char** argv) +{ + FILE* in = stdin; + FILE* destination_file = stdout; + int i = 1; + while(i <= argc) + { + if(NULL == argv[i]) + { + i = i + 1; + } + else if(match(argv[i], "-f")) + { + in = fopen(argv[i + 1], "r"); + if(NULL == in) { - #if __MESC__ - destination_file = open(optarg, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR); - #else - destination_file = fopen(optarg, "w"); - #endif - - if(NULL == destination_file) - { - file_print("The file: ", stderr); - file_print(optarg, stderr); - file_print(" can not be opened!\n", stderr); - exit(EXIT_FAILURE); - } - break; - } - case 'V': - { - file_print("M2-Planet 0.1\n", stdout); - exit(EXIT_SUCCESS); - } - default: - { - file_print("Unknown option\n", stderr); + file_print("Unable to open for reading file: ", stderr); + file_print(argv[i + 1], stderr); + file_print("\x0A Aborting to avoid problems\x0A", stderr); exit(EXIT_FAILURE); } + global_token = read_all_tokens(in, global_token); + i = i + 2; + } + else if(match(argv[i], "-o")) + { + destination_file = fopen(argv[i + 1], "w"); + if(NULL == destination_file) + { + file_print("Unable to open for writing file: ", stderr); + file_print(argv[i + 1], stderr); + file_print("\x0A Aborting to avoid problems\x0A", stderr); + exit(EXIT_FAILURE); + } + i = i + 2; + } + else if(match(argv[i], "--help")) + { + file_print(" -f input file\x0A -o output file\x0A --help for this message\x0A --version for file version\x0A", stdout); + exit(EXIT_SUCCESS); + } + else if(match(argv[i], "--version")) + { + file_print("Basic test version 0.0.0.1a\x0A", stderr); + exit(EXIT_SUCCESS); + } + else + { + file_print("UNKNOWN ARGUMENT\x0A", stdout); + exit(EXIT_FAILURE); } } @@ -122,5 +116,6 @@ int main(int argc, char **argv) recursive_output(globals_list, destination_file); file_print("\n# Program strings\n\n", destination_file); recursive_output(strings_list, destination_file); + file_print("\n:ELF_end\n", destination_file); return EXIT_SUCCESS; } diff --git a/cc.h b/cc.h index ee73d69..e8a1598 100644 --- a/cc.h +++ b/cc.h @@ -25,6 +25,8 @@ // CONSTANT FALSE 0 #define TRUE 1 // CONSTANT TRUE 1 +#define LF 10 +// CONSTANT LF 10 void file_print(char* s, FILE* f); int match(char* a, char* b); diff --git a/cc_core.c b/cc_core.c index 30e7905..300b658 100644 --- a/cc_core.c +++ b/cc_core.c @@ -30,6 +30,11 @@ char* break_target; /* Imported functions */ char* parse_string(char* string); +char* numerate_number(int a); +char* postpend_char(char* s, char a); +char* prepend_char(char a, char* s); +char* prepend_string(char* add, char* base); +void require_match(char* message, char* required); struct token_list* emit(char *s, struct token_list* head) { @@ -39,105 +44,6 @@ struct token_list* emit(char *s, struct token_list* head) return t; } -char* numerate_number(int a) -{ - char* result = calloc(16, sizeof(char)); - int i = 0; - - /* Deal with Zero case */ - if(0 == a) - { - result[0] = '0'; - result[1] = '\n'; - return result; - } - - /* Deal with negatives */ - if(0 > a) - { - result[0] = '-'; - i = 1; - a = a * -1; - } - - /* Using the largest 10^n number possible in 32bits */ - int divisor = 0x3B9ACA00; - /* Skip leading Zeros */ - while(0 == (a / divisor)) divisor = divisor / 10; - - /* Now simply collect numbers until divisor is gone */ - while(0 < divisor) - { - result[i] = ((a / divisor) + 48); - a = a % divisor; - divisor = divisor / 10; - i = i + 1; - } - - result[i] = '\n'; - return result; -} - -int match(char* a, char* b) -{ - int i = -1; - do - { - i = i + 1; - if(a[i] != b[i]) - { - return FALSE; - } - } while((0 != a[i]) && (0 !=b[i])); - return TRUE; -} - -char* postpend_char(char* s, char a) -{ - int i = 0; - while(0 != s[i]) - { - i = i + 1; - } - s[i] = a; - return s; -} - -char* prepend_char(char a, char* s) -{ - int hold = a; - int prev; - int i = 0; - do - { - prev = hold; - hold = s[i]; - s[i] = prev; - i = i + 1; - } while(0 != hold); - return s; -} - -char* prepend_string(char* add, char* base) -{ - char* ret = calloc(MAX_STRING, sizeof(char)); - int i = 0; - while(0 != add[i]) - { - ret[i] = add[i]; - i = i + 1; - } - - int j = 0; - while(0 != base[j]) - { - ret[i] = base[j]; - i = i + 1; - j = j + 1; - } - return ret; -} - struct token_list* sym_declare(char *s, struct type* t, struct token_list* list) { struct token_list* a = calloc(1, sizeof(struct token_list)); @@ -172,14 +78,22 @@ int stack_index(struct token_list* a, struct token_list* function) for(i = function->arguments; NULL != i; i = i->next) { - if(i == a) return depth; + if(i == a) + { + if(match("main", function->s)) + { + if(match("argc", i->s)) return (depth - 4); + else if(match("argv", i->s)) return (depth + 4); + } + return depth; + } else depth = depth + 4; } file_print(a->s,stderr); file_print(" does not exist in function ", stderr); file_print(function->s,stderr); - file_print("\n",stderr); + file_print("\x0A",stderr); exit(EXIT_FAILURE); } @@ -189,7 +103,7 @@ struct token_list* sym_get_value(char *s, struct token_list* out, struct token_l struct token_list* a = sym_lookup(s, global_constant_list); if(NULL != a) { - out = emit(prepend_string("LOAD_IMMEDIATE_eax %", postpend_char(a->arguments->s, '\n')), out); return out; + out = emit(prepend_string("LOAD_IMMEDIATE_eax %", postpend_char(a->arguments->s, LF)), out); return out; } a= sym_lookup(s, global_function_list); @@ -202,8 +116,8 @@ struct token_list* sym_get_value(char *s, struct token_list* out, struct token_l if(NULL != a) { current_target = a->type; - out = emit(prepend_string("LOAD_EFFECTIVE_ADDRESS %", postpend_char(numerate_number(stack_index(a, function)), '\n')), out); - if(!match("=", global_token->s)) out = emit("LOAD_INTEGER\n", out); + out = emit(prepend_string("LOAD_EFFECTIVE_ADDRESS %", postpend_char(numerate_number(stack_index(a, function)), LF)), out); + if(!match("=", global_token->s)) out = emit("LOAD_INTEGER\x0A", out); return out; } a = sym_lookup(s, function->arguments); @@ -211,8 +125,8 @@ struct token_list* sym_get_value(char *s, struct token_list* out, struct token_l if(NULL != a) { current_target = a->type; - out = emit(prepend_string("LOAD_EFFECTIVE_ADDRESS %", postpend_char(numerate_number(stack_index(a, function)), '\n')), out); - if(!match("=", global_token->s)) out = emit("LOAD_INTEGER\n", out); + out = emit(prepend_string("LOAD_EFFECTIVE_ADDRESS %", postpend_char(numerate_number(stack_index(a, function)), LF)), out); + if(!match("=", global_token->s) && !match("argv", s)) out = emit("LOAD_INTEGER\x0A", out); return out; } @@ -220,26 +134,16 @@ struct token_list* sym_get_value(char *s, struct token_list* out, struct token_l if(NULL != a) { current_target = a->type; - out = emit(prepend_string("LOAD_IMMEDIATE_eax &GLOBAL_", postpend_char(s, '\n')), out); - if(!match("=", global_token->s)) out = emit("LOAD_INTEGER\n", out); + out = emit(prepend_string("LOAD_IMMEDIATE_eax &GLOBAL_", postpend_char(s, LF)), out); + if(!match("=", global_token->s)) out = emit("LOAD_INTEGER\x0A", out); return out; } file_print(s ,stderr); - file_print(" is not a defined symbol\n", stderr); + file_print(" is not a defined symbol\x0A", stderr); exit(EXIT_FAILURE); } -void require_match(char* message, char* required) -{ - if(!match(global_token->s, required)) - { - file_print(message, stderr); - exit(EXIT_FAILURE); - } - global_token = global_token->next; -} - struct token_list* expression(struct token_list* out, struct token_list* function); /* @@ -253,7 +157,7 @@ struct token_list* primary_expr(struct token_list* out, struct token_list* funct { if(('0' <= global_token->s[0]) & (global_token->s[0] <= '9')) { - out = emit(prepend_string("LOAD_IMMEDIATE_eax %", postpend_char(global_token->s, '\n')), out); + out = emit(prepend_string("LOAD_IMMEDIATE_eax %", postpend_char(global_token->s, LF)), out); global_token = global_token->next; } else if((('a' <= global_token->s[0]) & (global_token->s[0] <= 'z')) | (('A' <= global_token->s[0]) & (global_token->s[0] <= 'Z'))) @@ -264,7 +168,7 @@ struct token_list* primary_expr(struct token_list* out, struct token_list* funct { global_token = global_token->next; out = expression(out, function); - require_match("Error in Primary expression\nDidn't get )\n", ")"); + require_match("Error in Primary expression\nDidn't get )\x0A", ")"); } else if(global_token->s[0] == 39) { /* 39 == ' */ @@ -292,7 +196,7 @@ struct token_list* primary_expr(struct token_list* out, struct token_list* funct { file_print("Recieved ", stderr); file_print(global_token->s, stderr); - file_print(" in primary_expr\n", stderr); + file_print(" in primary_expr\x0A", stderr); exit(EXIT_FAILURE); } @@ -309,26 +213,26 @@ struct token_list* process_expression_list(struct token_list* out, struct token_ if(global_token->s[0] != ')') { out = expression(out, function); - out = emit("PUSH_eax\t#_process_expression1\n", out); + out = emit("PUSH_eax\t#_process_expression1\x0A", out); function->temps = function->temps + 1; while(global_token->s[0] == ',') { global_token = global_token->next; out = expression(out, function); - out = emit("PUSH_eax\t#_process_expression2\n", out); + out = emit("PUSH_eax\t#_process_expression2\x0A", out); function->temps = function->temps + 1; } - require_match("ERROR in process_expression_list\nNo ) was found\n", ")"); + require_match("ERROR in process_expression_list\nNo ) was found\x0A", ")"); } else global_token = global_token->next; - out = emit(prepend_string("CALL_IMMEDIATE %FUNCTION_", postpend_char(func, '\n')), out); + out = emit(prepend_string("CALL_IMMEDIATE %FUNCTION_", postpend_char(func, LF)), out); int i; for(i = function->temps - temp; 0 != i; i = i - 1) { - out = emit("POP_ebx\t# _process_expression_locals\n", out); + out = emit("POP_ebx\t# _process_expression_locals\x0A", out); } function->temps = temp; @@ -339,7 +243,7 @@ struct token_list* process_expression_list(struct token_list* out, struct token_ struct token_list* pre_recursion(struct token_list* out, struct token_list* func) { global_token = global_token->next; - out = emit("PUSH_eax\t#_common_recursion\n", out); + out = emit("PUSH_eax\t#_common_recursion\x0A", out); func->temps = func->temps + 1; return out; } @@ -347,7 +251,7 @@ struct token_list* pre_recursion(struct token_list* out, struct token_list* func struct token_list* post_recursion(struct token_list* out, struct token_list* func) { func->temps = func->temps - 1; - out = emit("POP_ebx\t# _common_recursion\n", out); + out = emit("POP_ebx\t# _common_recursion\x0A", out); return out; } @@ -395,21 +299,21 @@ struct token_list* postfix_expr(struct token_list* out, struct token_list* funct out = emit(prepend_string("SAL_eax_Immediate8 !", numerate_number(ceil_log2(a->indirect->size))), out); } - out = emit("ADD_ebx_to_eax\n", out); + out = emit("ADD_ebx_to_eax\x0A", out); current_target = target; if(!match("=", global_token->next->s)) { if( 4 == a->indirect->size) { - out = emit("LOAD_INTEGER\n", out); + out = emit("LOAD_INTEGER\x0A", out); } else { - out = emit("LOAD_BYTE\n", out); + out = emit("LOAD_BYTE\x0A", out); } } - require_match("ERROR in postfix_expr\nMissing ]\n", "]"); + require_match("ERROR in postfix_expr\nMissing ]\x0A", "]"); } else if(global_token->s[0] == '(') { @@ -417,7 +321,7 @@ struct token_list* postfix_expr(struct token_list* out, struct token_list* funct } else if(match("->", global_token->s)) { - out = emit("# looking up offset\n", out); + out = emit("# looking up offset\x0A", out); global_token = global_token->next; struct type* i; for(i = current_target->members; NULL != i; i = i->members) @@ -430,18 +334,18 @@ struct token_list* postfix_expr(struct token_list* out, struct token_list* funct file_print(current_target->name, stderr); file_print("->", stderr); file_print(global_token->s, stderr); - file_print(" does not exist\n", stderr); + file_print(" does not exist\x0A", stderr); exit(EXIT_FAILURE); } if(0 != i->offset) { - out = emit("# -> offset calculation\n", out); + out = emit("# -> offset calculation\x0A", out); out = emit(prepend_string("LOAD_IMMEDIATE_ebx %", numerate_number(i->offset)), out); - out = emit("ADD_ebx_to_eax\n", out); + out = emit("ADD_ebx_to_eax\x0A", out); } if(!match("=", global_token->next->s)) { - out = emit("LOAD_INTEGER\n", out); + out = emit("LOAD_INTEGER\x0A", out); } current_target = i->type; global_token = global_token->next; @@ -462,26 +366,26 @@ struct token_list* unary_expr(struct token_list* out, struct token_list* functio { if(match("-", global_token->s)) { - out = emit("LOAD_IMMEDIATE_eax %0\n", out); + out = emit("LOAD_IMMEDIATE_eax %0\x0A", out); out = pre_recursion(out, function); out = postfix_expr(out, function); out = post_recursion(out, function); - out = emit("SUBTRACT_eax_from_ebx_into_ebx\nMOVE_ebx_to_eax\n", out); + out = emit("SUBTRACT_eax_from_ebx_into_ebx\nMOVE_ebx_to_eax\x0A", out); } else if(match("!", global_token->s)) { - out = emit("LOAD_IMMEDIATE_eax %1\n", out); + out = emit("LOAD_IMMEDIATE_eax %1\x0A", out); out = pre_recursion(out, function); out = postfix_expr(out, function); out = post_recursion(out, function); - out = emit("XOR_ebx_eax_into_eax\n", out); + out = emit("XOR_ebx_eax_into_eax\x0A", out); } else if(match("sizeof", global_token->s)) { global_token = global_token->next; - require_match("ERROR in unary_expr\nMissing (\n", "("); + require_match("ERROR in unary_expr\nMissing (\x0A", "("); struct type* a = type_name(); - require_match("ERROR in unary_expr\nMissing )\n", ")"); + require_match("ERROR in unary_expr\nMissing )\x0A", ")"); out = emit(prepend_string("LOAD_IMMEDIATE_eax %", numerate_number(a->size)), out); } @@ -510,35 +414,35 @@ struct token_list* additive_expr(struct token_list* out, struct token_list* func out = pre_recursion(out, function); out = unary_expr(out, function); out = post_recursion(out, function); - out = emit("ADD_ebx_to_eax\n", out); + out = emit("ADD_ebx_to_eax\x0A", out); } else if(match("-", global_token->s)) { out = pre_recursion(out, function); out = unary_expr(out, function); out = post_recursion(out, function); - out = emit("SUBTRACT_eax_from_ebx_into_ebx\nMOVE_ebx_to_eax\n", out); + out = emit("SUBTRACT_eax_from_ebx_into_ebx\nMOVE_ebx_to_eax\x0A", out); } else if(match("*", global_token->s)) { out = pre_recursion(out, function); out = unary_expr(out, function); out = post_recursion(out, function); - out = emit("MULTIPLY_eax_by_ebx_into_eax\n", out); + out = emit("MULTIPLY_eax_by_ebx_into_eax\x0A", out); } else if(match("/", global_token->s)) { out = pre_recursion(out, function); out = unary_expr(out, function); out = post_recursion(out, function); - out = emit("DIVIDE_eax_by_ebx_into_eax\n", out); + out = emit("XCHG_eax_ebx\nLOAD_IMMEDIATE_edx %0\nDIVIDE_eax_by_ebx_into_eax\x0A", out); } else if(match("%", global_token->s)) { out = pre_recursion(out, function); out = unary_expr(out, function); out = post_recursion(out, function); - out = emit("MODULUS_eax_from_ebx_into_ebx\nMOVE_ebx_to_eax\n", out); + out = emit("XCHG_eax_ebx\nLOAD_IMMEDIATE_edx %0\nMODULUS_eax_from_ebx_into_ebx\nMOVE_edx_to_eax\x0A", out); } else return out; } @@ -564,7 +468,7 @@ struct token_list* shift_expr(struct token_list* out, struct token_list* functio /* Ugly hack to Work around flaw in x86 */ struct token_list* old = out->next; free(out); - out = emit("COPY_eax_to_ecx\nPOP_eax\nSAL_eax_cl\n", old); + out = emit("COPY_eax_to_ecx\nPOP_eax\nSAL_eax_cl\x0A", old); } else if(match(">>", global_token->s)) { @@ -574,7 +478,7 @@ struct token_list* shift_expr(struct token_list* out, struct token_list* functio /* Ugly hack to Work around flaw in x86 */ struct token_list* old = out->next; free(out); - out = emit("COPY_eax_to_ecx\nPOP_eax\nSAR_eax_cl\n", old); + out = emit("COPY_eax_to_ecx\nPOP_eax\nSAR_eax_cl\x0A", old); } else { @@ -602,28 +506,28 @@ struct token_list* relational_expr(struct token_list* out, struct token_list* fu out = pre_recursion(out, function); out = shift_expr(out, function); out = post_recursion(out, function); - out = emit("CMP\nSETL\nMOVEZBL\n", out); + out = emit("CMP\nSETL\nMOVEZBL\x0A", out); } else if(match("<=", global_token->s)) { out = pre_recursion(out, function); out = shift_expr(out, function); out = post_recursion(out, function); - out = emit("CMP\nSETLE\nMOVEZBL\n", out); + out = emit("CMP\nSETLE\nMOVEZBL\x0A", out); } else if(match(">=", global_token->s)) { out = pre_recursion(out, function); out = shift_expr(out, function); out = post_recursion(out, function); - out = emit("CMP\nSETGE\nMOVEZBL\n", out); + out = emit("CMP\nSETGE\nMOVEZBL\x0A", out); } else if(match(">", global_token->s)) { out = pre_recursion(out, function); out = shift_expr(out, function); out = post_recursion(out, function); - out = emit("CMP\nSETG\nMOVEZBL\n", out); + out = emit("CMP\nSETG\nMOVEZBL\x0A", out); } else return out; } @@ -646,14 +550,14 @@ struct token_list* equality_expr(struct token_list* out, struct token_list* func out = pre_recursion(out, function); out = relational_expr(out, function); out = post_recursion(out, function); - out = emit("CMP\nSETE\nMOVEZBL\n", out); + out = emit("CMP\nSETE\nMOVEZBL\x0A", out); } else if(match("!=", global_token->s)) { out = pre_recursion(out, function); out = relational_expr(out, function); out = post_recursion(out, function); - out = emit("CMP\nSETNE\nMOVEZBL\n", out); + out = emit("CMP\nSETNE\nMOVEZBL\x0A", out); } else return out; } @@ -673,7 +577,7 @@ struct token_list* bitwise_and_expr(struct token_list* out, struct token_list* f out = pre_recursion(out, function); out = equality_expr(out, function); out = post_recursion(out, function); - out = emit("AND_eax_ebx\n", out); + out = emit("AND_eax_ebx\x0A", out); } return out; } @@ -692,7 +596,7 @@ struct token_list* bitwise_or_expr(struct token_list* out, struct token_list* fu out = pre_recursion(out, function); out = bitwise_and_expr(out, function); out = post_recursion(out, function); - out = emit("OR_eax_ebx\n", out); + out = emit("OR_eax_ebx\x0A", out); } return out; } @@ -716,15 +620,15 @@ struct token_list* expression(struct token_list* out, struct token_list* functio if(member) { - if(1 == target->indirect->size) out = emit("STORE_CHAR\n", out); + if(1 == target->indirect->size) out = emit("STORE_CHAR\x0A", out); else if(4 == target->indirect->size) { - out = emit("STORE_INTEGER\n", out); + out = emit("STORE_INTEGER\x0A", out); } } else { - out = emit("STORE_INTEGER\n", out); + out = emit("STORE_INTEGER\x0A", out); } } return out; @@ -735,7 +639,7 @@ struct token_list* expression(struct token_list* out, struct token_list* functio struct token_list* collect_local(struct token_list* out, struct token_list* function) { struct type* type_size = type_name(); - out = emit(prepend_string("# Defining local ", prepend_string(global_token->s, "\n")), out); + out = emit(prepend_string("# Defining local ", prepend_string(global_token->s, "\x0A")), out); struct token_list* a = sym_declare(global_token->s, type_size, function->locals); function->locals = a; @@ -749,9 +653,9 @@ struct token_list* collect_local(struct token_list* out, struct token_list* func } function->temps = function->temps + 1; - require_match("ERROR in collect_local\nMissing ;\n", ";"); + require_match("ERROR in collect_local\nMissing ;\x0A", ";"); - out = emit(prepend_string("PUSH_eax\t#", prepend_string(a->s, "\n")), out); + out = emit(prepend_string("PUSH_eax\t#", prepend_string(a->s, "\x0A")), out); return out; } @@ -767,12 +671,12 @@ struct token_list* process_if(struct token_list* out, struct token_list* functio out = emit(prepend_string("# IF_", number_string), out); global_token = global_token->next; - require_match("ERROR in process_if\nMISSING (\n", "("); + require_match("ERROR in process_if\nMISSING (\x0A", "("); out = expression(out, function); out = emit(prepend_string("TEST\nJUMP_EQ %ELSE_", number_string), out); - require_match("ERROR in process_if\nMISSING )\n", ")"); + require_match("ERROR in process_if\nMISSING )\x0A", ")"); out = statement(out, function); out = emit(prepend_string("JUMP %_END_IF_", number_string), out); @@ -802,25 +706,25 @@ struct token_list* process_for(struct token_list* out, struct token_list* functi global_token = global_token->next; - require_match("ERROR in process_for\nMISSING (\n", "("); + require_match("ERROR in process_for\nMISSING (\x0A", "("); out = expression(out, function); out = emit(prepend_string(":FOR_", number_string), out); - require_match("ERROR in process_for\nMISSING ;1\n", ";"); + require_match("ERROR in process_for\nMISSING ;1\x0A", ";"); out = expression(out, function); out = emit(prepend_string("TEST\nJUMP_EQ %FOR_END_", number_string), out); out = emit(prepend_string("JUMP %FOR_THEN_", number_string), out); out = emit(prepend_string(":FOR_ITER_", number_string), out); - require_match("ERROR in process_for\nMISSING ;2\n", ";"); + require_match("ERROR in process_for\nMISSING ;2\x0A", ";"); out = expression(out, function); out = emit(prepend_string("JUMP %FOR_", number_string), out); out = emit(prepend_string(":FOR_THEN_", number_string), out); - require_match("ERROR in process_for\nMISSING )\n", ")"); + require_match("ERROR in process_for\nMISSING )\x0A", ")"); out = statement(out, function); out = emit(prepend_string("JUMP %FOR_ITER_", number_string), out); @@ -835,15 +739,15 @@ struct token_list* process_for(struct token_list* out, struct token_list* functi struct token_list* process_asm(struct token_list* out) { global_token = global_token->next; - require_match("ERROR in process_asm\nMISSING (\n", "("); + require_match("ERROR in process_asm\nMISSING (\x0A", "("); while(34 == global_token->s[0]) {/* 34 == " */ out = emit((global_token->s + 1), out); - out = emit("\n", out); + out = emit("\x0A", out); global_token = global_token->next; } - require_match("ERROR in process_asm\nMISSING )\n", ")"); - require_match("ERROR in process_asm\nMISSING ;\n", ";"); + require_match("ERROR in process_asm\nMISSING )\x0A", ")"); + require_match("ERROR in process_asm\nMISSING ;\x0A", ";"); return out; } @@ -864,11 +768,11 @@ struct token_list* process_do(struct token_list* out, struct token_list* functio global_token = global_token->next; out = statement(out, function); - require_match("ERROR in process_do\nMISSING while\n", "while"); - require_match("ERROR in process_do\nMISSING (\n", "("); + require_match("ERROR in process_do\nMISSING while\x0A", "while"); + require_match("ERROR in process_do\nMISSING (\x0A", "("); out = expression(out, function); - require_match("ERROR in process_do\nMISSING )\n", ")"); - require_match("ERROR in process_do\nMISSING ;\n", ";"); + require_match("ERROR in process_do\nMISSING )\x0A", ")"); + require_match("ERROR in process_do\nMISSING ;\x0A", ";"); out = emit(prepend_string("TEST\nJUMP_NE %DO_", number_string), out); out = emit(prepend_string(":DO_END_", number_string), out); @@ -895,13 +799,13 @@ struct token_list* process_while(struct token_list* out, struct token_list* func out = emit(prepend_string(":WHILE_", number_string), out); global_token = global_token->next; - require_match("ERROR in process_while\nMISSING (\n", "("); + require_match("ERROR in process_while\nMISSING (\x0A", "("); out = expression(out, function); out = emit(prepend_string("TEST\nJUMP_EQ %END_WHILE_", number_string), out); out = emit(prepend_string("# THEN_while_", number_string), out); - require_match("ERROR in process_while\nMISSING )\n", ")"); + require_match("ERROR in process_while\nMISSING )\x0A", ")"); out = statement(out, function); out = emit(prepend_string("JUMP %WHILE_", number_string), out); @@ -918,14 +822,14 @@ struct token_list* return_result(struct token_list* out, struct token_list* func global_token = global_token->next; if(global_token->s[0] != ';') out = expression(out, function); - require_match("ERROR in return_result\nMISSING ;\n", ";"); + require_match("ERROR in return_result\nMISSING ;\x0A", ";"); struct token_list* i; for(i = function->locals; NULL != i; i = i->next) { - out = emit("POP_ebx\t# _return_result_locals\n", out); + out = emit("POP_ebx\t# _return_result_locals\x0A", out); } - out = emit("RETURN\n", out); + out = emit("RETURN\x0A", out); return out; } @@ -946,9 +850,9 @@ struct token_list* recursive_statement(struct token_list* out, struct token_list struct token_list* i; for(i = function->locals; frame != i; i = i->next) { - if(!match("RETURN\n", out->s)) + if(!match("RETURN\x0A", out->s)) { - out = emit( "POP_ebx\t# _recursive_statement_locals\n", out); + out = emit( "POP_ebx\t# _recursive_statement_locals\x0A", out); } function->locals = function->locals->next; } @@ -984,7 +888,7 @@ struct token_list* statement(struct token_list* out, struct token_list* function else if(':' == global_token->s[0]) { out = emit(global_token->s, out); - out = emit("\t#C goto label\n", out); + out = emit("\t#C goto label\x0A", out); global_token = global_token->next; } else if((NULL != lookup_type(global_token->s)) || match("struct", global_token->s)) @@ -1014,9 +918,9 @@ struct token_list* statement(struct token_list* out, struct token_list* function else if(match("goto", global_token->s)) { global_token = global_token->next; - out = emit(prepend_string("JUMP %", prepend_string(global_token->s, "\n")), out); + out = emit(prepend_string("JUMP %", prepend_string(global_token->s, "\x0A")), out); global_token = global_token->next; - require_match("ERROR in statement\nMissing ;\n", ";"); + require_match("ERROR in statement\nMissing ;\x0A", ";"); } else if(match("return", global_token->s)) { @@ -1033,17 +937,17 @@ struct token_list* statement(struct token_list* out, struct token_list* function while(i != break_locals) { if(NULL == i) break; - out = emit("POP_ebx\t# break_cleanup_locals\n", out); + out = emit("POP_ebx\t# break_cleanup_locals\x0A", out); i = i->next; } global_token = global_token->next; - out = emit(prepend_string("JUMP %", prepend_string(break_target, "\n")), out); - require_match("ERROR in statement\nMissing ;\n", ";"); + out = emit(prepend_string("JUMP %", prepend_string(break_target, "\x0A")), out); + require_match("ERROR in statement\nMissing ;\x0A", ";"); } else { out = expression(out, function); - require_match("ERROR in statement\nMISSING ;\n", ";"); + require_match("ERROR in statement\nMISSING ;\x0A", ";"); } return out; } @@ -1091,14 +995,14 @@ struct token_list* declare_function(struct token_list* out, struct type* type) if(global_token->s[0] == ';') global_token = global_token->next; else { - out = emit(prepend_string("# Defining function ", prepend_string(essential, "\n")), out); - out = emit(prepend_string(":FUNCTION_", prepend_string(essential, "\n")), out); + out = emit(prepend_string("# Defining function ", prepend_string(essential, "\x0A")), out); + out = emit(prepend_string(":FUNCTION_", prepend_string(essential, "\x0A")), out); out = statement(out, func); /* Prevent duplicate RETURNS */ - if(!match("RETURN\n", out->s)) + if(!match("RETURN\x0A", out->s)) { - out = emit("RETURN\n", out); + out = emit("RETURN\x0A", out); } } return out; @@ -1124,6 +1028,7 @@ struct token_list* declare_function(struct token_list* out, struct type* type) */ struct token_list* program(struct token_list* out) { + struct type* type_size; while(NULL != global_token) { new_type: @@ -1135,7 +1040,7 @@ new_type: } else { - struct type* type_size = type_name(); + type_size = type_name(); if(NULL == type_size) { goto new_type; @@ -1147,8 +1052,8 @@ new_type: global_symbol_list = sym_declare(global_token->prev->s, type_size, global_symbol_list); /* Ensure 4 bytes are allocated for the global */ - globals_list = emit(prepend_string(":GLOBAL_", prepend_string(global_token->prev->s, "\n")), globals_list); - globals_list = emit("NOP\n", globals_list); + globals_list = emit(prepend_string(":GLOBAL_", prepend_string(global_token->prev->s, "\x0A")), globals_list); + globals_list = emit("NOP\x0A", globals_list); global_token = global_token->next; } @@ -1157,7 +1062,7 @@ new_type: { file_print("Recieved ", stderr); file_print(global_token->s, stderr); - file_print(" in program\n", stderr); + file_print(" in program\x0A", stderr); exit(EXIT_FAILURE); } } @@ -1171,12 +1076,3 @@ void recursive_output(struct token_list* i, FILE* out) recursive_output(i->next, out); file_print(i->s, out); } - -void file_print(char* s, FILE* f) -{ - while(0 != s[0]) - { - fputc(s[0], f); - s = s + 1; - } -} diff --git a/cc_strings.c b/cc_strings.c index 8d98684..24b6b1f 100644 --- a/cc_strings.c +++ b/cc_strings.c @@ -81,6 +81,14 @@ int weird(char* string) else if('F' == string[2]) return TRUE; else return weird(string+3); } + else if('n' == string[1]) + { + return weird(string+2); + } + else if('t' == string[1]) + { + return weird(string+2); + } else { return weird(string+3); @@ -107,6 +115,16 @@ char* collect_regular_string(char* string) message[i] = t1 + t2; j = j + 4; } + else if((string[j] == '\\') & (string[j + 1] == 'n')) + { + message[i] = 10; + j = j + 2; + } + else if((string[j] == '\\') & (string[j + 1] == 't')) + { + message[i] = 9; + j = j + 2; + } else { message[i] = string[j]; @@ -117,7 +135,7 @@ char* collect_regular_string(char* string) } message[i] = 34; - message[i + 1] = '\n'; + message[i + 1] = LF; return message; } @@ -141,6 +159,18 @@ char* collect_weird_string(char* string) hold[k + 2] = upcase(string[j + 3]); j = j + 4; } + else if((string[j] == '\\') & (string[j + 1] == 'n')) + { + hold[k + 1] = '0'; + hold[k + 2] = 'A'; + j = j + 2; + } + else if((string[j] == '\\') & (string[j + 1] == 't')) + { + hold[k + 1] = '0'; + hold[k + 2] = '9'; + j = j + 2; + } else { hold[k + 1] = table[(string[j] >> 4)]; @@ -155,7 +185,7 @@ char* collect_weird_string(char* string) hold[k + 1] = '0'; hold[k + 2] = '0'; hold[k + 3] = 39; - hold[k + 4] = '\n'; + hold[k + 4] = LF; return hold; } diff --git a/cc_types.c b/cc_types.c index 144dd45..f0b909d 100644 --- a/cc_types.c +++ b/cc_types.c @@ -95,7 +95,7 @@ void create_struct() global_types = head; global_token = global_token->next; i->size = 4; - require_match("ERROR in create_struct\nMissing {\n", "{"); + require_match("ERROR in create_struct\x0A Missing {\x0A", "{"); struct type* last = NULL; while('}' != global_token->s[0]) { @@ -108,12 +108,12 @@ void create_struct() i->offset = offset; offset = offset + member_type->size; global_token = global_token->next; - require_match("ERROR in create_struct\nMissing ;\n", ";"); + require_match("ERROR in create_struct\x0A Missing ;\x0A", ";"); last = i; } global_token = global_token->next; - require_match("ERROR in create_struct\nMissing ;\n", ";"); + require_match("ERROR in create_struct\x0A Missing ;\x0A", ";"); head->size = offset; head->members = last; @@ -145,7 +145,7 @@ struct type* type_name() { file_print("Unknown type ", stderr); file_print(global_token->s, stderr); - file_print("\n", stderr); + file_print("\x0A", stderr); exit(EXIT_FAILURE); } else if(NULL == ret) diff --git a/functions/require_match.c b/functions/require_match.c new file mode 100644 index 0000000..6500218 --- /dev/null +++ b/functions/require_match.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2016 Jeremiah Orians + * This file is part of stage0. + * + * stage0 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * stage0 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with stage0. If not, see . + */ +#include "../cc.h" + +void require_match(char* message, char* required) +{ + if(!match(global_token->s, required)) + { + file_print(message, stderr); + exit(EXIT_FAILURE); + } + global_token = global_token->next; +} diff --git a/libc.c b/libc.c deleted file mode 100644 index b03eaa4..0000000 --- a/libc.c +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright (C) 2016 Jeremiah Orians - * This file is part of stage0. - * - * stage0 is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * stage0 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with stage0. If not, see . - */ - -#include "cc.h" -// CONSTANT NULL 0 -// CONSTANT EXIT_FAILURE 1 -// CONSTANT EXIT_SUCCESS 0 -// CONSTANT stdin 0 -// CONSTANT stdout 1 -// CONSTANT stderr 2 - -int fgetc(FILE* f); -void fputc(char s, FILE* f); -FILE* fopen(char* filename, char* mode); -int fclose(FILE* file); -void* malloc(int size) -{ - asm("STORE_eax_into_ESP_IMMEDIATE8 !4" - "PUSH_eax" - "LOAD_IMMEDIATE_eax %45" - "LOAD_IMMEDIATE_ebx %0" - "INT_80" - "POP_ebx" - "ADD_eax_to_ebx" - "PUSH_eax" - "PUSH_ebx" - "LOAD_IMMEDIATE_eax %45" - "INT_80" - "POP_ebx" - "CMP" - "POP_eax" - "JUMP_EQ8 !FUNCTION_malloc_Done" - "LOAD_IMMEDIATE_eax %-1" - ":FUNCTION_malloc_Done" - "RETURN"); -} -void* calloc(int count, int size) -{ - char* ret = malloc(count * size); - int i; - for(i = (count * size); i >= 0; i = i - 1) - { - ret[i] = 0; - } - return ret; -} - -void free(void* pointer) -{ - return; -} -void exit(int value) -{ - asm("POP_ebx" - "POP_ebx" - "LOAD_IMMEDIATE_eax %1" - "INT_80"); -} diff --git a/makefile b/makefile index 6fb031f..1809b08 100644 --- a/makefile +++ b/makefile @@ -6,12 +6,27 @@ all: M2-Planet CC=gcc CFLAGS=-D_GNU_SOURCE -O0 -std=c99 -ggdb -M2-Planet: cc_reader.c cc_strings.c cc_core.c cc.c cc_types.c cc.h | bin - $(CC) $(CFLAGS) cc_reader.c cc_strings.c cc_core.c cc.c cc_types.c cc.h -o bin/M2-Planet +M2-Planet-gcc: cc_reader.c cc_strings.c cc_core.c cc.c cc_types.c cc.h | bin + $(CC) $(CFLAGS) \ + test/functions/match.c \ + test/functions/numerate_number.c \ + test/functions/file_print.c \ + test/functions/string.c \ + functions/require_match.c \ + cc_reader.c \ + cc_strings.c \ + cc_types.c \ + cc_core.c \ + cc.c \ + cc.h \ + -o bin/M2-Planet-gcc M2-Planet-minimal: cc_reader.c cc_strings.c cc_core.c cc-minimal.c cc_types.c cc.h | bin $(CC) $(CFLAGS) cc_reader.c cc_strings.c cc_core.c cc-minimal.c cc_types.c cc.h -o bin/M2-Planet-minimal +M2-Planet: M2-Planet-gcc | bin results + ./test/test100/hello.sh + # Clean up after ourselves .PHONY: clean clean: @@ -30,6 +45,12 @@ clean: ./test/test11/cleanup.sh ./test/test12/cleanup.sh ./test/test13/cleanup.sh + ./test/test14/cleanup.sh + ./test/test15/cleanup.sh + ./test/test16/cleanup.sh + ./test/test17/cleanup.sh + ./test/test18/cleanup.sh + ./test/test19/cleanup.sh ./test/test99/cleanup.sh # Directories @@ -54,6 +75,12 @@ test: test00-binary \ test11-binary \ test12-binary \ test13-binary \ + test14-binary \ + test15-binary \ + test16-binary \ + test17-binary \ + test18-binary \ + test19-binary \ test99-binary | results sha256sum -c test/test.answers @@ -99,6 +126,24 @@ test12-binary: M2-Planet | results test13-binary: M2-Planet | results test/test13/hello.sh +test14-binary: M2-Planet | results + test/test14/hello.sh + +test15-binary: M2-Planet | results + test/test15/hello.sh + +test16-binary: M2-Planet | results + test/test16/hello.sh + +test17-binary: M2-Planet | results + test/test17/hello.sh + +test18-binary: M2-Planet | results + test/test18/hello.sh + +test19-binary: M2-Planet | results + test/test19/hello.sh + test99-binary: M2-Planet | results test/test99/hello.sh diff --git a/test/common_x86/ELF-i386.hex2 b/test/common_x86/ELF-i386.hex2 index 40c7d6e..11e9a71 100644 --- a/test/common_x86/ELF-i386.hex2 +++ b/test/common_x86/ELF-i386.hex2 @@ -15,9 +15,20 @@ ### You should have received a copy of the GNU General Public License ### along with stage0. If not, see . +### stage0's hex2 format for x86 +### !