Added additional functionality such as mixed structs, do while loops,
gotos and tests for the new functionality
This commit is contained in:
parent
9a919d20ea
commit
f6752b2802
26
cc-minimal.c
26
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;
|
||||
}
|
||||
|
|
32
cc.c
32
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;
|
||||
}
|
||||
|
|
25
cc.h
25
cc.h
|
@ -18,9 +18,21 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#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;
|
||||
|
||||
|
|
399
cc_core.c
399
cc_core.c
|
@ -19,13 +19,12 @@
|
|||
#include <stdint.h>
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
|
30
cc_reader.c
30
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;
|
||||
}
|
||||
|
|
63
cc_strings.c
63
cc_strings.c
|
@ -19,7 +19,6 @@
|
|||
#include <stdint.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "cc.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/* 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;
|
||||
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
int fgetc(FILE*);
|
||||
int* calloc(int, int);
|
||||
void free(void*);
|
||||
void exit(int);
|
||||
int strcmp(char* a, char* b);
|
64
makefile
64
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
#! /bin/sh
|
||||
rm -f test/test0/return.M1
|
||||
rm -f test/test0/return.hex2
|
||||
exit 0
|
|
@ -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
|
|
@ -0,0 +1,4 @@
|
|||
#! /bin/sh
|
||||
rm -f test/test00/return.M1
|
||||
rm -f test/test00/return.hex2
|
||||
exit 0
|
|
@ -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
|
|
@ -0,0 +1,4 @@
|
|||
#! /bin/sh
|
||||
rm -f test/test01/library_call.M1
|
||||
rm -f test/test01/library_call.hex2
|
||||
exit 0
|
|
@ -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
|
|
@ -0,0 +1,4 @@
|
|||
#! /bin/sh
|
||||
rm -f test/test02/if.M1
|
||||
rm -f test/test02/if.hex2
|
||||
exit 0
|
|
@ -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
|
|
@ -0,0 +1,4 @@
|
|||
#! /bin/sh
|
||||
rm -f test/test03/constant.M1
|
||||
rm -f test/test03/constant.hex2
|
||||
exit 0
|
|
@ -15,7 +15,7 @@
|
|||
* along with stage0. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Validate that IF statements behave correctly */
|
||||
/* Validate that constant statements behave correctly */
|
||||
int putchar(int);
|
||||
void exit(int);
|
||||
|
|
@ -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
|
|
@ -15,7 +15,7 @@
|
|||
* along with stage0. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Validate that IF statements behave correctly */
|
||||
/* Validate that call statements behave correctly */
|
||||
int putchar(int);
|
||||
void exit(int);
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
#! /bin/sh
|
||||
rm -f test/test04/call.M1
|
||||
rm -f test/test04/call.hex2
|
||||
exit 0
|
|
@ -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
|
|
@ -0,0 +1,6 @@
|
|||
# Ignore the files created by script
|
||||
*.M1
|
||||
*.hex2
|
||||
|
||||
# A place to put a good run for comparison
|
||||
actual.M1
|
|
@ -0,0 +1,4 @@
|
|||
#! /bin/sh
|
||||
rm -f test/test05/string.M1
|
||||
rm -f test/test05/string.hex2
|
||||
exit 0
|
|
@ -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
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* 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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
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;
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
7dc238b12da104224bdb3d64edea5b5e150964faf868556bbc05d346590e3664 test/test06/proof
|
|
@ -0,0 +1,7 @@
|
|||
# Ignore the files created by script
|
||||
*.M1
|
||||
*.hex2
|
||||
proof
|
||||
|
||||
# A place to put a good run for comparison
|
||||
actual.M1
|
|
@ -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
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* 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;
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
7dc238b12da104224bdb3d64edea5b5e150964faf868556bbc05d346590e3664 test/test07/proof
|
|
@ -0,0 +1,6 @@
|
|||
# Ignore the files created by script
|
||||
*.M1
|
||||
*.hex2
|
||||
|
||||
# A place to put a good run for comparison
|
||||
actual.M1
|
|
@ -0,0 +1,4 @@
|
|||
#! /bin/sh
|
||||
rm -f test/test08/struct.M1
|
||||
rm -f test/test08/struct.hex2
|
||||
exit 0
|
|
@ -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
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* 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);
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
# Ignore the files created by script
|
||||
*.M1
|
||||
*.hex2
|
||||
|
||||
# A place to put a good run for comparison
|
||||
actual.M1
|
|
@ -0,0 +1,4 @@
|
|||
#! /bin/sh
|
||||
rm -f test/test09/goto.M1
|
||||
rm -f test/test09/goto.hex2
|
||||
exit 0
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* 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;
|
||||
}
|
|
@ -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
|
|
@ -1,4 +0,0 @@
|
|||
#! /bin/sh
|
||||
rm -f test/test1/library_call.M1
|
||||
rm -f test/test1/library_call.hex2
|
||||
exit 0
|
|
@ -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
|
|
@ -0,0 +1,6 @@
|
|||
# Ignore the files created by script
|
||||
*.M1
|
||||
*.hex2
|
||||
|
||||
# A place to put a good run for comparison
|
||||
actual.M1
|
|
@ -0,0 +1,4 @@
|
|||
#! /bin/sh
|
||||
rm -f test/test10/nested_struct.M1
|
||||
rm -f test/test10/nested_struct.hex2
|
||||
exit 0
|
|
@ -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
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* 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);
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
#! /bin/sh
|
||||
rm -f test/test2/if.M1
|
||||
rm -f test/test2/if.hex2
|
||||
exit 0
|
|
@ -1,4 +0,0 @@
|
|||
#! /bin/sh
|
||||
rm -f test/test3/constant.M1
|
||||
rm -f test/test3/constant.hex2
|
||||
exit 0
|
|
@ -1,4 +0,0 @@
|
|||
#! /bin/sh
|
||||
rm -f test/test4/call.M1
|
||||
rm -f test/test4/call.hex2
|
||||
exit 0
|
Loading…
Reference in New Issue