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:
M | cc1/cc1.h | | | 14 | +++----------- |
M | cc1/code.c | | | 6 | +----- |
M | cc1/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) {