ref: 38c240c4f09858a4ce71d70ee7fe16e7df7c9bff
parent: ba98fe9738f78620b50c8351d46c95f923052dd7
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Sun Jan 17 06:59:04 EST 2016
Move initializer code to a new file This code is going to be too long, and it is not totally related to expressions, so it is better to create a new file.
--- a/cc1/Makefile
+++ b/cc1/Makefile
@@ -3,7 +3,7 @@
include ../config.mk
OBJS = types.o decl.o lex.o error.o symbol.o main.o expr.o \
- code.o stmt.o cpp.o fold.o
+ code.o stmt.o cpp.o fold.o init.o
all: cc1
--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -374,13 +374,14 @@
extern TUINT ones(int nbytes);
/* expr.c */
-extern Node *expr(void), *negate(Node *np), *constexpr(void);
+extern Node *decay(Node *), *negate(Node *np), *assign(Node *np);;
extern Node *convert(Node *np, Type *tp1, char iscast);
-extern Node *iconstexpr(void), *condexpr(void);
+extern Node *iconstexpr(void), *condexpr(void), *expr(void);
extern bool isnodecmp(int op);
extern int negop(int op);
extern bool cmpnode(Node *np, TUINT val);
-extern Node *decay(Node *np);
+
+/* init.c */
extern void initializer(Symbol *sym, Type *tp, int nelem);
/* cpp.c */
--- a/cc1/decl.c
+++ b/cc1/decl.c
@@ -779,7 +779,7 @@
if (sym->token == IDEN && sym->type->op != FTN)
emit(ODECL, sym);
- if (accept('='))
+ if (yytoken == '=')
initializer(sym, sym->type, -1);
if (!(sym->flags & (ISGLOBAL|ISEXTERN)) && tp->op != FTN)
sym->flags |= ISDEFINED;
--- a/cc1/expr.c
+++ b/cc1/expr.c
@@ -629,8 +629,6 @@
return np;
}
-static Node *assign(void);
-
static Node *
arguments(Node *np)
{
@@ -659,7 +657,7 @@
toomany = 0;
do {
- arg = decay(assign());
+ arg = decay(assign(NULL));
argtype = *targs;
if (argtype == ellipsistype) {
n = 0;
@@ -1007,16 +1005,22 @@
return cond;
}
-static Node *
-assign(void)
+Node *
+assign(Node *np)
{
- Node *np, *(*fun)(char , Node *, Node *);
+ Node *(*fun)(char , Node *, Node *);
char op;
- np = ternary();
+ if (np) {
+ op = OINIT;
+ } else {
+ op = OASSIGN;
+ np = ternary();
+ }
+
for (;;) {
switch (yytoken) {
- case '=': op = OASSIGN; fun = assignop; break;
+ case '=': /* op = op; */; fun = assignop; break;
case MUL_EQ: op = OA_MUL; fun = arithmetic; break;
case DIV_EQ: op = OA_DIV; fun = arithmetic; break;
case MOD_EQ: op = OA_MOD; fun = integerop; break;
@@ -1031,7 +1035,7 @@
}
chklvalue(np);
next();
- np = (fun)(op, np, assign());
+ np = (fun)(op, np, assign(NULL));
}
}
@@ -1069,9 +1073,9 @@
{
Node *lp, *rp;
- lp = assign();
+ lp = assign(NULL);
while (accept(',')) {
- rp = assign();
+ rp = assign(NULL);
lp = node(OCOMMA, rp->type, lp, rp);
}
@@ -1087,177 +1091,4 @@
if (np->constant)
warn("conditional expression is constant");
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->aggreg)
- 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 toomany = 0;
- TINT n;
- 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) {
- if (!toomany)
- warn("excess elements in array initializer");
- toomany = 1;
- sym = NULL;
- }
- newtp = tp->type;
- break;
- case STRUCT:
- if (n >= tp->n.elem) {
- if (!toomany)
- warn("excess elements in struct initializer");
- toomany = 1;
- sym = NULL;
- } else {
- sym = tp->p.fields[n];
- newtp = sym->type;
- }
- break;
- default:
- newtp = tp;
- warn("braces around scalar initializer");
- if (n > 0) {
- if (!toomany)
- warn("excess elements in scalar initializer");
- toomany = 1;
- sym = NULL;
- }
- break;
- }
- initializer(sym, newtp, n);
- if (!accept(','))
- break;
- }
- expect('}');
-
- if (tp->op == ARY && !tp->defined) {
- tp->n.elem = n + 1;
- tp->defined = 1;
- }
-}
-
-void
-initializer(Symbol *sym, Type *tp, int nelem)
-{
- Node *np;
- int flags = sym->flags;
-
- if (tp->op == FTN)
- error("function '%s' is initialized like a variable", sym->name);
-
- if (accept('{')) {
- initlist(sym, tp);
- return;
- }
- np = assign();
-
- /* if !sym it means there are too much initializers */
- if (!sym)
- return;
- if (nelem >= 0)
- return;
-
- np = assignop(OINIT, varnode(sym), np);
-
- if (flags & ISDEFINED) {
- errorp("redeclaration of '%s'", sym->name);
- } else if ((flags & (ISGLOBAL|ISLOCAL|ISPRIVATE)) != 0) {
- if (!np->right->constant)
- errorp("initializer element is not constant");
- emit(OINIT, np);
- sym->flags |= ISDEFINED;
- } else if ((flags & (ISEXTERN|ISTYPEDEF)) != 0) {
- errorp("'%s' has both '%s' and initializer",
- sym->name, (flags&ISEXTERN) ? "extern" : "typedef");
- } else {
- np->op = OASSIGN;
- emit(OEXPR, np);
- }
}
--- /dev/null
+++ b/cc1/init.c
@@ -1,0 +1,184 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "../inc/cc.h"
+#include "../inc/sizes.h"
+#include "cc1.h"
+
+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->aggreg)
+ 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 toomany = 0;
+ TINT n;
+ 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) {
+ if (!toomany)
+ warn("excess elements in array initializer");
+ toomany = 1;
+ sym = NULL;
+ }
+ newtp = tp->type;
+ break;
+ case STRUCT:
+ if (n >= tp->n.elem) {
+ if (!toomany)
+ warn("excess elements in struct initializer");
+ toomany = 1;
+ sym = NULL;
+ } else {
+ sym = tp->p.fields[n];
+ newtp = sym->type;
+ }
+ break;
+ default:
+ newtp = tp;
+ warn("braces around scalar initializer");
+ if (n > 0) {
+ if (!toomany)
+ warn("excess elements in scalar initializer");
+ toomany = 1;
+ sym = NULL;
+ }
+ break;
+ }
+ initializer(sym, newtp, n);
+ if (!accept(','))
+ break;
+ }
+ expect('}');
+
+ if (tp->op == ARY && !tp->defined) {
+ tp->n.elem = n + 1;
+ tp->defined = 1;
+ }
+}
+
+extern Node *assign(Node *np);
+
+void
+initializer(Symbol *sym, Type *tp, int nelem)
+{
+ Node *np;
+ int flags = sym->flags;
+
+ if (tp->op == FTN)
+ errorp("function '%s' is initialized like a variable", sym->name);
+
+ switch (yytoken) {
+ case '{':
+ initlist(sym, tp); /* FIXME: This code is not complete */
+ return;
+ case '=':
+ np = assign(varnode(sym));
+ break;
+ }
+
+ /* FIXME: old code used in the recursive call
+ * if (!sym)
+ * return;
+ * if (nelem >= 0)
+ * return;
+ */
+
+ if (flags & ISDEFINED) {
+ errorp("redeclaration of '%s'", sym->name);
+ } else if ((flags & (ISGLOBAL|ISLOCAL|ISPRIVATE)) != 0) {
+ if (!np->right->constant)
+ errorp("initializer element is not constant");
+ emit(OINIT, np);
+ sym->flags |= ISDEFINED;
+ } else if ((flags & (ISEXTERN|ISTYPEDEF)) != 0) {
+ errorp("'%s' has both '%s' and initializer",
+ sym->name, (flags&ISEXTERN) ? "extern" : "typedef");
+ } else {
+ np->op = OASSIGN;
+ emit(OEXPR, np);
+ }
+}