scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit e6ef99231498cfcd683a5132b7de6f266e50444d
parent 3f775a9d7d5405a555e5746f3314884ace516a4c
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Mon, 18 Jan 2016 22:29:11 +0100

Add mkcompound()

This function takes an initializer structure and it creates
an array of expressions which will be used in the symbol
created for the compound literal.

Diffstat:
Mcc1/cc1.h | 14+++-----------
Mcc1/code.c | 6+-----
Mcc1/init.c | 145+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
3 files changed, 112 insertions(+), 53 deletions(-)

diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -17,7 +17,6 @@ typedef struct symbol Symbol; typedef struct caselist Caselist; typedef struct node Node; typedef struct input Input; -typedef struct init Init; struct limits { union { @@ -62,14 +61,6 @@ struct type { } n; }; -struct designator; - -struct init { - Type *type; - TUINT pos; - struct designator *head; -}; - struct symbol { char *name; Type *type; @@ -84,7 +75,7 @@ struct symbol { TFLOAT f; char *s; unsigned char token; - Init *init; + Node **init; Symbol **pars; } u; struct symbol *next; @@ -175,7 +166,8 @@ enum { ISEMITTED = 1024, ISDEFINED = 2048, ISSTRING = 4096, - ISTYPEDEF = 8192 + ISTYPEDEF = 8192, + ISINITLST = 16384 }; /* lexer mode, compiler or preprocessor directive */ diff --git a/cc1/code.c b/cc1/code.c @@ -291,13 +291,9 @@ emittype(Type *tp) static void emitinit(unsigned op, void *arg) { - Node *np = arg; - puts("("); - emitexp(OEXPR, np->right); + emitexp(OEXPR, arg); puts(")"); - np->right = NULL; - freetree(np); } static void diff --git a/cc1/init.c b/cc1/init.c @@ -1,18 +1,29 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include "../inc/cc.h" #include "../inc/sizes.h" #include "cc1.h" +typedef struct init Init; + struct designator { TINT pos; Node *expr; struct designator *next; }; +struct init { + Type *type; + size_t pos; + size_t max; + struct designator *tail; + struct designator *head; +}; + static TINT arydesig(Init *ip) @@ -63,10 +74,6 @@ designation(Init *ip) struct designator *dp; TINT (*fun)(Init *); - dp = xmalloc(sizeof(*dp)); - dp->next = ip->head; - ip->head = dp; - switch (yytoken) { case '[': fun = arydesig; break; case '.': fun = fielddesig; break; @@ -85,79 +92,144 @@ initialize(Type *tp) { Node *np; - np = (accept('{')) ? initlist(tp) : assign(); - if ((np = convert(decay(np), tp, 0)) == NULL) + np = (accept('{')) ? initlist(tp) : decay(assign()); + if ((np = convert(np, tp, 0)) == NULL) { errorp("incorrect initializer"); + np = constnode(zero); + } return np; } static Node * -initlist(Type *tp) +mkcompound(Init *ip) { - Init *ip; + Node **v, **p; + size_t n; + struct designator *dp, *next; Symbol *sym; + + n = ip->max; + if (n >= n * sizeof(*v)) { + errorp("compound literal too big"); + return constnode(zero); + } + n *= sizeof(*v); + v = memset(xmalloc(n), 0, n); + + for (dp = ip->head; dp; dp = next) { + p = &v[dp->pos]; + freetree(*p); + *p = dp->expr; + next = dp->next; + free(dp); + } + + sym = newsym(NS_IDEN); + sym->u.init = v; + sym->type = ip->type; + sym->flags |= ISINITLST; + + return constnode(sym); +} + +static void +newdesig(Init *ip, Node *np) +{ struct designator *dp; - int toomany = 0; - Type *newtp; - ip = xmalloc(sizeof(*ip)); - ip->head = NULL; - ip->pos = 0; - ip->type = tp; + if (ip->pos > ip->max) + ip->max = ip->pos; + + dp = xmalloc(sizeof(*dp)); + dp->pos = ip->pos; + dp->expr = np; + dp->next = NULL; + + if (ip->head == NULL) { + ip->head = ip->tail = dp; + } else { + ip->tail->next = dp; + ip->tail = dp; + } +} - if (accept('}')) - goto end_of_initializer; +static Node * +initlist(Type *tp) +{ + Init in; + int toomany = 0, outbound; + Type *newtp; + Node *np; - for (ip->pos = 1; ; ++ip->pos) { - designation(ip); + in.tail = in.head = NULL; + in.type = tp; + in.pos = 0; + in.max = 0; + + do { + if (yytoken == '}') + break; + outbound = 0; + designation(&in); switch (tp->op) { case ARY: - newtp = sym->type; - if (!tp->defined || ip->pos <= tp->n.elem) + newtp = tp->type; + if (!tp->defined || in.pos < tp->n.elem) break; if (!toomany) warn("excess elements in array initializer"); + outbound = 1; toomany = 1; break; + /* TODO: case UNION: */ case STRUCT: - if (ip->pos <= tp->n.elem) { - sym = tp->p.fields[ip->pos-1]; - newtp = sym->type; + if (in.pos < tp->n.elem) { + newtp = tp->p.fields[in.pos]->type; break; } newtp = inttype; if (!toomany) warn("excess elements in struct initializer"); toomany = 1; + outbound = 1; break; default: newtp = tp; warn("braces around scalar initializer"); - if (ip->pos == 1) + if (in.pos == 0) break; if (!toomany) warn("excess elements in scalar initializer"); toomany = 1; + outbound = 1; break; } - dp = ip->head; - dp->pos = ip->pos; - dp->expr = initialize(newtp); - if (!accept(',')) - break; - } + np = initialize(newtp); + if (outbound) + freetree(np); + else + newdesig(&in, np); + + if (++in.pos == 0) + errorp("compound literal too big"); + + } while (accept(',')); + expect('}'); -end_of_initializer: if (tp->op == ARY && !tp->defined) { - tp->n.elem = ip->pos; + tp->n.elem = in.pos; tp->defined = 1; } - sym = newsym(NS_IDEN); - sym->u.init = ip; - sym->type = tp; - return constnode(sym); + if (tp->op == ARY || tp->op == STRUCT) + in.max = tp->n.elem; + else if (in.max == 0) { + errorp("empty scalar initializer"); + return constnode(zero); + } + + return mkcompound(&in); } void @@ -168,7 +240,6 @@ initializer(Symbol *sym, Type *tp, int nelem) if (tp->op == FTN) errorp("function '%s' is initialized like a variable", sym->name); - np = initialize(tp); if (flags & ISDEFINED) {