diff --git a/cc-minimal.c b/cc-minimal.c index 62ec871..c7018e8 100644 --- a/cc-minimal.c +++ b/cc-minimal.c @@ -21,28 +21,22 @@ void initialize_types(); 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(FILE* out, struct token_list* i); +void recursive_output(struct token_list* i, FILE* out); /* Our essential organizer */ -int main(int argc, char **argv) +int main() { - if (argc < 3) - { - fprintf(stderr, "We require more arguments\n"); - exit(EXIT_FAILURE); - } - initialize_types(); - FILE* input = fopen(argv[1], "r"); + FILE* input = fopen("input.c", "r"); global_token = reverse_list(read_all_tokens(input, NULL)); struct token_list* output_list = program(NULL); - FILE* output = fopen(argv[2], "w"); - fprintf(output, "\n# Core program\n\n"); - recursive_output(output, output_list); - fprintf(output, "\n# Program global variables\n\n"); - recursive_output(output, globals_list); - fprintf(output, "\n# Program strings\n\n"); - recursive_output(output, strings_list); + FILE* output = fopen("input.M1", "w"); + file_print("\n# Core program\n\n", output); + recursive_output(output_list, output); + file_print("\n# Program global variables\n\n", output); + recursive_output(globals_list, output); + file_print("\n# Program strings\n\n", output); + recursive_output(strings_list, output); fclose(output); return 0; } diff --git a/cc.c b/cc.c index f583962..98b4595 100644 --- a/cc.c +++ b/cc.c @@ -23,7 +23,7 @@ void initialize_types(); 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(FILE* out, struct token_list* i); +void recursive_output(struct token_list* i, FILE* out); #if !__MESC__ static @@ -44,7 +44,7 @@ int main(int argc, char **argv) int c; FILE* source_file; - FILE* destination_file; + FILE* destination_file = stdout; int option_index = 0; while ((c = getopt_long(argc, argv, "f:h:o:V", long_options, &option_index)) != -1) { @@ -53,7 +53,7 @@ int main(int argc, char **argv) case 0: break; case 'h': { - fprintf(stderr, "Usage: %s -f FILENAME1 {-f FILENAME2} -o OUTPUT\n", argv[0]); + file_print("Usage: M2-Planet -f FILENAME1 {-f FILENAME2} -o OUTPUT\n", stderr); exit(EXIT_SUCCESS); } case 'f': @@ -66,7 +66,9 @@ int main(int argc, char **argv) if(NULL == source_file) { - fprintf(stderr, "The file: %s can not be opened!\n", optarg); + file_print("The file: ", stderr); + file_print(optarg, stderr); + file_print(" can not be opened!\n", stderr); exit(EXIT_FAILURE); } @@ -83,19 +85,21 @@ int main(int argc, char **argv) if(NULL == destination_file) { - fprintf(stderr, "The file: %s can not be opened!\n", optarg); + file_print("The file: ", stderr); + file_print(optarg, stderr); + file_print(" can not be opened!\n", stderr); exit(EXIT_FAILURE); } break; } case 'V': { - fprintf(stdout, "M2-Planet 0.1\n"); + file_print("M2-Planet 0.1\n", stdout); exit(EXIT_SUCCESS); } default: { - fprintf(stderr, "Unknown option\n"); + file_print("Unknown option\n", stderr); exit(EXIT_FAILURE); } } @@ -103,7 +107,7 @@ int main(int argc, char **argv) if(NULL == global_token) { - fprintf(stderr, "Either no input files were given or they were empty\n"); + file_print("Either no input files were given or they were empty\n", stderr); exit(EXIT_FAILURE); } global_token = reverse_list(global_token); @@ -112,11 +116,11 @@ int main(int argc, char **argv) struct token_list* output_list = program(NULL); /* Output the program we have compiled */ - fprintf(destination_file, "\n# Core program\n\n"); - recursive_output(destination_file, output_list); - fprintf(destination_file, "\n# Program global variables\n\n"); - recursive_output(destination_file, globals_list); - fprintf(destination_file, "\n# Program strings\n\n"); - recursive_output(destination_file, strings_list); + file_print("\n# Core program\n\n", destination_file); + recursive_output(output_list, destination_file); + file_print("\n# Program global variables\n\n", destination_file); + recursive_output(globals_list, destination_file); + file_print("\n# Program strings\n\n", destination_file); + recursive_output(strings_list, destination_file); return EXIT_SUCCESS; } diff --git a/cc.h b/cc.h index 84edaf9..40f6577 100644 --- a/cc.h +++ b/cc.h @@ -18,9 +18,21 @@ #include #include #include -#include #define MAX_STRING 4096 +// CONSTANT MAX_STRING 4096 +#define FALSE 0 +// CONSTANT FALSE 0 +#define TRUE 1 +// CONSTANT TRUE 1 +// CONSTANT NULL 0 +// CONSTANT EXIT_FAILURE 1 +// CONSTANT EXIT_SUCCESS 0 +// CONSTANT stdin 0 +// CONSTANT stdout 1 +// CONSTANT stderr 2 + +void file_print(char* s, FILE* f); struct type { @@ -29,17 +41,15 @@ struct type int offset; struct type* indirect; struct type* members; + struct type* type; char* name; }; struct token_list { struct token_list* next; - union - { - struct token_list* prev; - struct token_list* entry; - }; + struct token_list* prev; + struct token_list* entry; char* s; struct type* type; struct token_list* arguments; @@ -47,6 +57,9 @@ struct token_list int temps; }; +/* What types we have */ +struct type* global_types; + /* What we are currently working on */ struct token_list* global_token; diff --git a/cc_core.c b/cc_core.c index 46621c2..f8a3ee9 100644 --- a/cc_core.c +++ b/cc_core.c @@ -19,13 +19,12 @@ #include /* Global lists */ -struct type* global_types; struct token_list* global_symbol_list; struct token_list* global_function_list; struct token_list* global_constant_list; /* What we are currently working on */ -struct token_list* current_target; +struct type* current_target; /* Imported functions */ char* parse_string(char* string); @@ -96,7 +95,8 @@ struct token_list* sym_declare(char *s, struct type* t, struct token_list* list) struct token_list* sym_lookup(char *s, struct token_list* symbol_list) { - for(struct token_list* i = symbol_list; NULL != i; i = i->next) + struct token_list* i; + for(i = symbol_list; NULL != i; i = i->next) { if(0 == strcmp(s,i->s)) return i; } @@ -106,7 +106,8 @@ struct token_list* sym_lookup(char *s, struct token_list* symbol_list) int stack_index(struct token_list* a, struct token_list* function) { int depth = 4 * function->temps; - for(struct token_list* i = function->locals; NULL != i; i = i->next) + struct token_list* i; + for(i = function->locals; NULL != i; i = i->next) { if(i == a) return depth; else depth = depth + 4; @@ -115,13 +116,16 @@ int stack_index(struct token_list* a, struct token_list* function) /* Deal with offset caused by return pointer */ depth = depth+ 4; - for(struct token_list* i = function->arguments; NULL != i; i = i->next) + for(i = function->arguments; NULL != i; i = i->next) { if(i == a) return depth; else depth = depth + 4; } - fprintf(stderr, "%s does not exist in function %s\n", a->s, function->s); + file_print(a->s,stderr); + file_print(" does not exist in function ", stderr); + file_print(function->s,stderr); + file_print("\n",stderr); exit(EXIT_FAILURE); } @@ -131,7 +135,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 = double_emit("LOAD_IMMEDIATE_eax %", a->arguments->s, out, true); return out; + out = double_emit("LOAD_IMMEDIATE_eax %", a->arguments->s, out, TRUE); return out; } a= sym_lookup(s, global_function_list); @@ -143,8 +147,8 @@ struct token_list* sym_get_value(char *s, struct token_list* out, struct token_l a= sym_lookup(s, function->locals); if(NULL != a) { - current_target = a; - out = double_emit("LOAD_EFFECTIVE_ADDRESS %", numerate_number(stack_index(a, function)), out, false); + current_target = a->type; + out = double_emit("LOAD_EFFECTIVE_ADDRESS %", numerate_number(stack_index(a, function)), out, FALSE); if(strcmp(global_token->s, "=")) out = emit("LOAD_INTEGER\n", out); return out; } @@ -152,8 +156,8 @@ struct token_list* sym_get_value(char *s, struct token_list* out, struct token_l if(NULL != a) { - current_target = a; - out = double_emit("LOAD_EFFECTIVE_ADDRESS %", numerate_number(stack_index(a, function)), out, false); + current_target = a->type; + out = double_emit("LOAD_EFFECTIVE_ADDRESS %", numerate_number(stack_index(a, function)), out, FALSE); if(strcmp(global_token->s, "=")) out = emit("LOAD_INTEGER\n", out); return out; } @@ -161,21 +165,22 @@ struct token_list* sym_get_value(char *s, struct token_list* out, struct token_l a = sym_lookup(s, global_symbol_list); if(NULL != a) { - current_target = a; - out = double_emit("LOAD_IMMEDIATE_eax &GLOBAL_", s, out, true); + current_target = a->type; + out = double_emit("LOAD_IMMEDIATE_eax &GLOBAL_", s, out, TRUE); if(strcmp(global_token->s, "=")) out = emit("LOAD_INTEGER\n", out); return out; } - fprintf(stderr, "%s is not a defined symbol\n", s); + file_print(s ,stderr); + file_print(" is not a defined symbol\n", stderr); exit(EXIT_FAILURE); } -void require_char(char* message, char required) +void require_match(char* message, char* required) { - if(global_token->s[0] != required) + if(strcmp(global_token->s, required)) { - fprintf(stderr, "%s", message); + file_print(message, stderr); exit(EXIT_FAILURE); } global_token = global_token->next; @@ -189,11 +194,12 @@ struct token_list* expression(struct token_list* out, struct token_list* functio * constant * ( expression ) */ +int string_num; struct token_list* primary_expr(struct token_list* out, struct token_list* function) { if(('0' <= global_token->s[0]) & (global_token->s[0] <= '9')) { - out = double_emit("LOAD_IMMEDIATE_eax %", global_token->s, out, true); + out = double_emit("LOAD_IMMEDIATE_eax %", global_token->s, out, TRUE); 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'))) @@ -204,17 +210,16 @@ struct token_list* primary_expr(struct token_list* out, struct token_list* funct { global_token = global_token->next; out = expression(out, function); - require_char("Error in Primary expression\nDidn't get )\n", ')'); + require_match("Error in Primary expression\nDidn't get )\n", ")"); } - else if(global_token->s[0] == '\'') - { + else if(global_token->s[0] == 39) + { /* 39 == ' */ out = emit("LOAD_IMMEDIATE_eax %", out); out = emit(numerate_number(global_token->s[1]), out); global_token = global_token->next; } - else if(global_token->s[0] == '"') - { - static int string_num; + else if(global_token->s[0] == 34) + { /* 34 == " */ char* number_string = numerate_number(string_num); out = emit("LOAD_IMMEDIATE_eax &STRING_", out); out = emit(number_string, out); @@ -231,7 +236,9 @@ struct token_list* primary_expr(struct token_list* out, struct token_list* funct } else { - fprintf(stderr, "Recieved %s in primary_expr\n", global_token->s); + file_print("Recieved ", stderr); + file_print(global_token->s, stderr); + file_print(" in primary_expr\n", stderr); exit(EXIT_FAILURE); } @@ -258,13 +265,14 @@ struct token_list* process_expression_list(struct token_list* out, struct token_ out = emit("PUSH_eax\t#_process_expression2\n", out); function->temps = function->temps + 1; } - require_char("ERROR in process_expression_list\nNo ) was found\n", ')'); + require_match("ERROR in process_expression_list\nNo ) was found\n", ")"); } else global_token = global_token->next; - out = double_emit("CALL_IMMEDIATE %FUNCTION_", func, out, true); + out = double_emit("CALL_IMMEDIATE %FUNCTION_", func, out, TRUE); - for(int i = function->temps - temp; 0 != i; i = i - 1) + int i; + for(i = function->temps - temp; 0 != i; i = i - 1) { out = emit("POP_ebx\t# _process_expression_locals\n", out); } @@ -273,12 +281,17 @@ struct token_list* process_expression_list(struct token_list* out, struct token_ return out; } -struct token_list* common_recursion(struct token_list* (*function) (struct token_list*, struct token_list*), struct token_list* out, struct token_list* func) + +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); func->temps = func->temps + 1; - out = function(out, func); + return out; +} + +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); return out; @@ -316,14 +329,16 @@ struct token_list* postfix_expr(struct token_list* out, struct token_list* funct { if(global_token->s[0] == '[') { - struct token_list* target = current_target; - struct type* a = current_target->type; - out = common_recursion(expression, out, function); + struct type* target = current_target; + struct type* a = current_target; + out = pre_recursion(out, function); + out = expression(out, function); + out = post_recursion(out, function); /* Add support for Ints */ if( 1 != a->indirect->size) { - out = double_emit("SAL_eax_Immediate8 !", numerate_number(ceil_log2(a->indirect->size)), out, false); + out = double_emit("SAL_eax_Immediate8 !", numerate_number(ceil_log2(a->indirect->size)), out, FALSE); } out = emit("ADD_ebx_to_eax\n", out); @@ -340,7 +355,7 @@ struct token_list* postfix_expr(struct token_list* out, struct token_list* funct out = emit("LOAD_BYTE\n", out); } } - require_char("ERROR in postfix_expr\nMissing ]\n", ']'); + require_match("ERROR in postfix_expr\nMissing ]\n", "]"); } else if(global_token->s[0] == '(') { @@ -351,25 +366,30 @@ struct token_list* postfix_expr(struct token_list* out, struct token_list* funct out = emit("# looking up offset\n", out); global_token = global_token->next; struct type* i; - for(i = current_target->type->members; NULL != i; i = i->members) + for(i = current_target->members; NULL != i; i = i->members) { if(!strcmp(i->name, global_token->s)) break; } if(NULL == i) { - fprintf(stderr, "ERROR in postfix_expr %s->%s does not exist\n", current_target->type->name, global_token->s); + file_print("ERROR in postfix_expr ", stderr); + file_print(current_target->name, stderr); + file_print("->", stderr); + file_print(global_token->s, stderr); + file_print(" does not exist\n", stderr); exit(EXIT_FAILURE); } if(0 != i->offset) { out = emit("# -> offset calculation\n", out); - out = double_emit("LOAD_IMMEDIATE_ebx %", numerate_number(i->offset), out, false); + out = double_emit("LOAD_IMMEDIATE_ebx %", numerate_number(i->offset), out, FALSE); out = emit("ADD_ebx_to_eax\n", out); } if(strcmp(global_token->next->s, "=")) { out = emit("LOAD_INTEGER\n", out); } + current_target = i->type; global_token = global_token->next; } else return out; @@ -381,21 +401,36 @@ struct token_list* postfix_expr(struct token_list* out, struct token_list* funct * postfix-expr * - postfix-expr * !postfix-expr + * sizeof ( type ) */ +struct type* type_name(); struct token_list* unary_expr(struct token_list* out, struct token_list* function) { if(!strcmp("-", global_token->s)) { out = emit("LOAD_IMMEDIATE_eax %0\n", out); - out = common_recursion(postfix_expr, out, function); + 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); } else if(!strcmp("!", global_token->s)) { out = emit("LOAD_IMMEDIATE_eax %1\n", out); - out = common_recursion(postfix_expr, out, function); + out = pre_recursion(out, function); + out = postfix_expr(out, function); + out = post_recursion(out, function); out = emit("XOR_ebx_eax_into_eax\n", out); } + else if(!strcmp("sizeof", global_token->s)) + { + global_token = global_token->next; + require_match("ERROR in unary_expr\nMissing (\n", "("); + struct type* a = type_name(); + require_match("ERROR in unary_expr\nMissing )\n", ")"); + + out = double_emit("LOAD_IMMEDIATE_eax %", numerate_number(a->size), out, FALSE); + } else out = postfix_expr(out, function); return out; @@ -404,6 +439,9 @@ struct token_list* unary_expr(struct token_list* out, struct token_list* functio /* * additive-expr: * postfix-expr + * additive-expr * postfix-expr + * additive-expr / postfix-expr + * additive-expr % postfix-expr * additive-expr + postfix-expr * additive-expr - postfix-expr */ @@ -415,14 +453,39 @@ struct token_list* additive_expr(struct token_list* out, struct token_list* func { if(!strcmp("+", global_token->s)) { - out = common_recursion(postfix_expr, out, function); + out = pre_recursion(out, function); + out = unary_expr(out, function); + out = post_recursion(out, function); out = emit("ADD_ebx_to_eax\n", out); } else if(!strcmp("-", global_token->s)) { - out = common_recursion(postfix_expr, out, function); + 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); } + else if(!strcmp("*", 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); + } + else if(!strcmp("/", 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); + } + else if(!strcmp("%", 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); + } else return out; } } @@ -441,7 +504,9 @@ struct token_list* shift_expr(struct token_list* out, struct token_list* functio { if(!strcmp(global_token->s, "<<")) { - out = common_recursion(additive_expr, out, function); + out = pre_recursion(out, function); + out = additive_expr(out, function); + out = post_recursion(out, function); // Ugly hack to Work around flaw in x86 struct token_list* old = out->next; free(out); @@ -449,7 +514,9 @@ struct token_list* shift_expr(struct token_list* out, struct token_list* functio } else if(!strcmp(global_token->s, ">>")) { - out = common_recursion(additive_expr, out, function); + out = pre_recursion(out, function); + out = additive_expr(out, function); + out = post_recursion(out, function); // Ugly hack to Work around flaw in x86 struct token_list* old = out->next; free(out); @@ -478,22 +545,30 @@ struct token_list* relational_expr(struct token_list* out, struct token_list* fu { if(!strcmp(global_token->s, "<")) { - out = common_recursion(shift_expr, out, function); + out = pre_recursion(out, function); + out = shift_expr(out, function); + out = post_recursion(out, function); out = emit("CMP\nSETL\nMOVEZBL\n", out); } else if(!strcmp(global_token->s, "<=")) { - out = common_recursion(shift_expr, out, function); + out = pre_recursion(out, function); + out = shift_expr(out, function); + out = post_recursion(out, function); out = emit("CMP\nSETLE\nMOVEZBL\n", out); } else if(!strcmp(global_token->s, ">=")) { - out = common_recursion(shift_expr, out, function); + out = pre_recursion(out, function); + out = shift_expr(out, function); + out = post_recursion(out, function); out = emit("CMP\nSETGE\nMOVEZBL\n", out); } else if(!strcmp(global_token->s, ">")) { - out = common_recursion(shift_expr, out, function); + out = pre_recursion(out, function); + out = shift_expr(out, function); + out = post_recursion(out, function); out = emit("CMP\nSETG\nMOVEZBL\n", out); } else return out; @@ -514,12 +589,16 @@ struct token_list* equality_expr(struct token_list* out, struct token_list* func { if(!strcmp(global_token->s, "==")) { - out = common_recursion(relational_expr, out, function); + out = pre_recursion(out, function); + out = relational_expr(out, function); + out = post_recursion(out, function); out = emit("CMP\nSETE\nMOVEZBL\n", out); } else if(!strcmp(global_token->s, "!=")) { - out = common_recursion(relational_expr, out, function); + out = pre_recursion(out, function); + out = relational_expr(out, function); + out = post_recursion(out, function); out = emit("CMP\nSETNE\nMOVEZBL\n", out); } else return out; @@ -537,7 +616,9 @@ struct token_list* bitwise_and_expr(struct token_list* out, struct token_list* f while(global_token->s[0] == '&') { - out = common_recursion(equality_expr, out, function); + out = pre_recursion(out, function); + out = equality_expr(out, function); + out = post_recursion(out, function); out = emit("AND_eax_ebx\n", out); } return out; @@ -554,7 +635,9 @@ struct token_list* bitwise_or_expr(struct token_list* out, struct token_list* fu while(global_token->s[0] == '|') { - out = common_recursion(bitwise_and_expr, out, function); + out = pre_recursion(out, function); + out = bitwise_and_expr(out, function); + out = post_recursion(out, function); out = emit("OR_eax_ebx\n", out); } return out; @@ -571,14 +654,16 @@ struct token_list* expression(struct token_list* out, struct token_list* functio if(global_token->s[0] == '=') { - struct token_list* target = current_target; - bool member = !strcmp(global_token->prev->s, "]"); - out = common_recursion(expression, out, function); + struct type* target = current_target; + int member = !strcmp(global_token->prev->s, "]"); + out = pre_recursion(out, function); + out = expression(out, function); + out = post_recursion(out, function); if(member) { - if(1 == target->type->indirect->size) out = emit("STORE_CHAR\n", out); - else if(4 == target->type->indirect->size) + if(1 == target->indirect->size) out = emit("STORE_CHAR\n", out); + else if(4 == target->indirect->size) { out = emit("STORE_INTEGER\n", out); } @@ -593,7 +678,8 @@ struct token_list* expression(struct token_list* out, struct token_list* functio struct type* lookup_type(char* s) { - for(struct type* i = global_types; NULL != i; i = i->next) + struct type* i; + for(i = global_types; NULL != i; i = i->next) { if(!strcmp(i->name, s)) { @@ -617,7 +703,7 @@ void create_struct() global_types = head; global_token = global_token->next; i->size = 4; - require_char("ERROR in create_struct\nMissing {\n", '{'); + require_match("ERROR in create_struct\nMissing {\n", "{"); struct type* last = NULL; while('}' != global_token->s[0]) { @@ -626,15 +712,16 @@ void create_struct() i->name = global_token->s; i->members = last; i->size = member_type->size; + i->type = member_type; i->offset = offset; offset = offset + member_type->size; global_token = global_token->next; - require_char("ERROR in create_struct\nMissing ;\n", ';'); + require_match("ERROR in create_struct\nMissing ;\n", ";"); last = i; } global_token = global_token->next; - require_char("ERROR in create_struct\nMissing ;\n", ';'); + require_match("ERROR in create_struct\nMissing ;\n", ";"); head->size = offset; head->members = last; @@ -646,14 +733,17 @@ void create_struct() * type-name: * char * * int + * struct + * FILE + * void */ struct type* type_name() { - int structure = false; + int structure = FALSE; if(!strcmp(global_token->s, "struct")) { - structure = true; + structure = TRUE; global_token = global_token->next; } @@ -661,7 +751,9 @@ struct type* type_name() if(NULL == ret && !structure) { - fprintf(stderr, "Unknown type %s\n", global_token->s); + file_print("Unknown type ", stderr); + file_print(global_token->s, stderr); + file_print("\n", stderr); exit(EXIT_FAILURE); } else if(NULL == ret) @@ -685,7 +777,7 @@ struct type* type_name() struct token_list* collect_local(struct token_list* out, struct token_list* function) { struct type* type_size = type_name(); - out = double_emit("# Defining local ", global_token->s, out, true); + out = double_emit("# Defining local ", global_token->s, out, TRUE); struct token_list* a = sym_declare(global_token->s, type_size, function->locals); function->locals = a; @@ -699,9 +791,9 @@ struct token_list* collect_local(struct token_list* out, struct token_list* func } function->temps = function->temps + 1; - require_char("ERROR in collect_local\nMissing ;\n", ';'); + require_match("ERROR in collect_local\nMissing ;\n", ";"); - out = double_emit("PUSH_eax\t#", a->s, out, true); + out = double_emit("PUSH_eax\t#", a->s, out, TRUE); return out; } @@ -714,26 +806,26 @@ struct token_list* process_if(struct token_list* out, struct token_list* functio char* number_string = numerate_number(if_count); if_count = if_count + 1; - out = double_emit("# IF_",number_string, out, false); + out = double_emit("# IF_",number_string, out, FALSE); global_token = global_token->next; - require_char("ERROR in process_if\nMISSING (\n", '('); + require_match("ERROR in process_if\nMISSING (\n", "("); out = expression(out, function); - out = double_emit("TEST\nJUMP_EQ %ELSE_", number_string, out, false); + out = double_emit("TEST\nJUMP_EQ %ELSE_", number_string, out, FALSE); - require_char("ERROR in process_if\nMISSING )\n", ')'); + require_match("ERROR in process_if\nMISSING )\n", ")"); out = statement(out, function); - out = double_emit("JUMP %_END_IF_", number_string, out, false); - out = double_emit(":ELSE_", number_string, out, false); + out = double_emit("JUMP %_END_IF_", number_string, out, FALSE); + out = double_emit(":ELSE_", number_string, out, FALSE); if(!strcmp(global_token->s, "else")) { global_token = global_token->next; out = statement(out, function); } - out = double_emit(":_END_IF_", number_string, out, false); + out = double_emit(":_END_IF_", number_string, out, FALSE); return out; } @@ -743,33 +835,33 @@ struct token_list* process_for(struct token_list* out, struct token_list* functi char* number_string = numerate_number(for_count); for_count = for_count + 1; - out = double_emit("# FOR_initialization_", number_string, out, false); + out = double_emit("# FOR_initialization_", number_string, out, FALSE); global_token = global_token->next; - require_char("ERROR in process_for\nMISSING (\n", '('); + require_match("ERROR in process_for\nMISSING (\n", "("); out = expression(out, function); - out = double_emit(":FOR_", number_string, out , false); + out = double_emit(":FOR_", number_string, out , FALSE); - require_char("ERROR in process_for\nMISSING ;1\n", ';'); + require_match("ERROR in process_for\nMISSING ;1\n", ";"); out = expression(out, function); - out = double_emit("TEST\nJUMP_EQ %FOR_END_", number_string, out, false); - out = double_emit("JUMP %FOR_THEN_", number_string, out, false); - out = double_emit(":FOR_ITER_", number_string, out, false); + out = double_emit("TEST\nJUMP_EQ %FOR_END_", number_string, out, FALSE); + out = double_emit("JUMP %FOR_THEN_", number_string, out, FALSE); + out = double_emit(":FOR_ITER_", number_string, out, FALSE); - require_char("ERROR in process_for\nMISSING ;2\n", ';'); + require_match("ERROR in process_for\nMISSING ;2\n", ";"); out = expression(out, function); - out = double_emit("JUMP %FOR_", number_string, out, false); - out = double_emit(":FOR_THEN_", number_string, out, false); + out = double_emit("JUMP %FOR_", number_string, out, FALSE); + out = double_emit(":FOR_THEN_", number_string, out, FALSE); - require_char("ERROR in process_for\nMISSING )\n", ')'); + require_match("ERROR in process_for\nMISSING )\n", ")"); out = statement(out, function); - out = double_emit("JUMP %FOR_ITER_", number_string, out, false); - out = double_emit(":FOR_END_", number_string, out, false); + out = double_emit("JUMP %FOR_ITER_", number_string, out, FALSE); + out = double_emit(":FOR_END_", number_string, out, FALSE); return out; } @@ -777,18 +869,41 @@ 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_char("ERROR in process_asm\nMISSING (\n", '('); - while('"' == global_token->s[0]) - { + require_match("ERROR in process_asm\nMISSING (\n", "("); + while(34 == global_token->s[0]) + {/* 34 == " */ out = emit((global_token->s + 1), out); out = emit("\n", out); global_token = global_token->next; } - require_char("ERROR in process_asm\nMISSING )\n", ')'); - require_char("ERROR in process_asm\nMISSING ;\n", ';'); + require_match("ERROR in process_asm\nMISSING )\n", ")"); + require_match("ERROR in process_asm\nMISSING ;\n", ";"); return out; } +/* Process do while loops */ +int do_count; +struct token_list* process_do(struct token_list* out, struct token_list* function) +{ + char* number_string = numerate_number(do_count); + do_count = do_count + 1; + + out = double_emit(":DO_", number_string, out, FALSE); + + 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", "("); + out = expression(out, function); + require_match("ERROR in process_do\nMISSING )\n", ")"); + require_match("ERROR in process_do\nMISSING ;\n", ";"); + + out = double_emit("TEST\nJUMP_NE %DO_", number_string, out, FALSE); + return out; +} + + /* Process while loops */ int while_count; struct token_list* process_while(struct token_list* out, struct token_list* function) @@ -796,20 +911,20 @@ struct token_list* process_while(struct token_list* out, struct token_list* func char* number_string = numerate_number(while_count); while_count = while_count + 1; - out = double_emit(":WHILE_", number_string, out, false); + out = double_emit(":WHILE_", number_string, out, FALSE); global_token = global_token->next; - require_char("ERROR in process_while\nMISSING (\n", '('); + require_match("ERROR in process_while\nMISSING (\n", "("); out = expression(out, function); - out = double_emit("TEST\nJUMP_EQ %END_WHILE_", number_string, out, false); - out = double_emit("# THEN_while_", number_string, out, false); + out = double_emit("TEST\nJUMP_EQ %END_WHILE_", number_string, out, FALSE); + out = double_emit("# THEN_while_", number_string, out, FALSE); - require_char("ERROR in process_while\nMISSING )\n", ')'); + require_match("ERROR in process_while\nMISSING )\n", ")"); out = statement(out, function); - out = double_emit("JUMP %WHILE_", number_string, out, false); - out = double_emit(":END_WHILE_", number_string, out, false); + out = double_emit("JUMP %WHILE_", number_string, out, FALSE); + out = double_emit(":END_WHILE_", number_string, out, FALSE); return out; } @@ -819,12 +934,12 @@ 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_char("ERROR in return_result\nMISSING ;\n", ';'); + require_match("ERROR in return_result\nMISSING ;\n", ";"); - for(struct token_list* i = function->locals; NULL != i; i = i->next) + struct token_list* i; + for(i = function->locals; NULL != i; i = i->next) { out = emit("POP_ebx\t# _return_result_locals\n", out); - function->locals = function->locals->next; } out = emit("RETURN\n", out); return out; @@ -844,7 +959,8 @@ struct token_list* recursive_statement(struct token_list* out, struct token_list /* Clean up any locals added */ if(NULL != function->locals) { - for(struct token_list* i = function->locals; frame != i; i = i->next) + struct token_list* i; + for(i = function->locals; frame != i; i = i->next) { out = emit( "POP_ebx\t# _recursive_statement_locals\n", out); function->locals = function->locals->next; @@ -860,9 +976,12 @@ struct token_list* recursive_statement(struct token_list* out, struct token_list * type-name identifier = expression; * if ( expression ) statement * if ( expression ) statement else statement + * do statement while ( expression ) ; * while ( expression ) statement * for ( expression ; expression ; expression ) statement * asm ( "assembly" ... "assembly" ) ; + * goto label ; + * label: * return ; * expr ; */ @@ -872,6 +991,12 @@ struct token_list* statement(struct token_list* out, struct token_list* function { out = recursive_statement(out, function); } + else if(':' == global_token->s[0]) + { + out = emit(global_token->s, out); + out = emit("\t#C goto label\n", out); + global_token = global_token->next; + } else if((NULL != lookup_type(global_token->s)) || !strcmp("struct", global_token->s)) { out = collect_local(out, function); @@ -880,6 +1005,10 @@ struct token_list* statement(struct token_list* out, struct token_list* function { out = process_if(out, function); } + else if(!strcmp(global_token->s, "do")) + { + out = process_do(out, function); + } else if(!strcmp(global_token->s, "while")) { out = process_while(out, function); @@ -892,6 +1021,13 @@ struct token_list* statement(struct token_list* out, struct token_list* function { out = process_asm(out); } + else if(!strcmp("goto", global_token->s)) + { + global_token = global_token->next; + out = double_emit("JUMP %", global_token->s, out, TRUE); + global_token = global_token->next; + require_match("ERROR in statement\nMissing ;\n", ";"); + } else if(!strcmp(global_token->s, "return")) { out = return_result(out, function); @@ -899,7 +1035,7 @@ struct token_list* statement(struct token_list* out, struct token_list* function else { out = expression(out, function); - require_char("ERROR in statement\nMISSING ;\n", ';'); + require_match("ERROR in statement\nMISSING ;\n", ";"); } return out; } @@ -947,8 +1083,8 @@ struct token_list* declare_function(struct token_list* out, struct type* type) if(global_token->s[0] == ';') global_token = global_token->next; else { - out = double_emit("# Defining function ", essential, out, true); - out = double_emit(":FUNCTION_", essential, out, true); + out = double_emit("# Defining function ", essential, out, TRUE); + out = double_emit(":FUNCTION_", essential, out, TRUE); out = statement(out, func); /* Prevent duplicate RETURNS */ @@ -1003,7 +1139,7 @@ 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 = double_emit(":GLOBAL_", global_token->prev->s, globals_list, true); + globals_list = double_emit(":GLOBAL_", global_token->prev->s, globals_list, TRUE); globals_list = emit("NOP\n", globals_list); global_token = global_token->next; @@ -1011,7 +1147,9 @@ new_type: else if(global_token->s[0] == '(') out = declare_function(out, type_size); else { - fprintf(stderr, "Recieved %s in program\n", global_token->s); + file_print("Recieved ", stderr); + file_print(global_token->s, stderr); + file_print(" in program\n", stderr); exit(EXIT_FAILURE); } } @@ -1019,45 +1157,18 @@ new_type: return out; } -void recursive_output(FILE* out, struct token_list* i) +void recursive_output(struct token_list* i, FILE* out) { if(NULL == i) return; - recursive_output(out, i->next); - fprintf(out, "%s", i->s); + recursive_output(i->next, out); + file_print(i->s, out); } -/* Initialize default types */ -void initialize_types() +void file_print(char* s, FILE* f) { - /* Define void */ - global_types = calloc(1, sizeof(struct type)); - global_types->name = "void"; - global_types->size = 4; - /* void* has the same properties as void */ - global_types->indirect = global_types; - - /* Define int */ - struct type* a = calloc(1, sizeof(struct type)); - a->name = "int"; - a->size = 4; - /* int* has the same properties as int */ - a->indirect = a; - - /* Define char* */ - struct type* b = calloc(1, sizeof(struct type)); - b->name = "char*"; - b->size = 4; - - /* Define char */ - struct type* c = calloc(1, sizeof(struct type)); - c->name = "char"; - c->size = 1; - - /* char** is char */ - c->indirect = b; - b->indirect = c; - - /* Finalize type list */ - a->next = c; - global_types->next = a; + while(0 != s[0]) + { + fputc(s[0], f); + s = s + 1; + } } diff --git a/cc_reader.c b/cc_reader.c index 00d2fdd..5115612 100644 --- a/cc_reader.c +++ b/cc_reader.c @@ -40,12 +40,32 @@ char consume_word(struct token_list* current, char c, char frequent) return fgetc(input); } + +void fixup_label(struct token_list* current) +{ + int hold = ':'; + int prev; + int i = 0; + do + { + prev = hold; + hold = current->s[i]; + current->s[i] = prev; + i = i + 1; + } while(0 != hold); +} + char preserve_keyword(struct token_list* current, char c) { while((('a' <= c) & (c <= 'z')) | (('A' <= c) & (c <= 'Z')) | (('0' <= c) & (c <= '9')) | (c == '_')) { c = consume_byte(current, c); } + if(':' == c) + { + fixup_label(current); + return 32; + } return c; } @@ -86,9 +106,9 @@ reset: { c = preserve_symbol(current, c); } - else if(c == '\'') - { - c = consume_word(current, c, '\''); + else if(c == 39) + { /* 39 == ' */ + c = consume_word(current, c, 39); } else if(c == '"') { @@ -114,7 +134,7 @@ reset: goto reset; } } - else if(c == EOF) + else if(c < 0) { free(current); return c; @@ -148,7 +168,7 @@ struct token_list* read_all_tokens(FILE* a, struct token_list* current) input = a; token = current; int ch =fgetc(input); - while(EOF != ch) ch = get_token(ch); + while(0 <= ch) ch = get_token(ch); return token; } diff --git a/cc_strings.c b/cc_strings.c index 7d4b50d..8d98684 100644 --- a/cc_strings.c +++ b/cc_strings.c @@ -19,7 +19,6 @@ #include struct token_list* emit(char *s, struct token_list* head); -int asprintf(char **strp, const char *fmt, ...); char upcase(char a) { @@ -31,7 +30,7 @@ char upcase(char a) return a; } -int8_t hex(int c, bool high) +int hex(int c, int high) { if (c >= '0' && c <= '9') { @@ -52,38 +51,35 @@ int8_t hex(int c, bool high) if(high) { - c = c * 16; + c = c << 4; } return c; } -bool weird(char* string) +int weird(char* string) { - if(0 == string[0]) return false; + if(0 == string[0]) return FALSE; if('\\' == string[0]) { if('x' == string[1]) { - switch(string[2]) - { - case '0': return true; - case '1': return true; - case '8': return true; - case '9': return true; - case 'a': return true; - case 'A': return true; - case 'b': return true; - case 'B': return true; - case 'c': return true; - case 'C': return true; - case 'd': return true; - case 'D': return true; - case 'e': return true; - case 'E': return true; - case 'f': return true; - case 'F': return true; - default: return weird(string+3); - } + if('0' == string[2]) return TRUE; + else if('1' == string[2]) return TRUE; + else if('8' == string[2]) return TRUE; + else if('9' == string[2]) return TRUE; + else if('a' == string[2]) return TRUE; + else if('A' == string[2]) return TRUE; + else if('b' == string[2]) return TRUE; + else if('B' == string[2]) return TRUE; + else if('c' == string[2]) return TRUE; + else if('C' == string[2]) return TRUE; + else if('d' == string[2]) return TRUE; + else if('D' == string[2]) return TRUE; + else if('e' == string[2]) return TRUE; + else if('E' == string[2]) return TRUE; + else if('f' == string[2]) return TRUE; + else if('F' == string[2]) return TRUE; + else return weird(string+3); } else { @@ -99,13 +95,15 @@ char* collect_regular_string(char* string) int j = 0; int i = 0; char* message = calloc(MAX_STRING, sizeof(char)); - message[0] = '"'; + + /* 34 == " */ + message[0] = 34; while(string[j] != 0) { if((string[j] == '\\') & (string[j + 1] == 'x')) { - int t1 = hex(string[j + 2], true); - int t2 = hex(string[j + 3], false); + int t1 = hex(string[j + 2], TRUE); + int t2 = hex(string[j + 3], FALSE); message[i] = t1 + t2; j = j + 4; } @@ -118,20 +116,21 @@ char* collect_regular_string(char* string) i = i + 1; } - message[i] = '"'; + message[i] = 34; message[i + 1] = '\n'; return message; } /* Deal with non-human strings */ -char table[16] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46}; char* collect_weird_string(char* string) { int j = 1; int k = 1; + char* table = "0123456789ABCDEF"; char* hold = calloc(MAX_STRING, sizeof(char)); - hold[0] = '\''; + /* 39 == ' */ + hold[0] = 39; while(string[j] != 0) { hold[k] = ' '; @@ -155,7 +154,7 @@ char* collect_weird_string(char* string) hold[k] = ' '; hold[k + 1] = '0'; hold[k + 2] = '0'; - hold[k + 3] = '\''; + hold[k + 3] = 39; hold[k + 4] = '\n'; return hold; } diff --git a/cc_types.c b/cc_types.c new file mode 100644 index 0000000..5883a0d --- /dev/null +++ b/cc_types.c @@ -0,0 +1,68 @@ +/* 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" +#include + +/* Initialize default types */ +void initialize_types() +{ + /* Define void */ + global_types = calloc(1, sizeof(struct type)); + global_types->name = "void"; + global_types->size = 4; + global_types->type = global_types; + /* void* has the same properties as void */ + global_types->indirect = global_types; + + /* Define int */ + struct type* a = calloc(1, sizeof(struct type)); + a->name = "int"; + a->size = 4; + /* int* has the same properties as int */ + a->indirect = a; + a->type = a; + + /* Define char* */ + struct type* b = calloc(1, sizeof(struct type)); + b->name = "char*"; + b->size = 4; + b->type = b; + + /* Define char */ + struct type* c = calloc(1, sizeof(struct type)); + c->name = "char"; + c->size = 1; + c->type = c; + + /* char** is char */ + c->indirect = b; + b->indirect = c; + + /* Define FILE */ + struct type* d = calloc(1, sizeof(struct type)); + d->name = "FILE"; + d->size = 4; + d->type = d; + /* int* has the same properties as int */ + d->indirect = d; + + /* Finalize type list */ + c->next = d; + a->next = c; + global_types->next = a; +} diff --git a/libc.c b/libc.c new file mode 100644 index 0000000..0a41ee8 --- /dev/null +++ b/libc.c @@ -0,0 +1,21 @@ +/* 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 . + */ +int fgetc(FILE*); +int* calloc(int, int); +void free(void*); +void exit(int); +int strcmp(char* a, char* b); diff --git a/makefile b/makefile index 9f3b913..8992f74 100644 --- a/makefile +++ b/makefile @@ -6,21 +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.h | bin - $(CC) $(CFLAGS) cc_reader.c cc_strings.c cc_core.c cc.c cc.h -o bin/M2-Planet +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-minimal: cc_reader.c cc_strings.c cc_core.c cc-minimal.c cc.h | bin - $(CC) $(CFLAGS) cc_reader.c cc_strings.c cc_core.c cc-minimal.c cc.h -o bin/M2-Planet-minimal +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 # Clean up after ourselves .PHONY: clean clean: rm -rf bin/ test/results/ - ./test/test0/cleanup.sh - ./test/test1/cleanup.sh - ./test/test2/cleanup.sh - ./test/test3/cleanup.sh - ./test/test4/cleanup.sh + ./test/test00/cleanup.sh + ./test/test01/cleanup.sh + ./test/test02/cleanup.sh + ./test/test03/cleanup.sh + ./test/test04/cleanup.sh + ./test/test05/cleanup.sh + ./test/test06/cleanup.sh + ./test/test07/cleanup.sh + ./test/test08/cleanup.sh + ./test/test09/cleanup.sh + ./test/test10/cleanup.sh ./test/test99/cleanup.sh # Directories @@ -31,23 +37,41 @@ results: mkdir -p test/results # tests -test: test0-binary test1-binary test2-binary test3-binary test4-binary test99-binary | results +test: test00-binary test01-binary test02-binary test03-binary test04-binary test05-binary test06-binary test07-binary test08-binary test09-binary test10-binary test99-binary | results sha256sum -c test/test.answers -test0-binary: M2-Planet | results - test/test0/hello.sh +test00-binary: M2-Planet | results + test/test00/hello.sh -test1-binary: M2-Planet | results - test/test1/hello.sh +test01-binary: M2-Planet | results + test/test01/hello.sh -test2-binary: M2-Planet | results - test/test2/hello.sh +test02-binary: M2-Planet | results + test/test02/hello.sh -test3-binary: M2-Planet | results - test/test3/hello.sh +test03-binary: M2-Planet | results + test/test03/hello.sh -test4-binary: M2-Planet | results - test/test4/hello.sh +test04-binary: M2-Planet | results + test/test04/hello.sh + +test05-binary: M2-Planet | results + test/test05/hello.sh + +test06-binary: M2-Planet | results + test/test06/hello.sh + +test07-binary: M2-Planet | results + test/test07/hello.sh + +test08-binary: M2-Planet | results + test/test08/hello.sh + +test09-binary: M2-Planet | results + test/test09/hello.sh + +test10-binary: M2-Planet | results + test/test10/hello.sh test99-binary: M2-Planet | results test/test99/hello.sh diff --git a/test/common_x86/x86_defs.M1 b/test/common_x86/x86_defs.M1 index 895eec7..3b53c15 100644 --- a/test/common_x86/x86_defs.M1 +++ b/test/common_x86/x86_defs.M1 @@ -28,6 +28,7 @@ DEFINE COPY_esp_to_ecx 89E1 DEFINE INT_80 CD80 DEFINE JUMP E9 DEFINE JUMP_EQ 0F84 +DEFINE JUMP_NE 0F85 DEFINE JUMP_EQ8 74 DEFINE JUMP_NE8 75 DEFINE LOAD_BYTE 0FBE00 diff --git a/test/test.answers b/test/test.answers index d839db1..0566b3b 100644 --- a/test/test.answers +++ b/test/test.answers @@ -1,6 +1,12 @@ -646164d0e3de386d0c534cc5abd415e331c4bfa289e5755688b0ac15b082b8e3 test/results/test0-binary -117b1837f95ca77de4a30b2b0428472ce60433ea82b0ca6d2e5f57316ef20c9a test/results/test1-binary -3de3e1eabc6b808fbe172c7bb5a4e677a272fcbec7f73f2f896090051280d95a test/results/test2-binary -97c9a95f88b63cf318b8caae963abc899004dc17c9695d7f5a2b0f7d4cf7dcb8 test/results/test3-binary -e20f8dbbfaf58b3706e7b445dcb63ee8ff071d0efb6bfc00c89ed9365d5555eb test/results/test4-binary -be3e57116e09c63e7819a391c550d2bdde2eb9f3409d9a54fcd09d2062b75dcf test/results/test99-binary +646164d0e3de386d0c534cc5abd415e331c4bfa289e5755688b0ac15b082b8e3 test/results/test00-binary +117b1837f95ca77de4a30b2b0428472ce60433ea82b0ca6d2e5f57316ef20c9a test/results/test01-binary +3de3e1eabc6b808fbe172c7bb5a4e677a272fcbec7f73f2f896090051280d95a test/results/test02-binary +97c9a95f88b63cf318b8caae963abc899004dc17c9695d7f5a2b0f7d4cf7dcb8 test/results/test03-binary +e20f8dbbfaf58b3706e7b445dcb63ee8ff071d0efb6bfc00c89ed9365d5555eb test/results/test04-binary +d427f256cbe716cd5b15d45072d4153e55e3529dd6a3b1dc6d429e540861c812 test/results/test05-binary +500dad424f01059c03a0fffada3ebc5bdb2b3b2a17813f89fed771b68690df71 test/results/test06-binary +67ba7b001b45aa551be1ddff605b856fc8b2d9159d1d95bda7592c71ab68f4f3 test/results/test07-binary +0d7709779c4d6acecb8fe3d2f384b2a03b4dd9a272924672c2111c4dafcaee45 test/results/test08-binary +2832ac2466f13aa63f2ccafd1a132b82dbb8d421c9c81ffaa5adaee13cd1b00b test/results/test09-binary +ccded240b943e39dc32454cd61c07f7b1978da0f203a4a93ebb93625dcaa96af test/results/test10-binary +746ce0eeeec1b7b8fa6836c4d3cb916b25db62bbf525251cc4ca594dd7a66969 test/results/test99-binary diff --git a/test/test0/cleanup.sh b/test/test0/cleanup.sh deleted file mode 100755 index b60e8d8..0000000 --- a/test/test0/cleanup.sh +++ /dev/null @@ -1,4 +0,0 @@ -#! /bin/sh -rm -f test/test0/return.M1 -rm -f test/test0/return.hex2 -exit 0 diff --git a/test/test0/hello.sh b/test/test0/hello.sh deleted file mode 100755 index 44ba6e6..0000000 --- a/test/test0/hello.sh +++ /dev/null @@ -1,17 +0,0 @@ -#! /bin/sh -set -x -# Build the test -bin/M2-Planet -f test/test0/return.c -o test/test0/return.M1 || exit 1 -# Macro assemble with libc written in M1-Macro -M1 -f test/common_x86/x86_defs.M1 -f test/common_x86/libc.M1 -f test/test0/return.M1 --LittleEndian --Architecture 1 -o test/test0/return.hex2 || exit 2 -# Resolve all linkages -hex2 -f test/common_x86/ELF-i386.hex2 -f test/test0/return.hex2 --LittleEndian --Architecture 1 --BaseAddress 0x8048000 -o test/results/test0-binary --exec_enable || exit 3 - -# Ensure binary works if host machine supports test -if [ "$(get_machine)" = "x86_64" ] -then - # Verify that the compiled program returns the correct result - ./test/results/test0-binary - [ 42 = $? ] || exit 3 -fi -exit 0 diff --git a/test/test0/.gitignore b/test/test00/.gitignore similarity index 100% rename from test/test0/.gitignore rename to test/test00/.gitignore diff --git a/test/test00/cleanup.sh b/test/test00/cleanup.sh new file mode 100755 index 0000000..ecd42d4 --- /dev/null +++ b/test/test00/cleanup.sh @@ -0,0 +1,4 @@ +#! /bin/sh +rm -f test/test00/return.M1 +rm -f test/test00/return.hex2 +exit 0 diff --git a/test/test00/hello.sh b/test/test00/hello.sh new file mode 100755 index 0000000..8f80ffe --- /dev/null +++ b/test/test00/hello.sh @@ -0,0 +1,17 @@ +#! /bin/sh +set -x +# Build the test +bin/M2-Planet -f test/test00/return.c -o test/test00/return.M1 || exit 1 +# Macro assemble with libc written in M1-Macro +M1 -f test/common_x86/x86_defs.M1 -f test/common_x86/libc.M1 -f test/test00/return.M1 --LittleEndian --Architecture 1 -o test/test00/return.hex2 || exit 2 +# Resolve all linkages +hex2 -f test/common_x86/ELF-i386.hex2 -f test/test00/return.hex2 --LittleEndian --Architecture 1 --BaseAddress 0x8048000 -o test/results/test00-binary --exec_enable || exit 3 + +# Ensure binary works if host machine supports test +if [ "$(get_machine)" = "x86_64" ] +then + # Verify that the compiled program returns the correct result + ./test/results/test00-binary + [ 42 = $? ] || exit 3 +fi +exit 0 diff --git a/test/test0/return.c b/test/test00/return.c similarity index 100% rename from test/test0/return.c rename to test/test00/return.c diff --git a/test/test1/.gitignore b/test/test01/.gitignore similarity index 100% rename from test/test1/.gitignore rename to test/test01/.gitignore diff --git a/test/test01/cleanup.sh b/test/test01/cleanup.sh new file mode 100755 index 0000000..75e151a --- /dev/null +++ b/test/test01/cleanup.sh @@ -0,0 +1,4 @@ +#! /bin/sh +rm -f test/test01/library_call.M1 +rm -f test/test01/library_call.hex2 +exit 0 diff --git a/test/test01/hello.sh b/test/test01/hello.sh new file mode 100755 index 0000000..d33cb10 --- /dev/null +++ b/test/test01/hello.sh @@ -0,0 +1,18 @@ +#! /bin/sh +set -x +# Build the test +bin/M2-Planet -f test/test01/library_call.c -o test/test01/library_call.M1 || exit 1 +# Macro assemble with libc written in M1-Macro +M1 -f test/common_x86/x86_defs.M1 -f test/common_x86/libc.M1 -f test/test01/library_call.M1 --LittleEndian --Architecture 1 -o test/test01/library_call.hex2 || exit 2 +# Resolve all linkages +hex2 -f test/common_x86/ELF-i386.hex2 -f test/test01/library_call.hex2 --LittleEndian --Architecture 1 --BaseAddress 0x8048000 -o test/results/test01-binary --exec_enable || exit 3 + +# Ensure binary works if host machine supports test +if [ "$(get_machine)" = "x86_64" ] +then + # Verify that the compiled program returns the correct result + out=$(./test/results/test01-binary 2>&1) + [ 42 = $? ] || exit 3 + [ "$out" = "Hello mes" ] || exit 4 +fi +exit 0 diff --git a/test/test1/library_call.c b/test/test01/library_call.c similarity index 100% rename from test/test1/library_call.c rename to test/test01/library_call.c diff --git a/test/test2/.gitignore b/test/test02/.gitignore similarity index 100% rename from test/test2/.gitignore rename to test/test02/.gitignore diff --git a/test/test02/cleanup.sh b/test/test02/cleanup.sh new file mode 100755 index 0000000..8881f4f --- /dev/null +++ b/test/test02/cleanup.sh @@ -0,0 +1,4 @@ +#! /bin/sh +rm -f test/test02/if.M1 +rm -f test/test02/if.hex2 +exit 0 diff --git a/test/test2/hello.sh b/test/test02/hello.sh similarity index 52% rename from test/test2/hello.sh rename to test/test02/hello.sh index 7f33d43..2bdcc28 100755 --- a/test/test2/hello.sh +++ b/test/test02/hello.sh @@ -1,17 +1,17 @@ #! /bin/sh set -x # Build the test -bin/M2-Planet -f test/test2/if.c -o test/test2/if.M1 || exit 1 +bin/M2-Planet -f test/test02/if.c -o test/test02/if.M1 || exit 1 # Macro assemble with libc written in M1-Macro -M1 -f test/common_x86/x86_defs.M1 -f test/common_x86/libc.M1 -f test/test2/if.M1 --LittleEndian --Architecture 1 -o test/test2/if.hex2 || exit 2 +M1 -f test/common_x86/x86_defs.M1 -f test/common_x86/libc.M1 -f test/test02/if.M1 --LittleEndian --Architecture 1 -o test/test02/if.hex2 || exit 2 # Resolve all linkages -hex2 -f test/common_x86/ELF-i386.hex2 -f test/test2/if.hex2 --LittleEndian --Architecture 1 --BaseAddress 0x8048000 -o test/results/test2-binary --exec_enable || exit 3 +hex2 -f test/common_x86/ELF-i386.hex2 -f test/test02/if.hex2 --LittleEndian --Architecture 1 --BaseAddress 0x8048000 -o test/results/test02-binary --exec_enable || exit 3 # Ensure binary works if host machine supports test if [ "$(get_machine)" = "x86_64" ] then # Verify that the compiled program returns the correct result - out=$(./test/results/test2-binary 2>&1 ) + out=$(./test/results/test02-binary 2>&1 ) [ 42 = $? ] || exit 4 [ "$out" = "Hello mes" ] || exit 5 fi diff --git a/test/test2/if.c b/test/test02/if.c similarity index 100% rename from test/test2/if.c rename to test/test02/if.c diff --git a/test/test3/.gitignore b/test/test03/.gitignore similarity index 100% rename from test/test3/.gitignore rename to test/test03/.gitignore diff --git a/test/test03/cleanup.sh b/test/test03/cleanup.sh new file mode 100755 index 0000000..09ce8ab --- /dev/null +++ b/test/test03/cleanup.sh @@ -0,0 +1,4 @@ +#! /bin/sh +rm -f test/test03/constant.M1 +rm -f test/test03/constant.hex2 +exit 0 diff --git a/test/test3/constant.c b/test/test03/constant.c similarity index 96% rename from test/test3/constant.c rename to test/test03/constant.c index 04cd649..ff900dc 100644 --- a/test/test3/constant.c +++ b/test/test03/constant.c @@ -15,7 +15,7 @@ * along with stage0. If not, see . */ -/* Validate that IF statements behave correctly */ +/* Validate that constant statements behave correctly */ int putchar(int); void exit(int); diff --git a/test/test03/hello.sh b/test/test03/hello.sh new file mode 100755 index 0000000..369ab09 --- /dev/null +++ b/test/test03/hello.sh @@ -0,0 +1,18 @@ +#! /bin/sh +set -x +# Build the test +bin/M2-Planet -f test/test03/constant.c -o test/test03/constant.M1 || exit 1 +# Macro assemble with libc written in M1-Macro +M1 -f test/common_x86/x86_defs.M1 -f test/common_x86/libc.M1 -f test/test03/constant.M1 --LittleEndian --Architecture 1 -o test/test03/constant.hex2 || exit 2 +# Resolve all linkages +hex2 -f test/common_x86/ELF-i386.hex2 -f test/test03/constant.hex2 --LittleEndian --Architecture 1 --BaseAddress 0x8048000 -o test/results/test03-binary --exec_enable || exit 3 + +# Ensure binary works if host machine supports test +if [ "$(get_machine)" = "x86_64" ] +then + # Verify that the compiled program returns the correct result + out=$(./test/results/test03-binary 2>&1 ) + [ 42 = $? ] || exit 4 + [ "$out" = "Hello mes" ] || exit 5 +fi +exit 0 diff --git a/test/test4/.gitignore b/test/test04/.gitignore similarity index 100% rename from test/test4/.gitignore rename to test/test04/.gitignore diff --git a/test/test4/call.c b/test/test04/call.c similarity index 95% rename from test/test4/call.c rename to test/test04/call.c index 7dcb484..fdac5ea 100644 --- a/test/test4/call.c +++ b/test/test04/call.c @@ -15,7 +15,7 @@ * along with stage0. If not, see . */ -/* Validate that IF statements behave correctly */ +/* Validate that call statements behave correctly */ int putchar(int); void exit(int); diff --git a/test/test04/cleanup.sh b/test/test04/cleanup.sh new file mode 100755 index 0000000..1e4895d --- /dev/null +++ b/test/test04/cleanup.sh @@ -0,0 +1,4 @@ +#! /bin/sh +rm -f test/test04/call.M1 +rm -f test/test04/call.hex2 +exit 0 diff --git a/test/test4/hello.sh b/test/test04/hello.sh similarity index 51% rename from test/test4/hello.sh rename to test/test04/hello.sh index 989ea82..099924c 100755 --- a/test/test4/hello.sh +++ b/test/test04/hello.sh @@ -1,17 +1,17 @@ #! /bin/sh set -x # Build the test -bin/M2-Planet -f test/test4/call.c -o test/test4/call.M1 || exit 1 +bin/M2-Planet -f test/test04/call.c -o test/test04/call.M1 || exit 1 # Macro assemble with libc written in M1-Macro -M1 -f test/common_x86/x86_defs.M1 -f test/common_x86/libc.M1 -f test/test4/call.M1 --LittleEndian --Architecture 1 -o test/test4/call.hex2 || exit 2 +M1 -f test/common_x86/x86_defs.M1 -f test/common_x86/libc.M1 -f test/test04/call.M1 --LittleEndian --Architecture 1 -o test/test04/call.hex2 || exit 2 # Resolve all linkages -hex2 -f test/common_x86/ELF-i386.hex2 -f test/test4/call.hex2 --LittleEndian --Architecture 1 --BaseAddress 0x8048000 -o test/results/test4-binary --exec_enable || exit 3 +hex2 -f test/common_x86/ELF-i386.hex2 -f test/test04/call.hex2 --LittleEndian --Architecture 1 --BaseAddress 0x8048000 -o test/results/test04-binary --exec_enable || exit 3 # Ensure binary works if host machine supports test if [ "$(get_machine)" = "x86_64" ] then # Verify that the compiled program returns the correct result - out=$(./test/results/test4-binary 2>&1 ) + out=$(./test/results/test04-binary 2>&1 ) [ 42 = $? ] || exit 4 [ "$out" = "Hello mes" ] || exit 5 fi diff --git a/test/test05/.gitignore b/test/test05/.gitignore new file mode 100644 index 0000000..e483926 --- /dev/null +++ b/test/test05/.gitignore @@ -0,0 +1,6 @@ +# Ignore the files created by script +*.M1 +*.hex2 + +# A place to put a good run for comparison +actual.M1 diff --git a/test/test05/cleanup.sh b/test/test05/cleanup.sh new file mode 100755 index 0000000..da8f707 --- /dev/null +++ b/test/test05/cleanup.sh @@ -0,0 +1,4 @@ +#! /bin/sh +rm -f test/test05/string.M1 +rm -f test/test05/string.hex2 +exit 0 diff --git a/test/test3/hello.sh b/test/test05/hello.sh similarity index 50% rename from test/test3/hello.sh rename to test/test05/hello.sh index 323ae85..7898483 100755 --- a/test/test3/hello.sh +++ b/test/test05/hello.sh @@ -1,17 +1,17 @@ #! /bin/sh set -x # Build the test -bin/M2-Planet -f test/test3/constant.c -o test/test3/constant.M1 || exit 1 +bin/M2-Planet -f test/test05/string.c -o test/test05/string.M1 || exit 1 # Macro assemble with libc written in M1-Macro -M1 -f test/common_x86/x86_defs.M1 -f test/common_x86/libc.M1 -f test/test3/constant.M1 --LittleEndian --Architecture 1 -o test/test3/constant.hex2 || exit 2 +M1 -f test/common_x86/x86_defs.M1 -f test/common_x86/libc.M1 -f test/test05/string.M1 --LittleEndian --Architecture 1 -o test/test05/string.hex2 || exit 2 # Resolve all linkages -hex2 -f test/common_x86/ELF-i386.hex2 -f test/test3/constant.hex2 --LittleEndian --Architecture 1 --BaseAddress 0x8048000 -o test/results/test3-binary --exec_enable || exit 3 +hex2 -f test/common_x86/ELF-i386.hex2 -f test/test05/string.hex2 --LittleEndian --Architecture 1 --BaseAddress 0x8048000 -o test/results/test05-binary --exec_enable || exit 3 # Ensure binary works if host machine supports test if [ "$(get_machine)" = "x86_64" ] then # Verify that the compiled program returns the correct result - out=$(./test/results/test3-binary 2>&1 ) + out=$(./test/results/test05-binary 2>&1 ) [ 42 = $? ] || exit 4 [ "$out" = "Hello mes" ] || exit 5 fi diff --git a/test/test05/string.c b/test/test05/string.c new file mode 100644 index 0000000..91ebb5d --- /dev/null +++ b/test/test05/string.c @@ -0,0 +1,38 @@ +/* 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 . + */ + +/* Validate that string statements behave correctly */ +int putchar(int); +void exit(int); + +void printc(char* s, int a) +{ + while((0 != s[0]) && (a > 0)) + { + putchar(s[0]); + s = s + 1; + a = a - 1; + } +} + +int main() +{ + char* string = "mes Hello "; + printc(string + 4, 99); + printc(string, 3); + return 42; +} diff --git a/test/test06/.gitignore b/test/test06/.gitignore new file mode 100644 index 0000000..a8bb3dd --- /dev/null +++ b/test/test06/.gitignore @@ -0,0 +1,7 @@ +# Ignore the files created by script +for.M1 +for.hex2 +proof + +# A place to put a good run for comparison +actual.M1 diff --git a/test/test06/cleanup.sh b/test/test06/cleanup.sh new file mode 100755 index 0000000..fffe224 --- /dev/null +++ b/test/test06/cleanup.sh @@ -0,0 +1,5 @@ +#! /bin/sh +rm -f test/test06/for.M1 +rm -f test/test06/for.hex2 +rm -f test/test06/proof +exit 0 diff --git a/test/test06/for.c b/test/test06/for.c new file mode 100644 index 0000000..4b398e1 --- /dev/null +++ b/test/test06/for.c @@ -0,0 +1,36 @@ +/* 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 +int putchar(int); + +int main() +{ + int max = 90; + int i; + int j; + for(i = 65; i <= max; i = i + 1) + { + putchar(i); + for(j = i + 1; j <= max; j = j + 1) + { + putchar(j); + } + putchar(10); + } + return 0; +} diff --git a/test/test06/hello.sh b/test/test06/hello.sh new file mode 100755 index 0000000..12400f6 --- /dev/null +++ b/test/test06/hello.sh @@ -0,0 +1,18 @@ +#! /bin/sh +set -ex +# Build the test +bin/M2-Planet -f test/test06/for.c -o test/test06/for.M1 || exit 1 +# Macro assemble with libc written in M1-Macro +M1 -f test/common_x86/x86_defs.M1 -f test/common_x86/libc.M1 -f test/test06/for.M1 --LittleEndian --Architecture 1 -o test/test06/for.hex2 || exit 2 +# Resolve all linkages +hex2 -f test/common_x86/ELF-i386.hex2 -f test/test06/for.hex2 --LittleEndian --Architecture 1 --BaseAddress 0x8048000 -o test/results/test06-binary --exec_enable || exit 3 + +# Ensure binary works if host machine supports test +if [ "$(get_machine)" = "x86_64" ] +then + # Verify that the resulting file works + ./test/results/test06-binary >| test/test06/proof || exit 4 + out=$(sha256sum -c test/test06/proof.answer) + [ "$out" = "test/test06/proof: OK" ] || exit 5 +fi +exit 0 diff --git a/test/test06/proof.answer b/test/test06/proof.answer new file mode 100644 index 0000000..cb8f4e7 --- /dev/null +++ b/test/test06/proof.answer @@ -0,0 +1 @@ +7dc238b12da104224bdb3d64edea5b5e150964faf868556bbc05d346590e3664 test/test06/proof diff --git a/test/test07/.gitignore b/test/test07/.gitignore new file mode 100644 index 0000000..0ce0949 --- /dev/null +++ b/test/test07/.gitignore @@ -0,0 +1,7 @@ +# Ignore the files created by script +*.M1 +*.hex2 +proof + +# A place to put a good run for comparison +actual.M1 diff --git a/test/test07/cleanup.sh b/test/test07/cleanup.sh new file mode 100755 index 0000000..e18e753 --- /dev/null +++ b/test/test07/cleanup.sh @@ -0,0 +1,5 @@ +#! /bin/sh +rm -f test/test07/do.M1 +rm -f test/test07/do.hex2 +rm -f test/test07/proof +exit 0 diff --git a/test/test07/do.c b/test/test07/do.c new file mode 100644 index 0000000..e7425ee --- /dev/null +++ b/test/test07/do.c @@ -0,0 +1,37 @@ +/* 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 . + */ + +/* Validate that call statements behave correctly */ +int putchar(int); +void exit(int); + +int main() +{ + int i = 65; + do + { + int j = i; + do + { + putchar(j); + j = j + 1; + } while (j <= 90); + i = i + 1; + putchar(10); + } while (i <= 90); + return 0; +} diff --git a/test/test07/hello.sh b/test/test07/hello.sh new file mode 100755 index 0000000..3197dca --- /dev/null +++ b/test/test07/hello.sh @@ -0,0 +1,18 @@ +#! /bin/sh +set -ex +# Build the test +bin/M2-Planet -f test/test07/do.c -o test/test07/do.M1 || exit 1 +# Macro assemble with libc written in M1-Macro +M1 -f test/common_x86/x86_defs.M1 -f test/common_x86/libc.M1 -f test/test07/do.M1 --LittleEndian --Architecture 1 -o test/test07/do.hex2 || exit 2 +# Resolve all linkages +hex2 -f test/common_x86/ELF-i386.hex2 -f test/test07/do.hex2 --LittleEndian --Architecture 1 --BaseAddress 0x8048000 -o test/results/test07-binary --exec_enable || exit 3 + +# Ensure binary works if host machine supports test +if [ "$(get_machine)" = "x86_64" ] +then + # Verify that the resulting file works + ./test/results/test07-binary >| test/test07/proof || exit 4 + out=$(sha256sum -c test/test07/proof.answer) + [ "$out" = "test/test07/proof: OK" ] || exit 5 +fi +exit 0 diff --git a/test/test07/proof.answer b/test/test07/proof.answer new file mode 100644 index 0000000..fcb235f --- /dev/null +++ b/test/test07/proof.answer @@ -0,0 +1 @@ +7dc238b12da104224bdb3d64edea5b5e150964faf868556bbc05d346590e3664 test/test07/proof diff --git a/test/test08/.gitignore b/test/test08/.gitignore new file mode 100644 index 0000000..e483926 --- /dev/null +++ b/test/test08/.gitignore @@ -0,0 +1,6 @@ +# Ignore the files created by script +*.M1 +*.hex2 + +# A place to put a good run for comparison +actual.M1 diff --git a/test/test08/cleanup.sh b/test/test08/cleanup.sh new file mode 100755 index 0000000..124215a --- /dev/null +++ b/test/test08/cleanup.sh @@ -0,0 +1,4 @@ +#! /bin/sh +rm -f test/test08/struct.M1 +rm -f test/test08/struct.hex2 +exit 0 diff --git a/test/test08/hello.sh b/test/test08/hello.sh new file mode 100755 index 0000000..a604a93 --- /dev/null +++ b/test/test08/hello.sh @@ -0,0 +1,18 @@ +#! /bin/sh +set -x +# Build the test +bin/M2-Planet -f test/test08/struct.c -o test/test08/struct.M1 || exit 1 +# Macro assemble with libc written in M1-Macro +M1 -f test/common_x86/x86_defs.M1 -f test/common_x86/libc.M1 -f test/test08/struct.M1 --LittleEndian --Architecture 1 -o test/test08/struct.hex2 || exit 2 +# Resolve all linkages +hex2 -f test/common_x86/ELF-i386.hex2 -f test/test08/struct.hex2 --LittleEndian --Architecture 1 --BaseAddress 0x8048000 -o test/results/test08-binary --exec_enable || exit 3 + +# Ensure binary works if host machine supports test +if [ "$(get_machine)" = "x86_64" ] +then + # Verify that the compiled program returns the correct result + out=$(./test/results/test08-binary 2>&1 ) + [ 16 = $? ] || exit 4 + [ "$out" = "35419896642975313541989657891634" ] || exit 5 +fi +exit 0 diff --git a/test/test08/struct.c b/test/test08/struct.c new file mode 100644 index 0000000..d850052 --- /dev/null +++ b/test/test08/struct.c @@ -0,0 +1,58 @@ +/* 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 . + */ + +/* Validate that call statements behave correctly */ +void *malloc(int); +int putchar(int); +void exit(int); + +struct foo +{ + struct foo* next; + struct foo* prev; + int a; + int b; +}; + +void print_hex(int a, int count) +{ + if(count <= 0) return; + print_hex(a >> 4, count - 1); + putchar((a & 15) + 48); +} + +int main() +{ + struct foo* a = malloc(sizeof(struct foo)); + struct foo* b = malloc(sizeof(struct foo)); + + a->a = 0x35419896; + a->b = 0x57891634; + b->a = 0x13579246; + b->b = 0x64297531; + a->next = b; + a->prev = b; + b->next = a; + b->prev = a; + + print_hex(a->next->next->a, 8); + print_hex(b->prev->prev->b, 8); + print_hex(b->next->a, 8); + print_hex(b->prev->b, 8); + putchar(10); + return sizeof(struct foo); +} diff --git a/test/test09/.gitignore b/test/test09/.gitignore new file mode 100644 index 0000000..e483926 --- /dev/null +++ b/test/test09/.gitignore @@ -0,0 +1,6 @@ +# Ignore the files created by script +*.M1 +*.hex2 + +# A place to put a good run for comparison +actual.M1 diff --git a/test/test09/cleanup.sh b/test/test09/cleanup.sh new file mode 100755 index 0000000..2e5e7a8 --- /dev/null +++ b/test/test09/cleanup.sh @@ -0,0 +1,4 @@ +#! /bin/sh +rm -f test/test09/goto.M1 +rm -f test/test09/goto.hex2 +exit 0 diff --git a/test/test09/goto.c b/test/test09/goto.c new file mode 100644 index 0000000..c109ebb --- /dev/null +++ b/test/test09/goto.c @@ -0,0 +1,46 @@ +/* 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 . + */ + +/* Validate that call statements behave correctly */ +int putchar(int); +void exit(int); + +void printstring(char* s) +{ + while(0 != s[0]) + { + putchar(s[0]); + s = s + 1; + } +} + +int main() +{ + goto win; + exit(1); + +mes: + printstring("Hello mes\x0A"); + goto done; + +win: + goto mes; + exit(2); + +done: + return 42; +} diff --git a/test/test09/hello.sh b/test/test09/hello.sh new file mode 100755 index 0000000..807e2cf --- /dev/null +++ b/test/test09/hello.sh @@ -0,0 +1,18 @@ +#! /bin/sh +set -x +# Build the test +bin/M2-Planet -f test/test09/goto.c -o test/test09/goto.M1 || exit 1 +# Macro assemble with libc written in M1-Macro +M1 -f test/common_x86/x86_defs.M1 -f test/common_x86/libc.M1 -f test/test09/goto.M1 --LittleEndian --Architecture 1 -o test/test09/goto.hex2 || exit 2 +# Resolve all linkages +hex2 -f test/common_x86/ELF-i386.hex2 -f test/test09/goto.hex2 --LittleEndian --Architecture 1 --BaseAddress 0x8048000 -o test/results/test09-binary --exec_enable || exit 3 + +# Ensure binary works if host machine supports test +if [ "$(get_machine)" = "x86_64" ] +then + # Verify that the compiled program returns the correct result + out=$(./test/results/test09-binary 2>&1 ) + [ 42 = $? ] || exit 4 + [ "$out" = "Hello mes" ] || exit 5 +fi +exit 0 diff --git a/test/test1/cleanup.sh b/test/test1/cleanup.sh deleted file mode 100755 index e6b127f..0000000 --- a/test/test1/cleanup.sh +++ /dev/null @@ -1,4 +0,0 @@ -#! /bin/sh -rm -f test/test1/library_call.M1 -rm -f test/test1/library_call.hex2 -exit 0 diff --git a/test/test1/hello.sh b/test/test1/hello.sh deleted file mode 100755 index 9ae5397..0000000 --- a/test/test1/hello.sh +++ /dev/null @@ -1,18 +0,0 @@ -#! /bin/sh -set -x -# Build the test -bin/M2-Planet -f test/test1/library_call.c -o test/test1/library_call.M1 || exit 1 -# Macro assemble with libc written in M1-Macro -M1 -f test/common_x86/x86_defs.M1 -f test/common_x86/libc.M1 -f test/test1/library_call.M1 --LittleEndian --Architecture 1 -o test/test1/library_call.hex2 || exit 2 -# Resolve all linkages -hex2 -f test/common_x86/ELF-i386.hex2 -f test/test1/library_call.hex2 --LittleEndian --Architecture 1 --BaseAddress 0x8048000 -o test/results/test1-binary --exec_enable || exit 3 - -# Ensure binary works if host machine supports test -if [ "$(get_machine)" = "x86_64" ] -then - # Verify that the compiled program returns the correct result - out=$(./test/results/test1-binary 2>&1) - [ 42 = $? ] || exit 3 - [ "$out" = "Hello mes" ] || exit 4 -fi -exit 0 diff --git a/test/test10/.gitignore b/test/test10/.gitignore new file mode 100644 index 0000000..e483926 --- /dev/null +++ b/test/test10/.gitignore @@ -0,0 +1,6 @@ +# Ignore the files created by script +*.M1 +*.hex2 + +# A place to put a good run for comparison +actual.M1 diff --git a/test/test10/cleanup.sh b/test/test10/cleanup.sh new file mode 100755 index 0000000..9811983 --- /dev/null +++ b/test/test10/cleanup.sh @@ -0,0 +1,4 @@ +#! /bin/sh +rm -f test/test10/nested_struct.M1 +rm -f test/test10/nested_struct.hex2 +exit 0 diff --git a/test/test10/hello.sh b/test/test10/hello.sh new file mode 100755 index 0000000..7b4512b --- /dev/null +++ b/test/test10/hello.sh @@ -0,0 +1,18 @@ +#! /bin/sh +set -x +# Build the test +bin/M2-Planet -f test/test10/nested_struct.c -o test/test10/nested_struct.M1 || exit 1 +# Macro assemble with libc written in M1-Macro +M1 -f test/common_x86/x86_defs.M1 -f test/common_x86/libc.M1 -f test/test10/nested_struct.M1 --LittleEndian --Architecture 1 -o test/test10/nested_struct.hex2 || exit 2 +# Resolve all linkages +hex2 -f test/common_x86/ELF-i386.hex2 -f test/test10/nested_struct.hex2 --LittleEndian --Architecture 1 --BaseAddress 0x8048000 -o test/results/test10-binary --exec_enable || exit 3 + +# Ensure binary works if host machine supports test +if [ "$(get_machine)" = "x86_64" ] +then + # Verify that the compiled program returns the correct result + out=$(./test/results/test10-binary 2>&1 ) + [ 12 = $? ] || exit 4 + [ "$out" = "35419896642975313541989657891634" ] || exit 5 +fi +exit 0 diff --git a/test/test10/nested_struct.c b/test/test10/nested_struct.c new file mode 100644 index 0000000..09ceec0 --- /dev/null +++ b/test/test10/nested_struct.c @@ -0,0 +1,68 @@ +/* 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 . + */ + +/* Validate that nested struct statements behave correctly */ +void *malloc(int); +int putchar(int); +void exit(int); + +struct bar +{ + char z; + int x; + int y; +}; + +struct foo +{ + struct foo* next; + struct foo* prev; + struct bar* a; +}; + +void print_hex(int a, int count) +{ + if(count <= 0) return; + print_hex(a >> 4, count - 1); + putchar((a & 15) + 48); +} + +int main() +{ + struct foo* a = malloc(sizeof(struct foo)); + struct foo* b = malloc(sizeof(struct foo)); + struct bar* c = malloc(sizeof(struct bar)); + struct bar* d = malloc(sizeof(struct bar)); + + c->x = 0x35419896; + c->y = 0x57891634; + d->x = 0x13579246; + d->y = 0x64297531; + a->a = c; + b->a = d; + a->next = b; + a->prev = b; + b->next = a; + b->prev = a; + + print_hex(a->next->next->a->x, 8); + print_hex(b->prev->prev->a->y, 8); + print_hex(b->next->a->x, 8); + print_hex(b->prev->a->y, 8); + putchar(10); + return sizeof(struct foo); +} diff --git a/test/test2/cleanup.sh b/test/test2/cleanup.sh deleted file mode 100755 index ea7143d..0000000 --- a/test/test2/cleanup.sh +++ /dev/null @@ -1,4 +0,0 @@ -#! /bin/sh -rm -f test/test2/if.M1 -rm -f test/test2/if.hex2 -exit 0 diff --git a/test/test3/cleanup.sh b/test/test3/cleanup.sh deleted file mode 100755 index a72e6ba..0000000 --- a/test/test3/cleanup.sh +++ /dev/null @@ -1,4 +0,0 @@ -#! /bin/sh -rm -f test/test3/constant.M1 -rm -f test/test3/constant.hex2 -exit 0 diff --git a/test/test4/cleanup.sh b/test/test4/cleanup.sh deleted file mode 100755 index f2c8289..0000000 --- a/test/test4/cleanup.sh +++ /dev/null @@ -1,4 +0,0 @@ -#! /bin/sh -rm -f test/test4/call.M1 -rm -f test/test4/call.hex2 -exit 0