2018-01-25 01:00:22 +00:00
|
|
|
/* Copyright (C) 2016 Jeremiah Orians
|
2020-02-01 20:23:49 +00:00
|
|
|
* Copyright (C) 2020 deesix <deesix@tuta.io>
|
2018-10-18 00:27:06 +01:00
|
|
|
* This file is part of M2-Planet.
|
2018-01-25 01:00:22 +00:00
|
|
|
*
|
2018-10-18 00:27:06 +01:00
|
|
|
* M2-Planet is free software: you can redistribute it and/or modify
|
2018-01-25 01:00:22 +00:00
|
|
|
* 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.
|
|
|
|
*
|
2018-10-18 00:27:06 +01:00
|
|
|
* M2-Planet is distributed in the hope that it will be useful,
|
2018-01-25 01:00:22 +00:00
|
|
|
* 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
|
2018-10-18 00:27:06 +01:00
|
|
|
* along with M2-Planet. If not, see <http://www.gnu.org/licenses/>.
|
2018-01-25 01:00:22 +00:00
|
|
|
*/
|
|
|
|
#include "cc.h"
|
2020-01-22 23:03:28 +00:00
|
|
|
|
|
|
|
/* Imported functions */
|
2021-04-04 03:41:52 +01:00
|
|
|
int strtoint(char *a);
|
2020-01-22 23:03:28 +00:00
|
|
|
void line_error();
|
|
|
|
void require(int bool, char* error);
|
2018-01-25 01:00:22 +00:00
|
|
|
|
2020-12-28 02:51:46 +00:00
|
|
|
/* enable easy primitive extension */
|
|
|
|
struct type* add_primitive(struct type* a)
|
|
|
|
{
|
|
|
|
if(NULL == prim_types) return a;
|
|
|
|
struct type* i = prim_types;
|
|
|
|
while(NULL != i->next)
|
|
|
|
{
|
|
|
|
i = i->next;
|
|
|
|
}
|
|
|
|
i->next = a;
|
|
|
|
|
|
|
|
return prim_types;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* enable easy primitive creation */
|
|
|
|
struct type* new_primitive(char* name0, char* name1, char* name2, int size, int sign)
|
|
|
|
{
|
|
|
|
/* Create type** */
|
|
|
|
struct type* a = calloc(1, sizeof(struct type));
|
|
|
|
require(NULL != a, "Exhusted memory while declaring new primitive**\n");
|
|
|
|
a->name = name2;
|
|
|
|
a->size = register_size;
|
|
|
|
a->indirect = a;
|
|
|
|
a->is_signed = sign;
|
|
|
|
|
|
|
|
/* Create type* */
|
|
|
|
struct type* b = calloc(1, sizeof(struct type));
|
|
|
|
require(NULL != b, "Exhusted memory while declaring new primitive*\n");
|
|
|
|
b->name = name1;
|
|
|
|
b->size = register_size;
|
|
|
|
b->is_signed = sign;
|
|
|
|
b->indirect = a;
|
|
|
|
b->type = b;
|
|
|
|
a->type = b;
|
|
|
|
|
|
|
|
struct type* r = calloc(1, sizeof(struct type));
|
|
|
|
require(NULL != r, "Exhusted memory while declaring new primitive\n");
|
|
|
|
r->name = name0;
|
|
|
|
r->size = size;
|
|
|
|
r->is_signed = sign;
|
|
|
|
r->indirect = b;
|
|
|
|
r->type = r;
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2018-01-25 01:00:22 +00:00
|
|
|
/* Initialize default types */
|
|
|
|
void initialize_types()
|
|
|
|
{
|
2020-02-01 20:23:49 +00:00
|
|
|
if(AMD64 == Architecture || AARCH64 == Architecture) register_size = 8;
|
2019-04-18 01:19:17 +01:00
|
|
|
else register_size = 4;
|
|
|
|
|
2018-01-25 01:00:22 +00:00
|
|
|
/* Define void */
|
2020-12-28 02:51:46 +00:00
|
|
|
struct type* hold = new_primitive("void", "void*", "void**", register_size, FALSE);
|
|
|
|
prim_types = add_primitive(hold);
|
2018-01-25 01:00:22 +00:00
|
|
|
|
2020-01-25 19:15:45 +00:00
|
|
|
/* Define unsigned LONG */
|
2021-01-01 20:55:34 +00:00
|
|
|
hold = new_primitive("SCM","SCM*", "SCM**", register_size, FALSE);
|
2020-12-28 02:51:46 +00:00
|
|
|
prim_types = add_primitive(hold);
|
2018-01-25 01:00:22 +00:00
|
|
|
|
2019-10-27 02:45:02 +00:00
|
|
|
/* Define LONG */
|
2020-12-28 02:51:46 +00:00
|
|
|
hold = new_primitive("long", "long*", "long**", register_size, TRUE);
|
|
|
|
prim_types = add_primitive(hold);
|
2018-01-25 01:00:22 +00:00
|
|
|
|
2019-10-27 02:45:02 +00:00
|
|
|
/* Define UNSIGNED */
|
2020-12-28 02:51:46 +00:00
|
|
|
hold = new_primitive("unsigned", "unsigned*", "unsigned**",register_size, FALSE);
|
|
|
|
prim_types = add_primitive(hold);
|
2018-01-25 01:00:22 +00:00
|
|
|
|
2019-10-27 02:45:02 +00:00
|
|
|
/* Define int */
|
2020-12-31 14:53:05 +00:00
|
|
|
integer = new_primitive("int", "int*", "int**", register_size, TRUE);
|
|
|
|
prim_types = add_primitive(integer);
|
2018-05-03 01:56:44 +01:00
|
|
|
|
2019-10-27 02:45:02 +00:00
|
|
|
/* Define char */
|
2020-12-28 02:51:46 +00:00
|
|
|
hold = new_primitive("char", "char*", "char**", 1, TRUE);
|
|
|
|
prim_types = add_primitive(hold);
|
2019-10-27 02:45:02 +00:00
|
|
|
|
|
|
|
/* Define FUNCTION */
|
2020-12-28 02:51:46 +00:00
|
|
|
hold = new_primitive("FUNCTION", "FUNCTION*", "FUNCTION**", register_size, FALSE);
|
|
|
|
prim_types = add_primitive(hold);
|
2019-10-26 20:40:35 +01:00
|
|
|
|
2021-01-03 03:00:02 +00:00
|
|
|
if(BOOTSTRAP_MODE)
|
|
|
|
{
|
|
|
|
/* Define FILE */
|
|
|
|
hold = new_primitive("FILE", "FILE*", "FILE**", register_size, TRUE);
|
|
|
|
prim_types = add_primitive(hold);
|
2020-12-28 02:51:46 +00:00
|
|
|
|
2021-01-03 03:00:02 +00:00
|
|
|
/* Primitives mes.c wanted */
|
|
|
|
hold = new_primitive("size_t", "size_t*", "size_t**", register_size, FALSE);
|
|
|
|
prim_types = add_primitive(hold);
|
|
|
|
|
|
|
|
hold = new_primitive("ssize_t", "ssize_t*", "ssize_t**", register_size, FALSE);
|
|
|
|
prim_types = add_primitive(hold);
|
|
|
|
}
|
2020-12-28 02:51:46 +00:00
|
|
|
|
|
|
|
global_types = prim_types;
|
2018-01-25 01:00:22 +00:00
|
|
|
}
|
2018-02-01 04:14:40 +00:00
|
|
|
|
2018-08-16 17:01:55 +01:00
|
|
|
struct type* lookup_type(char* s, struct type* start)
|
2018-02-01 04:14:40 +00:00
|
|
|
{
|
|
|
|
struct type* i;
|
2018-08-16 17:01:55 +01:00
|
|
|
for(i = start; NULL != i; i = i->next)
|
2018-02-01 04:14:40 +00:00
|
|
|
{
|
|
|
|
if(match(i->name, s))
|
|
|
|
{
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-08-26 21:34:31 +01:00
|
|
|
struct type* lookup_member(struct type* parent, char* name)
|
|
|
|
{
|
|
|
|
struct type* i;
|
2020-01-22 23:03:28 +00:00
|
|
|
require(NULL != parent, "Not a valid struct type\n");
|
2018-08-26 21:34:31 +01:00
|
|
|
for(i = parent->members; NULL != i; i = i->members)
|
|
|
|
{
|
|
|
|
if(match(i->name, name)) return i;
|
|
|
|
}
|
|
|
|
|
2021-04-03 23:56:55 +01:00
|
|
|
fputs("ERROR in lookup_member ", stderr);
|
|
|
|
fputs(parent->name, stderr);
|
|
|
|
fputs("->", stderr);
|
|
|
|
fputs(global_token->s, stderr);
|
|
|
|
fputs(" does not exist\n", stderr);
|
2018-08-26 21:34:31 +01:00
|
|
|
line_error();
|
2021-04-03 23:56:55 +01:00
|
|
|
fputs("\n", stderr);
|
2018-08-26 21:34:31 +01:00
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
2018-02-01 04:14:40 +00:00
|
|
|
struct type* type_name();
|
|
|
|
void require_match(char* message, char* required);
|
2018-04-27 20:57:48 +01:00
|
|
|
|
|
|
|
int member_size;
|
|
|
|
struct type* build_member(struct type* last, int offset)
|
|
|
|
{
|
|
|
|
struct type* i = calloc(1, sizeof(struct type));
|
2020-01-25 19:15:45 +00:00
|
|
|
require(NULL != i, "Exhusted memory while building a struct member\n");
|
2019-06-20 02:43:34 +01:00
|
|
|
i->members = last;
|
|
|
|
i->offset = offset;
|
|
|
|
|
|
|
|
struct type* member_type = type_name();
|
2020-01-22 23:03:28 +00:00
|
|
|
require(NULL != member_type, "struct member type can not be invalid\n");
|
2019-06-20 02:43:34 +01:00
|
|
|
i->type = member_type;
|
2018-04-27 20:57:48 +01:00
|
|
|
i->name = global_token->s;
|
2018-07-20 03:33:02 +01:00
|
|
|
global_token = global_token->next;
|
2020-01-22 23:03:28 +00:00
|
|
|
require(NULL != global_token, "struct member can not be EOF terminated\n");
|
2018-07-20 03:33:02 +01:00
|
|
|
|
|
|
|
/* Check to see if array */
|
|
|
|
if(match( "[", global_token->s))
|
|
|
|
{
|
|
|
|
global_token = global_token->next;
|
2020-01-22 23:03:28 +00:00
|
|
|
require(NULL != global_token, "struct member arrays can not be EOF sized\n");
|
2021-04-04 03:41:52 +01:00
|
|
|
i->size = member_type->type->size * strtoint(global_token->s);
|
2019-12-19 00:43:28 +00:00
|
|
|
if(0 == i->size)
|
|
|
|
{
|
2021-04-03 23:56:55 +01:00
|
|
|
fputs("Struct only supports [num] form\n", stderr);
|
2019-12-19 00:43:28 +00:00
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2018-07-20 03:33:02 +01:00
|
|
|
global_token = global_token->next;
|
|
|
|
require_match("Struct only supports [num] form\n", "]");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
i->size = member_type->size;
|
|
|
|
}
|
|
|
|
member_size = i->size;
|
2019-06-20 02:43:34 +01:00
|
|
|
|
2018-04-27 20:57:48 +01:00
|
|
|
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", ";");
|
2020-01-22 23:03:28 +00:00
|
|
|
require(NULL != global_token, "Unterminated union\n");
|
2018-04-27 20:57:48 +01:00
|
|
|
}
|
|
|
|
member_size = size;
|
2018-07-20 03:33:02 +01:00
|
|
|
global_token = global_token->next;
|
2018-04-27 20:57:48 +01:00
|
|
|
return last;
|
|
|
|
}
|
|
|
|
|
2018-02-01 04:14:40 +00:00
|
|
|
void create_struct()
|
|
|
|
{
|
|
|
|
int offset = 0;
|
2018-08-12 18:11:02 +01:00
|
|
|
member_size = 0;
|
2018-02-01 04:14:40 +00:00
|
|
|
struct type* head = calloc(1, sizeof(struct type));
|
2020-01-25 19:15:45 +00:00
|
|
|
require(NULL != head, "Exhusted memory while creating a struct\n");
|
2018-02-01 04:14:40 +00:00
|
|
|
struct type* i = calloc(1, sizeof(struct type));
|
2020-01-25 19:15:45 +00:00
|
|
|
require(NULL != i, "Exhusted memory while creating a struct indirection\n");
|
2018-02-01 04:14:40 +00:00
|
|
|
head->name = global_token->s;
|
2019-12-23 11:39:45 +00:00
|
|
|
head->type = head;
|
2018-02-01 04:14:40 +00:00
|
|
|
i->name = global_token->s;
|
2019-12-23 11:39:45 +00:00
|
|
|
i->type = i;
|
2018-02-01 04:14:40 +00:00
|
|
|
head->indirect = i;
|
|
|
|
i->indirect = head;
|
|
|
|
head->next = global_types;
|
|
|
|
global_types = head;
|
|
|
|
global_token = global_token->next;
|
2019-04-19 22:43:59 +01:00
|
|
|
i->size = register_size;
|
2018-07-20 03:33:02 +01:00
|
|
|
require_match("ERROR in create_struct\n Missing {\n", "{");
|
2018-02-01 04:14:40 +00:00
|
|
|
struct type* last = NULL;
|
|
|
|
while('}' != global_token->s[0])
|
|
|
|
{
|
2018-04-27 20:57:48 +01:00
|
|
|
if(match(global_token->s, "union"))
|
|
|
|
{
|
|
|
|
last = build_union(last, offset);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
last = build_member(last, offset);
|
|
|
|
}
|
|
|
|
offset = offset + member_size;
|
2018-07-20 03:33:02 +01:00
|
|
|
require_match("ERROR in create_struct\n Missing ;\n", ";");
|
2020-01-22 23:03:28 +00:00
|
|
|
require(NULL != global_token, "Unterminated struct\n");
|
2018-02-01 04:14:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
global_token = global_token->next;
|
2018-07-20 03:33:02 +01:00
|
|
|
require_match("ERROR in create_struct\n Missing ;\n", ";");
|
2018-02-01 04:14:40 +00:00
|
|
|
|
|
|
|
head->size = offset;
|
|
|
|
head->members = last;
|
2018-08-12 18:11:02 +01:00
|
|
|
i->members = last;
|
2018-02-01 04:14:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct type* type_name()
|
|
|
|
{
|
2019-06-04 02:01:14 +01:00
|
|
|
struct type* ret;
|
2018-02-01 04:14:40 +00:00
|
|
|
|
2020-01-22 23:03:28 +00:00
|
|
|
require(NULL != global_token, "Recieved EOF instead of type name\n");
|
2021-05-02 14:46:04 +01:00
|
|
|
|
|
|
|
if(match("extern", global_token->s))
|
|
|
|
{
|
|
|
|
global_token = global_token->next;
|
|
|
|
require(NULL != global_token, "unfinished type definition in extern\n");
|
|
|
|
}
|
|
|
|
|
2019-06-04 02:01:14 +01:00
|
|
|
if(match("struct", global_token->s))
|
2018-02-01 04:14:40 +00:00
|
|
|
{
|
|
|
|
global_token = global_token->next;
|
2020-01-22 23:03:28 +00:00
|
|
|
require(NULL != global_token, "structs can not have a EOF type name\n");
|
2019-06-04 02:01:14 +01:00
|
|
|
ret = lookup_type(global_token->s, global_types);
|
|
|
|
if(NULL == ret)
|
|
|
|
{
|
|
|
|
create_struct();
|
|
|
|
return NULL;
|
|
|
|
}
|
2018-02-01 04:14:40 +00:00
|
|
|
}
|
2019-06-04 02:01:14 +01:00
|
|
|
else
|
2018-02-01 04:14:40 +00:00
|
|
|
{
|
2019-06-04 02:01:14 +01:00
|
|
|
ret = lookup_type(global_token->s, global_types);
|
|
|
|
if(NULL == ret)
|
|
|
|
{
|
2021-04-03 23:56:55 +01:00
|
|
|
fputs("Unknown type ", stderr);
|
|
|
|
fputs(global_token->s, stderr);
|
|
|
|
fputs("\n", stderr);
|
2019-06-04 02:01:14 +01:00
|
|
|
line_error();
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2018-02-01 04:14:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
global_token = global_token->next;
|
2020-01-22 23:03:28 +00:00
|
|
|
require(NULL != global_token, "unfinished type definition\n");
|
2018-02-01 04:14:40 +00:00
|
|
|
|
2019-10-26 20:40:35 +01:00
|
|
|
if(match("const", global_token->s))
|
|
|
|
{
|
|
|
|
global_token = global_token->next;
|
2020-01-22 23:03:28 +00:00
|
|
|
require(NULL != global_token, "unfinished type definition in const\n");
|
2019-10-26 20:40:35 +01:00
|
|
|
}
|
|
|
|
|
2018-02-01 04:14:40 +00:00
|
|
|
while(global_token->s[0] == '*')
|
|
|
|
{
|
|
|
|
ret = ret->indirect;
|
|
|
|
global_token = global_token->next;
|
2020-01-22 23:03:28 +00:00
|
|
|
require(NULL != global_token, "unfinished type definition in indirection\n");
|
2018-02-01 04:14:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2021-01-03 03:00:02 +00:00
|
|
|
|
|
|
|
struct type* mirror_type(struct type* source, char* name)
|
|
|
|
{
|
|
|
|
struct type* head = calloc(1, sizeof(struct type));
|
|
|
|
require(NULL != head, "Exhusted memory while creating a struct\n");
|
|
|
|
struct type* i = calloc(1, sizeof(struct type));
|
|
|
|
require(NULL != i, "Exhusted memory while creating a struct indirection\n");
|
|
|
|
|
|
|
|
head->name = name;
|
|
|
|
i->name = name;
|
|
|
|
head->size = source->size;
|
|
|
|
i->size = source->indirect->size;
|
|
|
|
head->offset = source->offset;
|
|
|
|
i->offset = source->indirect->offset;
|
|
|
|
head->is_signed = source->is_signed;
|
|
|
|
i->is_signed = source->indirect->is_signed;
|
|
|
|
head->indirect = i;
|
|
|
|
i->indirect = head;
|
|
|
|
head->members = source->members;
|
|
|
|
i->members = source->indirect->members;
|
|
|
|
head->type = head;
|
|
|
|
i->type = i;
|
|
|
|
|
|
|
|
return head;
|
|
|
|
}
|