ref: 7ba972cc2abea4cb7399b463d22f5dae705d2aa6
parent: ca4dc0e4231ef4fa8cd322fd21beb4a99e6a0fac
author: Roberto E. Vargas Caballero <[email protected]>
date: Mon Sep 14 12:03:33 EDT 2015
Add designated initializers syntax At this point we accept designated initializer but we are not emiting them. The reason is because we have to build a full tree with the information of the initializer list, and emit first the nested elements.
--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -52,7 +52,7 @@
} p;
union {
unsigned char rank; /* convertion rank */
- short elem; /* number of type parameters */
+ TINT elem; /* number of type parameters */
} n;
};
--- a/cc1/expr.c
+++ b/cc1/expr.c
@@ -978,13 +978,95 @@
return np;
}
+struct designator {
+ TINT pos;
+ struct designator *next;
+};
+
+static TINT
+arydesig(Type *tp)
+{
+ TINT npos;
+ Node *np;
+
+ if (tp->op != ARY)
+ errorp("array index in non-array initializer");
+ next();
+ np = iconstexpr();
+ npos = np->sym->u.i;
+ freetree(np);
+ expect(']');
+ return npos;
+}
+
+static TINT
+fielddesig(Type *tp)
+{
+ TINT npos;
+ int ons;
+ Symbol *sym, **p;
+
+ if (tp->op != STRUCT || tp->op != UNION)
+ errorp("field name not in record or union initializer");
+ ons = namespace;
+ namespace = tp->ns;
+ next();
+ namespace = ons;
+ if (yytoken != IDEN)
+ unexpected();
+ sym = yylval.sym;
+ if ((sym->flags & ISDECLARED) == 0) {
+ errorp(" unknown field '%s' specified in initializer",
+ sym->name);
+ return 0;
+ }
+ for (p = tp->p.fields; *p != sym; ++p)
+ /* nothing */;
+ return p - tp->p.fields;
+}
+
+static struct designator *
+designation(Type *tp)
+{
+ struct designator *des = NULL, *d;
+ TINT (*fun)(Type *);
+
+ for (;;) {
+ switch (yytoken) {
+ case '[': fun = arydesig; break;
+ case '.': fun = fielddesig; break;
+ default:
+ if (des)
+ expect('=');
+ return des;
+ }
+ d = xmalloc(sizeof(*d));
+ d->next = NULL;
+
+ if (!des) {
+ des = d;
+ } else {
+ des->next = d;
+ des = d;
+ }
+ des->pos = (*fun)(tp);
+ }
+}
+
static void
initlist(Symbol *sym, Type *tp)
{
+ struct designator *des;
int n, toomany = 0;
Type *newtp;
for (n = 0; ; ++n) {
+ if ((des = designation(tp)) == NULL) {
+ des = xmalloc(sizeof(*des));
+ des->pos = n;
+ } else {
+ n = des->pos;
+ }
switch (tp->op) {
case ARY:
if (tp->defined && n >= tp->n.elem && !toomany) {
@@ -1043,6 +1125,9 @@
/* if !sym it means there are too much initializers */
if (!sym)
return;
+ if (nelem >= 0)
+ return;
+
np = assignop(OINIT, varnode(sym), np);
if ((flags & (ISEXTERN|ISTYPEDEF)) != 0) {
@@ -1052,8 +1137,6 @@
} else if ((flags & (ISEXTERN|ISTYPEDEF)) != 0) {
errorp("'%s' has both '%s' and initializer",
sym->name, (flags&ISEXTERN) ? "extern" : "typedef");
- } else if (flags & ISFIELD) {
- ;
} else {
np->op = OASSIGN;
emit(OEXPR, np);