[hackers] [scc] Add initializer to static objects || Roberto E. Vargas Caballero

From: <git_AT_suckless.org>
Date: Thu, 10 Sep 2015 18:19:11 +0200 (CEST)

commit 4730c12530c7db4e61d812e9f45d631d7bc1bdfe
Author: Roberto E. Vargas Caballero <k0ga_AT_shike2.com>
AuthorDate: Thu Sep 10 18:16:05 2015 +0200
Commit: Roberto E. Vargas Caballero <k0ga_AT_shike2.com>
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
_AT_@ -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
_AT_@ -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] = "+",
_AT_@ -39,7 +40,6 @@ char *optxt[] = {
         [OBXOR] = "^",
         [OBOR] = "|",
         [OASSIGN] = ":",
- [OINIT] = ":",
         [OA_MUL] = ":*",
         [OA_DIV] = ":/",
         [OA_MOD] = ":%",
_AT_@ -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,
_AT_@ -129,7 +128,8 @@ void (*opcode[])(unsigned, void *) = {
         [OSWITCH] = emitswitch,
         [OSWITCHT] = emitswitcht,
         [OPAR] = emitbin,
- [OCALL] = emitbin
+ [OCALL] = emitbin,
+ [OINIT] = emitinit
 };
 
 void
_AT_@ -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
_AT_@ -661,6 +661,7 @@ identifier(struct decl *dcl)
                         flags |= (curctx == GLOBALCTX) ? ISPRIVATE : ISLOCAL;
                         break;
                 case TYPEDEF:
+ flags |= ISTYPEDEF;
                         sym->token = TYPEIDEN;
                         break;
                 }
_AT_@ -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('='))
_AT_@ -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
_AT_@ -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);
+ }
 }
Received on Thu Sep 10 2015 - 18:19:11 CEST

This archive was generated by hypermail 2.3.0 : Thu Sep 10 2015 - 18:24:12 CEST