/* Copyright (C) 2016 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 . */ #include "cc.h" #include void line_error(); int numerate_string(char *a); /* Initialize default types */ void initialize_types() { if(AMD64 == Architecture) register_size = 8; else register_size = 4; /* Define void */ global_types = calloc(1, sizeof(struct type)); global_types->name = "void"; global_types->is_signed = FALSE; global_types->size = register_size; global_types->type = global_types; /* void* has the same properties as void */ global_types->indirect = global_types; /* Define UNis_signed LONG */ struct type* a = calloc(1, sizeof(struct type)); a->name = "SCM"; a->is_signed = FALSE; a->size = register_size; a->indirect = a; a->type = a; /* Define LONG */ struct type* b = calloc(1, sizeof(struct type)); b->name = "long"; b->is_signed = TRUE; b->size = register_size; b->indirect = b; b->type = b; /* Define UNSIGNED */ struct type* c = calloc(1, sizeof(struct type)); c->name = "unsigned"; c->is_signed = FALSE; c->size = register_size; c->type = c; /* unsigned* has the same properties as unsigned */ c->indirect = c; /* Define int */ struct type* d = calloc(1, sizeof(struct type)); d->name = "int"; d->is_signed = TRUE; d->size = register_size; /* int* has the same properties as int */ d->indirect = d; d->type = d; /* Define char* */ struct type* e = calloc(1, sizeof(struct type)); e->name = "char*"; e->is_signed = FALSE; e->size = register_size; e->type = e; /* Define char */ struct type* f = calloc(1, sizeof(struct type)); f->name = "char"; f->is_signed = FALSE; f->size = 1; f->type = f; /* Define char** */ struct type* g = calloc(1, sizeof(struct type)); g->name = "char**"; g->is_signed = FALSE; g->size = register_size; g->type = e; g->indirect = g; /*fix up indirects for chars */ f->indirect = e; e->indirect = g; /* Define FILE */ struct type* h = calloc(1, sizeof(struct type)); h->name = "FILE"; h->is_signed = FALSE; h->size = register_size; h->type = h; /* FILE* has the same properties as FILE */ h->indirect = h; /* Define FUNCTION */ struct type* i = calloc(1, sizeof(struct type)); i->name = "FUNCTION"; i->is_signed = FALSE; i->size = register_size; i->type = i; /* FUNCTION* has the same properties as FUNCTION */ i->indirect = i; /* Primitives mes.c wanted */ struct type* j = calloc(1, sizeof(struct type)); j->name = "size_t"; j->is_signed = FALSE; j->size = register_size; j->indirect = j; struct type* k = calloc(1, sizeof(struct type)); k->name = "ssize_t"; k->is_signed = FALSE; k->size = register_size; k->indirect = k; /* Finalize type list */ j->next = k; i->next = j; h->next = i; g->next = h; f->next = g; d->next = f; c->next = d; b->next = c; a->next = b; global_types->next = a; prim_types = global_types; } struct type* lookup_type(char* s, struct type* start) { struct type* i; for(i = start; NULL != i; i = i->next) { if(match(i->name, s)) { return i; } } return NULL; } struct type* lookup_member(struct type* parent, char* name) { struct type* i; for(i = parent->members; NULL != i; i = i->members) { if(match(i->name, name)) return i; } file_print("ERROR in lookup_member ", stderr); file_print(parent->name, stderr); file_print("->", stderr); file_print(global_token->s, stderr); file_print(" does not exist\n", stderr); line_error(); file_print("\n", stderr); exit(EXIT_FAILURE); } struct type* type_name(); void require_match(char* message, char* required); int member_size; struct type* build_member(struct type* last, int offset) { struct type* i = calloc(1, sizeof(struct type)); i->members = last; i->offset = offset; struct type* member_type = type_name(); i->type = member_type; i->name = global_token->s; global_token = global_token->next; /* Check to see if array */ if(match( "[", global_token->s)) { global_token = global_token->next; i->size = member_type->type->size * numerate_string(global_token->s); global_token = global_token->next; require_match("Struct only supports [num] form\n", "]"); } else { i->size = member_type->size; } member_size = i->size; return i; } struct type* build_union(struct type* last, int offset) { int size = 0; global_token = global_token->next; require_match("ERROR in build_union\nMissing {\n", "{"); while('}' != global_token->s[0]) { last = build_member(last, offset); if(member_size > size) { size = member_size; } require_match("ERROR in build_union\nMissing ;\n", ";"); } member_size = size; global_token = global_token->next; return last; } void create_struct() { int offset = 0; member_size = 0; struct type* head = calloc(1, sizeof(struct type)); struct type* i = calloc(1, sizeof(struct type)); head->name = global_token->s; i->name = global_token->s; head->indirect = i; i->indirect = head; head->next = global_types; global_types = head; global_token = global_token->next; i->size = register_size; require_match("ERROR in create_struct\n Missing {\n", "{"); struct type* last = NULL; while('}' != global_token->s[0]) { if(match(global_token->s, "union")) { last = build_union(last, offset); } else { last = build_member(last, offset); } offset = offset + member_size; require_match("ERROR in create_struct\n Missing ;\n", ";"); } global_token = global_token->next; require_match("ERROR in create_struct\n Missing ;\n", ";"); head->size = offset; head->members = last; i->members = last; } struct type* type_name() { struct type* ret; if(match("struct", global_token->s)) { global_token = global_token->next; ret = lookup_type(global_token->s, global_types); if(NULL == ret) { create_struct(); return NULL; } } else { ret = lookup_type(global_token->s, global_types); if(NULL == ret) { file_print("Unknown type ", stderr); file_print(global_token->s, stderr); file_print("\n", stderr); line_error(); exit(EXIT_FAILURE); } } global_token = global_token->next; if(match("const", global_token->s)) { global_token = global_token->next; } while(global_token->s[0] == '*') { ret = ret->indirect; global_token = global_token->next; } return ret; }