commit 4730c12530c7db4e61d812e9f45d631d7bc1bdfe
Author:     Roberto E. Vargas Caballero <[email protected]>
AuthorDate: Thu Sep 10 18:16:05 2015 +0200
Commit:     Roberto E. Vargas Caballero <[email protected]>
CommitDate: Thu Sep 10 18:16:05 2015 +0200

    Add initializer to static objects
    
    Static objects cannot be initialized by assignations, so we need define
    the initializer with other syntax.

diff --git a/cc1/cc1.h b/cc1/cc1.h
index ed6c670..da438c6 100644
--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -158,7 +158,8 @@ enum {
        ISLOCAL    =     512,
        ISEMITTED  =    1024,
        ISDEFINED  =    2048,
-       ISSTRING   =    4096
+       ISSTRING   =    4096,
+       ISTYPEDEF =     8192
 };
 
 
diff --git a/cc1/code.c b/cc1/code.c
index 92d5217..cd54267 100644
--- a/cc1/code.c
+++ b/cc1/code.c
@@ -16,7 +16,8 @@ static void emitbin(unsigned, void *),
             emitsymid(unsigned, void *),
             emittext(unsigned, void *),
             emitfun(unsigned, void *),
-            emitdcl(unsigned, void *);
+            emitdcl(unsigned, void *),
+            emitinit(unsigned, void *);
 
 char *optxt[] = {
        [OADD] = "+",
@@ -39,7 +40,6 @@ char *optxt[] = {
        [OBXOR]  = "^",
        [OBOR] = "|",
        [OASSIGN] = ":",
-       [OINIT] = ":",
        [OA_MUL] = ":*",
        [OA_DIV] = ":/",
        [OA_MOD] = ":%",
@@ -92,7 +92,6 @@ void (*opcode[])(unsigned, void *) = {
        [OBXOR]  = emitbin,
        [OBOR] = emitbin,
        [OASSIGN] = emitbin,
-       [OINIT] = emitbin,
        [OA_MUL] = emitbin,
        [OA_DIV] = emitbin,
        [OA_MOD] = emitbin,
@@ -129,7 +128,8 @@ void (*opcode[])(unsigned, void *) = {
        [OSWITCH] = emitswitch,
        [OSWITCHT] = emitswitcht,
        [OPAR] = emitbin,
-       [OCALL] = emitbin
+       [OCALL] = emitbin,
+       [OINIT] = emitinit
 };
 
 void
@@ -284,6 +284,18 @@ emittype(Type *tp)
 }
 
 static void
+emitinit(unsigned op, void *arg)
+{
+       Node *np = arg;
+
+       puts("(");
+       emitexp(OEXPR, np->right);
+       puts(")");
+       np->right = NULL;
+       freetree(np);
+}
+
+static void
 emitdcl(unsigned op, void *arg)
 {
        Symbol *sym = arg;
diff --git a/cc1/decl.c b/cc1/decl.c
index a7bd932..dd67a92 100644
--- a/cc1/decl.c
+++ b/cc1/decl.c
@@ -661,6 +661,7 @@ identifier(struct decl *dcl)
                        flags |= (curctx == GLOBALCTX) ? ISPRIVATE : ISLOCAL;
                        break;
                case TYPEDEF:
+                       flags |= ISTYPEDEF;
                        sym->token = TYPEIDEN;
                        break;
                }
@@ -668,8 +669,6 @@ identifier(struct decl *dcl)
        }
 
        /* TODO: disallow initializators in functions */
-       /* TODO: check if typedef has initializer */
-       /* TODO: check if the variable is extern and has initializer */
        if (sym->token == IDEN && sym->type->op != FTN)
                emit(ODECL, sym);
        if (accept('='))
@@ -732,7 +731,7 @@ decl(void)
                case TYPE:
                case TQUALIFIER:
                case SCLASS:
-                       if (sym->token == TYPEIDEN)
+                       if (sym->flags & ISTYPEDEF)
                                errorp("function definition declared 
'typedef'");
                        if (sym->flags & ISDEFINED)
                                errorp("redefinition of '%s'", sym->name);
diff --git a/cc1/expr.c b/cc1/expr.c
index 58534dc..ea7916e 100644
--- a/cc1/expr.c
+++ b/cc1/expr.c
@@ -980,24 +980,46 @@ condexpr(void)
 
 /* TODO: check correctness of the initializator  */
 /* TODO: emit initializer */
+static void
+initlist(void)
+{
+       Node *np;
+
+       if (yytoken == '}')
+               return;
+
+       do {
+               if (accept('{'))
+                       initlist();
+               assign();
+       } while (accept(','));
+
+       expect('}');
+}
+
 void
 initializer(Symbol *sym)
 {
        Node *np;
+       int flags = sym->flags;
 
        if (accept('{')) {
-               do {
-                       if (yytoken == '}')
-                               break;
-                       initializer(sym);
-               } while (accept(','));
-
-               expect('}');
-               return;
-       }
-       np = expr();
-       if ((sym->flags & ISLOCAL) == 0) {
-               emit(OEXPR, assignop(OINIT, varnode(sym), np));
+               initlist();
                return;
        }
+       np = assignop(OINIT, varnode(sym), assign());
+
+       if ((flags & (ISLOCAL|ISPRIVATE|ISGLOBAL)) != 0) {
+               if (!np->right->constant)
+                       errorp("initializer element is not constant");
+               emit(OINIT, np);
+       } 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