commit 7ba972cc2abea4cb7399b463d22f5dae705d2aa6
Author:     Roberto E. Vargas Caballero <[email protected]>
AuthorDate: Mon Sep 14 16:03:33 2015 +0200
Commit:     Roberto E. Vargas Caballero <[email protected]>
CommitDate: Mon Sep 14 16:21:42 2015 +0200

    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.

diff --git a/cc1/cc1.h b/cc1/cc1.h
index addbea9..3d0d427 100644
--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -52,7 +52,7 @@ struct type {
        } p;
        union {
                unsigned char rank;     /* convertion rank */
-               short elem;             /* number of type parameters */
+               TINT elem;             /* number of type parameters */
        } n;
 };
 
diff --git a/cc1/expr.c b/cc1/expr.c
index 6d3ed17..f66b08a 100644
--- a/cc1/expr.c
+++ b/cc1/expr.c
@@ -978,13 +978,95 @@ condexpr(void)
        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 @@ initializer(Symbol *sym, Type *tp, int nelem)
        /* 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 @@ initializer(Symbol *sym, Type *tp, int nelem)
        } 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);

Reply via email to