diff --git a/cc_core.c b/cc_core.c index 1f751ae..a9c7581 100644 --- a/cc_core.c +++ b/cc_core.c @@ -38,11 +38,13 @@ int current_count; int Address_of; /* Imported functions */ +char* number_to_hex(int a, int bytes); +char* numerate_number(int a); char* parse_string(char* string); int escape_lookup(char* c); -char* numerate_number(int a); int numerate_string(char *a); -char* number_to_hex(int a, int bytes); +void require(int bool, char* error); + struct token_list* emit(char *s, struct token_list* head) { @@ -89,6 +91,7 @@ struct token_list* sym_lookup(char *s, struct token_list* symbol_list) void line_error() { + require(NULL != global_token, "EOF reached inside of line_error\n"); file_print(global_token->filename, stderr); file_print(":", stderr); file_print(numerate_number(global_token->linenumber), stderr); @@ -97,6 +100,7 @@ void line_error() void require_match(char* message, char* required) { + require(NULL != global_token, "EOF reached inside of require match\n"); if(!match(global_token->s, required)) { line_error(); @@ -104,6 +108,7 @@ void require_match(char* message, char* required) exit(EXIT_FAILURE); } global_token = global_token->next; + require(NULL != global_token, "EOF after require match occurred\n"); } void expression(); @@ -140,6 +145,7 @@ void function_call(char* s, int bool) if(global_token->s[0] != ')') { expression(); + require(NULL != global_token, "incomplete function call, recieved EOF instead of )\n"); if((KNIGHT_POSIX == Architecture) || (KNIGHT_NATIVE == Architecture)) emit_out("PUSHR R0 R15\t#_process_expression1\n"); else if(X86 == Architecture) emit_out("PUSH_eax\t#_process_expression1\n"); else if(AMD64 == Architecture) emit_out("PUSH_RAX\t#_process_expression1\n"); @@ -149,6 +155,7 @@ void function_call(char* s, int bool) while(global_token->s[0] == ',') { global_token = global_token->next; + require(NULL != global_token, "incomplete function call, recieved EOF instead of argument\n"); expression(); if((KNIGHT_POSIX == Architecture) || (KNIGHT_NATIVE == Architecture)) emit_out("PUSHR R0 R15\t#_process_expression2\n"); else if(X86 == Architecture) emit_out("PUSH_eax\t#_process_expression2\n"); @@ -280,6 +287,7 @@ void constant_load(struct token_list* a) void variable_load(struct token_list* a) { + require(NULL != global_token, "incomplete variable load recieved\n"); if(match("FUNCTION", a->type->name) && match("(", global_token->s)) { function_call(numerate_number(a->depth), TRUE); @@ -307,6 +315,7 @@ void variable_load(struct token_list* a) void function_load(struct token_list* a) { + require(NULL != global_token, "incomplete function load\n"); if(match("(", global_token->s)) { function_call(a->s, FALSE); @@ -332,6 +341,8 @@ void global_load(struct token_list* a) else if(ARMV7L == Architecture) emit_out("!0 R0 LOAD32 R15 MEMORY\n~0 JUMP_ALWAYS\n&GLOBAL_"); emit_out(a->s); emit_out("\n"); + + require(NULL != global_token, "unterminated global load\n"); if(!match("=", global_token->s)) { if((KNIGHT_POSIX == Architecture) || (KNIGHT_NATIVE == Architecture)) emit_out("LOAD R0 R0 0\n"); @@ -353,6 +364,7 @@ void global_load(struct token_list* a) void primary_expr_failure() { + require(NULL != global_token, "hit EOF when expecting primary expression\n"); line_error(); file_print("Received ", stderr); file_print(global_token->s, stderr); @@ -505,6 +517,7 @@ void common_recursion(FUNCTION f) struct type* last_type = current_target; global_token = global_token->next; + require(NULL != global_token, "Recieved EOF in common_recursion\n"); f(); current_target = promote_type(current_target, last_type); @@ -516,6 +529,7 @@ void common_recursion(FUNCTION f) void general_recursion(FUNCTION f, char* s, char* name, FUNCTION iterate) { + require(NULL != global_token, "Recieved EOF in general_recursion\n"); if(match(name, global_token->s)) { common_recursion(f); @@ -526,6 +540,7 @@ void general_recursion(FUNCTION f, char* s, char* name, FUNCTION iterate) void arithmetic_recursion(FUNCTION f, char* s1, char* s2, char* name, FUNCTION iterate) { + require(NULL != global_token, "Recieved EOF in arithmetic_recursion\n"); if(match(name, global_token->s)) { common_recursion(f); @@ -575,10 +590,12 @@ void postfix_expr_arrow() { emit_out("# looking up offset\n"); global_token = global_token->next; + require(NULL != global_token, "naked -> not allowed\n"); struct type* i = lookup_member(current_target, global_token->s); current_target = i->type; global_token = global_token->next; + require(NULL != global_token, "Unterminated -> expression not allowed\n"); if(0 != i->offset) { @@ -623,6 +640,8 @@ void postfix_expr_array() struct type* array = current_target; common_recursion(expression); current_target = array; + require(NULL != current_target, "Arrays only apply to variables\n"); + char* assign; if((KNIGHT_POSIX == Architecture) || (KNIGHT_NATIVE == Architecture)) assign = "LOAD R0 R0 0\n"; else if(X86 == Architecture) assign = "LOAD_INTEGER\n"; @@ -675,6 +694,7 @@ struct type* type_name(); void unary_expr_sizeof() { global_token = global_token->next; + require(NULL != global_token, "Recieved EOF when starting sizeof\n"); require_match("ERROR in unary_expr\nMissing (\n", "("); struct type* a = type_name(); require_match("ERROR in unary_expr\nMissing )\n", ")"); @@ -690,6 +710,7 @@ void unary_expr_sizeof() void postfix_expr_stub() { + require(NULL != global_token, "Unexpected EOF, improperly terminated primary expression\n"); if(match("[", global_token->s)) { postfix_expr_array(); @@ -887,10 +908,12 @@ void bitwise_expr() void primary_expr() { + require(NULL != global_token, "Recieved EOF where primary expression expected\n"); if(match("&", global_token->s)) { Address_of = TRUE; global_token = global_token->next; + require(NULL != global_token, "Recieved EOF after & where primary expression expected\n"); } else { @@ -1016,10 +1039,12 @@ void collect_local() emit_out("\n"); global_token = global_token->next; + require(NULL != global_token, "incomplete local missing name\n"); if(match("=", global_token->s)) { global_token = global_token->next; + require(NULL != global_token, "incomplete local assignment\n"); expression(); } @@ -1073,6 +1098,7 @@ void process_if() if(match("else", global_token->s)) { global_token = global_token->next; + require(NULL != global_token, "Recieved EOF where an else statement expected\n"); statement(); } emit_out(":_END_IF_"); @@ -1170,6 +1196,7 @@ void process_asm() emit_out((global_token->s + 1)); emit_out("\n"); global_token = global_token->next; + require(NULL != global_token, "Recieved EOF inside asm statement\n"); } require_match("ERROR in process_asm\nMISSING )\n", ")"); require_match("ERROR in process_asm\nMISSING ;\n", ";"); @@ -1195,6 +1222,7 @@ void process_do() uniqueID_out(function->s, number_string); global_token = global_token->next; + require(NULL != global_token, "Recieved EOF where do statement is expected\n"); statement(); require_match("ERROR in process_do\nMISSING while\n", "while"); @@ -1274,6 +1302,7 @@ void process_while() void return_result() { global_token = global_token->next; + require(NULL != global_token, "Incomplete return statement recieved\n"); if(global_token->s[0] != ';') expression(); require_match("ERROR in return_result\nMISSING ;\n", ";"); @@ -1330,11 +1359,13 @@ void process_break() void recursive_statement() { global_token = global_token->next; + require(NULL != global_token, "Recieved EOF in recursive statement\n"); struct token_list* frame = function->locals; while(!match("}", global_token->s)) { statement(); + require(NULL != global_token, "Recieved EOF in recursive statement prior to }\n"); } global_token = global_token->next; @@ -1416,6 +1447,7 @@ void statement() else if(match("goto", global_token->s)) { global_token = global_token->next; + require(NULL != global_token, "naked goto is not supported\n"); if((KNIGHT_POSIX == Architecture) || (KNIGHT_NATIVE == Architecture)) emit_out("JUMP @"); else if(X86 == Architecture) emit_out("JUMP %"); else if(AMD64 == Architecture) emit_out("JUMP %"); @@ -1451,6 +1483,7 @@ void statement() void collect_arguments() { global_token = global_token->next; + require(NULL != global_token, "Recieved EOF when attempting to collect arguments\n"); while(!match(")", global_token->s)) { @@ -1480,11 +1513,18 @@ void collect_arguments() } global_token = global_token->next; + require(NULL != global_token, "Incomplete argument list\n"); function->arguments = a; } /* ignore trailing comma (needed for foo(bar(), 1); expressions*/ - if(global_token->s[0] == ',') global_token = global_token->next; + if(global_token->s[0] == ',') + { + global_token = global_token->next; + require(NULL != global_token, "naked comma in collect arguments\n"); + } + + require(NULL != global_token, "Argument list never completed\n"); } global_token = global_token->next; } @@ -1503,6 +1543,7 @@ void declare_function() } else collect_arguments(); + require(NULL != global_token, "Function definitions either need to be prototypes or full\n"); /* If just a prototype don't waste time */ if(global_token->s[0] == ';') global_token = global_token->next; else @@ -1552,8 +1593,10 @@ new_type: if(match("CONSTANT", global_token->s)) { global_token = global_token->next; + require(NULL != global_token, "CONSTANT lacks a name\n"); global_constant_list = sym_declare(global_token->s, NULL, global_constant_list); + require(NULL != global_token->next, "CONSTANT lacks a value\n"); if(match("sizeof", global_token->next->s)) { global_token = global_token->next->next; @@ -1579,6 +1622,7 @@ new_type: /* Add to global symbol table */ global_symbol_list = sym_declare(global_token->s, type_size, global_symbol_list); global_token = global_token->next; + require(NULL != global_token, "Unterminated global\n"); if(match(";", global_token->s)) { /* Ensure 4 bytes are allocated for the global */ @@ -1596,6 +1640,7 @@ new_type: globals_list = emit(global_token->prev->s, globals_list); globals_list = emit("\n", globals_list); global_token = global_token->next; + require(NULL != global_token, "Global locals value in assignment\n"); if(in_set(global_token->s[0], "0123456789")) { /* Assume Int */ globals_list = emit("%", globals_list); diff --git a/cc_reader.c b/cc_reader.c index c8de815..dbd2a07 100644 --- a/cc_reader.c +++ b/cc_reader.c @@ -16,23 +16,16 @@ */ #include "cc.h" + +/* imported functions */ +int in_set(int c, char* s); +void require(int bool, char* error); + +/* Globals */ FILE* input; struct token_list* token; int line; char* file; -int in_set(int c, char* s); - - -/* Deal with common errors */ -void require(int bool, char* error) -{ - if(!bool) - { - file_print(error, stderr); - exit(EXIT_FAILURE); - } -} - int clearWhiteSpace(int c) { diff --git a/cc_types.c b/cc_types.c index 3149ada..08ce16e 100644 --- a/cc_types.c +++ b/cc_types.c @@ -17,8 +17,11 @@ #include "cc.h" #include -void line_error(); + +/* Imported functions */ int numerate_string(char *a); +void line_error(); +void require(int bool, char* error); /* Initialize default types */ void initialize_types() @@ -156,6 +159,7 @@ struct type* lookup_type(char* s, struct type* start) struct type* lookup_member(struct type* parent, char* name) { struct type* i; + require(NULL != parent, "Not a valid struct type\n"); for(i = parent->members; NULL != i; i = i->members) { if(match(i->name, name)) return i; @@ -182,14 +186,17 @@ struct type* build_member(struct type* last, int offset) i->offset = offset; struct type* member_type = type_name(); + require(NULL != member_type, "struct member type can not be invalid\n"); i->type = member_type; i->name = global_token->s; global_token = global_token->next; + require(NULL != global_token, "struct member can not be EOF terminated\n"); /* Check to see if array */ if(match( "[", global_token->s)) { global_token = global_token->next; + require(NULL != global_token, "struct member arrays can not be EOF sized\n"); i->size = member_type->type->size * numerate_string(global_token->s); if(0 == i->size) { @@ -221,6 +228,7 @@ struct type* build_union(struct type* last, int offset) size = member_size; } require_match("ERROR in build_union\nMissing ;\n", ";"); + require(NULL != global_token, "Unterminated union\n"); } member_size = size; global_token = global_token->next; @@ -257,6 +265,7 @@ void create_struct() } offset = offset + member_size; require_match("ERROR in create_struct\n Missing ;\n", ";"); + require(NULL != global_token, "Unterminated struct\n"); } global_token = global_token->next; @@ -272,9 +281,11 @@ struct type* type_name() { struct type* ret; + require(NULL != global_token, "Recieved EOF instead of type name\n"); if(match("struct", global_token->s)) { global_token = global_token->next; + require(NULL != global_token, "structs can not have a EOF type name\n"); ret = lookup_type(global_token->s, global_types); if(NULL == ret) { @@ -296,16 +307,19 @@ struct type* type_name() } global_token = global_token->next; + require(NULL != global_token, "unfinished type definition\n"); if(match("const", global_token->s)) { global_token = global_token->next; + require(NULL != global_token, "unfinished type definition in const\n"); } while(global_token->s[0] == '*') { ret = ret->indirect; global_token = global_token->next; + require(NULL != global_token, "unfinished type definition in indirection\n"); } return ret; diff --git a/functions/require.c b/functions/require.c new file mode 100644 index 0000000..ba5983c --- /dev/null +++ b/functions/require.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2016 Jeremiah Orians + * Copyright (C) 2018 Jan (janneke) Nieuwenhuizen + * This file is part of M2-Planet. + * + * M2-Planet 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. + * + * M2-Planet 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 M2-Planet. If not, see . + */ + +#include +#include + +void file_print(char* s, FILE* f); + +void require(int bool, char* error) +{ + if(!bool) + { + file_print(error, stderr); + exit(EXIT_FAILURE); + } +} diff --git a/makefile b/makefile index 7565815..b090f34 100644 --- a/makefile +++ b/makefile @@ -18,10 +18,29 @@ VPATH = bin:test:test/results PACKAGE = m2-planet +# C compiler settings +CC?=gcc +CFLAGS:=$(CFLAGS) -D_GNU_SOURCE -O0 -std=c99 -ggdb + all: M2-Planet M2-Planet: bin results cc.h cc_reader.c cc_strings.c cc_types.c cc_core.c cc.c - ./test/test100/hello.sh + $(CC) $(CFLAGS) \ + functions/match.c \ + functions/in_set.c \ + functions/numerate_number.c \ + functions/file_print.c \ + functions/number_pack.c \ + functions/string.c \ + functions/require.c \ + cc_reader.c \ + cc_strings.c \ + cc_types.c \ + cc_core.c \ + cc.c \ + cc.h \ + gcc_req.h \ + -o bin/M2-Planet # Clean up after ourselves .PHONY: clean diff --git a/test/test.answers b/test/test.answers index 433860c..80ac07e 100644 --- a/test/test.answers +++ b/test/test.answers @@ -53,10 +53,10 @@ a0ae067746e7a2b01d33950da1cf640e12c3a70a045ab331ea2025af59dec9af test/results/t 1154f39f25dcd6d914e9a542306f95280926baf985d011b2152c7ea0b87ab42d test/results/test10-knight-native-binary c1b5a2a3cd46c5e95e5540e871c2a916e028684ca80f51c001ef489342e27625 test/results/test10-knight-posix-binary b3e13d54aab689137628fb9c4487bfd8288f9bd18bef8fe756577c8d2dce1f1f test/results/test10-x86-binary -c0becbe4e1edb7218bf2f6849493f768da8078a87af18ff093eaf9f6c1fcb9e7 test/results/test100-amd64-binary -d95bd6ad6a59ef9f508e462ebb4b716f2799ed30a5882c549156cb0f3ca00a42 test/results/test100-armv7l-binary -d044e557477b6a2db1c983d353bc7aa2080600894839947f5191ee524f231300 test/results/test100-knight-posix-binary -8e33e2bf5cdb0c127cca0c4bdbc627d7f2cbdb5130aadedbfc01a379520174a0 test/results/test100-x86-binary +1b6e8c0ab5a944f1d83065db5d18a265c6e14109c532b89d3cc316b4074f9e73 test/results/test100-amd64-binary +540ca777bf1a48c51ae9ca9e172ded87b28362adee9ca220c176122e872f6c45 test/results/test100-armv7l-binary +6f8d22172abf64e5cfc8621c81236aab58de96fdc79332475df0e1c5b87821a3 test/results/test100-knight-posix-binary +7637a9078de8914e2821df07371083b319a095d51e237881e526290ab472df67 test/results/test100-x86-binary 34e6d535e30ef8826a4ad1a4d08b76cfa370c54595599ad3be784b64c9cd8ec5 test/results/test11-amd64-binary 893695e6f300a0fe055fad935a56abd549bba70d1d39c535a680f41bbb73f117 test/results/test11-armv7l-binary 955b564d2c89abf2cfc6c80d766cd11479d146b828dec69e654b0958a62d5e6e test/results/test11-knight-native-binary diff --git a/test/test100/hello-amd64.sh b/test/test100/hello-amd64.sh index 82116c3..173cad3 100755 --- a/test/test100/hello-amd64.sh +++ b/test/test100/hello-amd64.sh @@ -28,6 +28,7 @@ set -ex -f functions/file_print.c \ -f functions/number_pack.c \ -f functions/string.c \ + -f functions/require.c \ -f cc.h \ -f cc_reader.c \ -f cc_strings.c \ @@ -73,6 +74,7 @@ then -f functions/file_print.c \ -f functions/number_pack.c \ -f functions/string.c \ + -f functions/require.c \ -f cc.h \ -f cc_reader.c \ -f cc_strings.c \ diff --git a/test/test100/hello-armv7l.sh b/test/test100/hello-armv7l.sh index c25f044..cb49f95 100755 --- a/test/test100/hello-armv7l.sh +++ b/test/test100/hello-armv7l.sh @@ -28,6 +28,7 @@ set -ex -f functions/file_print.c \ -f functions/number_pack.c \ -f functions/string.c \ + -f functions/require.c \ -f cc.h \ -f cc_reader.c \ -f cc_strings.c \ @@ -73,6 +74,7 @@ then -f functions/file_print.c \ -f functions/number_pack.c \ -f functions/string.c \ + -f functions/require.c \ -f cc.h \ -f cc_reader.c \ -f cc_strings.c \ diff --git a/test/test100/hello-knight-posix.sh b/test/test100/hello-knight-posix.sh index a051be8..1ce9c02 100755 --- a/test/test100/hello-knight-posix.sh +++ b/test/test100/hello-knight-posix.sh @@ -28,6 +28,7 @@ set -ex -f functions/file_print.c \ -f functions/number_pack.c \ -f functions/string.c \ + -f functions/require.c \ -f cc.h \ -f cc_reader.c \ -f cc_strings.c \ @@ -68,6 +69,7 @@ then -f functions/file_print.c \ -f functions/number_pack.c \ -f functions/string.c \ + -f functions/require.c \ -f cc.h \ -f cc_reader.c \ -f cc_strings.c \ diff --git a/test/test100/hello-x86.sh b/test/test100/hello-x86.sh index d873462..65b5156 100755 --- a/test/test100/hello-x86.sh +++ b/test/test100/hello-x86.sh @@ -28,6 +28,7 @@ set -ex -f functions/file_print.c \ -f functions/number_pack.c \ -f functions/string.c \ + -f functions/require.c \ -f cc.h \ -f cc_reader.c \ -f cc_strings.c \ @@ -73,6 +74,7 @@ then -f functions/file_print.c \ -f functions/number_pack.c \ -f functions/string.c \ + -f functions/require.c \ -f cc.h \ -f cc_reader.c \ -f cc_strings.c \ diff --git a/test/test100/hello.sh b/test/test100/hello.sh deleted file mode 100755 index f7032f2..0000000 --- a/test/test100/hello.sh +++ /dev/null @@ -1,60 +0,0 @@ -#! /bin/sh -## Copyright (C) 2017 Jeremiah Orians -## This file is part of M2-Planet. -## -## M2-Planet 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. -## -## M2-Planet 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 M2-Planet. If not, see . - -set -ex -# Build using seed if possible -if [ -f bin/M2-Planet-seed ] -then - [ ! -f test/results ] && mkdir -p test/results - cp bin/M2-Planet-seed bin/M2-Planet - - if [ "$(get_machine ${GET_MACHINE_FLAGS})" = "amd64" ] - then - ./test/test100/hello-amd64.sh - mv test/results/test100-amd64-binary bin/M2-Planet - elif [ "$(get_machine ${GET_MACHINE_FLAGS})" = "x86" ] - then - ./test/test100/hello-x86.sh - mv test/results/test100-x86-binary bin/M2-Planet - elif [ "$(get_machine ${GET_MACHINE_FLAGS})" = "armv7l" ] - then - ./test/test100/hello-armv7l.sh - mv test/results/test100-armv7l-binary bin/M2-Planet - fi - -else -[ -z "${CC+x}" ] && export CC=gcc -[ -z "${CFLAGS+x}" ] && export CFLAGS=" -D_GNU_SOURCE -O0 -std=c99 -ggdb" - -${CC} ${CFLAGS} \ - functions/match.c \ - functions/in_set.c \ - functions/numerate_number.c \ - functions/file_print.c \ - functions/number_pack.c \ - functions/string.c \ - cc_reader.c \ - cc_strings.c \ - cc_types.c \ - cc_core.c \ - cc.c \ - cc.h \ - gcc_req.h \ - -o bin/M2-Planet || exit 5 -fi - -exit 0 diff --git a/test/test100/proof.answer b/test/test100/proof.answer index 35aac0a..a7c413b 100644 --- a/test/test100/proof.answer +++ b/test/test100/proof.answer @@ -1 +1 @@ -cdfe50b2c9eac325f228fce9146358df4ef672f030cf936506a445555716cf89 test/test100/proof +77224b14932a67cddb5e21c3ba1f7a1604ce48b2a63792791eb48fbb76110053 test/test100/proof