shithub: scc

Download patch

ref: 1814a219b69466faf91e429a2fa30671d4e9a26b
parent: 8a12777187779837b55e84a8cae473f2b41527cd
parent: 04eaf8bf9813e47819a823534b8b53e481088f77
author: Roberto E. Vargas Caballero <[email protected]>
date: Wed Jul 22 14:15:30 EDT 2015

Merge branch 'master' of ssh://suckless.org/gitrepos/scc

--- a/cc1/TODO
+++ b/cc1/TODO
@@ -2,7 +2,6 @@
 * Verify correctness in initializators
 * emit initializators
 * emit structures definition
-* Assign const expression value to enum members
 * Define array types based in the value of constant expressions
 * Rewrite decl.c and use only one decl function with a function pointer
   parameter
@@ -13,7 +12,6 @@
 * Rewrite error recovery code, and ensure correct state after recovery
 * Allow comparisions between pointers and 0
 * Implement function calls
-* Implement enum type in eqtype()
 * Parse correctly all integer and float constants
 * Add C99 features (almost all the new features of C99 are missed)
 * Add correct emit for any kind of constant
--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -130,7 +130,8 @@
 	ISFIELD    =      32,
 	ISPARAM    =      64,
 	ISEXTERN   =     128,
-	ISUSED     =     256
+	ISUSED     =     256,
+	ISCONSTANT =     512
 };
 
 
--- a/cc1/code.c
+++ b/cc1/code.c
@@ -124,15 +124,20 @@
 	[OSWITCH] = emitswitch
 };
 
-static Node *simple_sub(Node *), *simple_add(Node *);
+static Node *simple_add(Type *, Node *, Node *),
+            *simple_sub(Type *, Node *, Node *),
+            *simple_mul(Type *, Node *, Node *),
+            *simple_div(Type *, Node *, Node *),
+            *simple_mod(Type *, Node *, Node *);
 
-static Node *(*opsimp[])(Node *) = {
+static Node *(*opsimp[])(Type *, Node *, Node *) = {
 	[OADD] = simple_add,
-	[OSUB] = simple_sub
-
+	[OSUB] = simple_sub,
+	[OMUL] = simple_mul,
+	[ODIV] = simple_div,
+	[OMOD] = simple_mod
 };
 
-
 void
 freetree(Node *np)
 {
@@ -388,10 +393,8 @@
 }
 
 static Node *
-simple_add(Node *np)
+simple_mod(Type *tp, Node *lp, Node *rp)
 {
-	Node *lp = np->left, *rp = np->right;
-	Type *tp = np->type;
 	Symbol *sym, *ls = lp->sym, *rs = rp->sym;
 
 	switch (tp->op) {
@@ -398,22 +401,94 @@
 	case INT:
 		sym = newsym(NS_IDEN);
 		sym->type = tp;
+		if (tp->sign) {
+			if (rs->u.i == 0)
+				goto division_by_0;
+			sym->u.i = ls->u.i % rs->u.i;
+		} else {
+			if (rs->u.u == 0)
+				goto division_by_0;
+			sym->u.u = ls->u.u % rs->u.u;
+		}
+		return constnode(sym);
+	default:
+		return NULL;
+	}
+
+division_by_0:
+	warn("division by 0");
+	return NULL;
+}
+
+static Node *
+simple_div(Type *tp, Node *lp, Node *rp)
+{
+	Symbol *sym, *ls = lp->sym, *rs = rp->sym;
+
+	switch (tp->op) {
+	case INT:
+		sym = newsym(NS_IDEN);
+		sym->type = tp;
+		if (tp->sign) {
+			if (rs->u.i == 0)
+				goto division_by_0;
+			sym->u.i = ls->u.i / rs->u.i;
+		} else {
+			if (rs->u.u == 0)
+				goto division_by_0;
+			sym->u.u = ls->u.u / rs->u.u;
+		}
+		return constnode(sym);
+	default:
+		return NULL;
+	}
+
+division_by_0:
+	warn("division by 0");
+	return NULL;
+}
+
+static Node *
+simple_mul(Type *tp, Node *lp, Node *rp)
+{
+	Symbol *sym, *ls = lp->sym, *rs = rp->sym;
+
+	switch (tp->op) {
+	case INT:
+		sym = newsym(NS_IDEN);
+		sym->type = tp;
 		if (tp->sign)
+			sym->u.i = ls->u.i * rs->u.i;
+		else
+			sym->u.u = ls->u.u * rs->u.u;
+		return constnode(sym);
+	default:
+		return NULL;
+	}
+}
+
+static Node *
+simple_add(Type *tp, Node *lp, Node *rp)
+{
+	Symbol *sym, *ls = lp->sym, *rs = rp->sym;
+
+	switch (tp->op) {
+	case INT:
+		sym = newsym(NS_IDEN);
+		sym->type = tp;
+		if (tp->sign)
 			sym->u.i = ls->u.i + rs->u.i;
 		else
 			sym->u.u = ls->u.u + rs->u.u;
-		freetree(np);
 		return constnode(sym);
 	default:
-		return np;
+		return NULL;
 	}
 }
 
 static Node *
-simple_sub(Node *np)
+simple_sub(Type *tp, Node *lp, Node *rp)
 {
-	Node *lp = np->left, *rp = np->right;
-	Type *tp = np->type;
 	Symbol *sym, *ls = lp->sym, *rs = rp->sym;
 
 	switch (tp->op) {
@@ -424,10 +499,9 @@
 			sym->u.i = ls->u.i - rs->u.i;
 		else
 			sym->u.u = ls->u.u - rs->u.u;
-		freetree(np);
 		return constnode(sym);
 	default:
-		return np;
+		return NULL;
 	}
 }
 
@@ -434,7 +508,14 @@
 Node *
 simplify(Node *np)
 {
-	if (!np->left->constant || !np->right->constant)
+	Node *new, *lp = np->left, *rp = np->right;
+
+	if (!lp->constant || !rp->constant)
 		return np;
-	return (*opsimp[np->op])(np);
+	new = (*opsimp[np->op])(np->type, lp, rp);
+	if (new) {
+		freetree(np);
+		np = new;
+	}
+	return np;
 }
--- a/cc1/decl.c
+++ b/cc1/decl.c
@@ -51,6 +51,7 @@
 	 * is the correct, that in this case should be int
 	 */
 	n = (np == NULL) ? 0 : np->sym->u.i;
+	freetree(np);
 
 	return queue(dp, ARY, n, NULL);
 }
@@ -215,11 +216,13 @@
 			switch (yylval.token) {
 			case ENUM:
 				dcl = enumdcl;
-				p = &type; break;
+				p = &type;
+				break;
 			case STRUCT:
 			case UNION:
 				dcl = structdcl;
-				p = &type; break;
+				p = &type;
+				break;
 			case VOID:
 			case BOOL:
 			case CHAR:
@@ -230,7 +233,8 @@
 				break;
 			case SIGNED:
 			case UNSIGNED:
-				p = &sign; break;
+				p = &sign;
+				break;
 			case LONG:
 				if (size == LONG) {
 					size = LLONG;
@@ -251,6 +255,7 @@
 			if (size || sign)
 				goto invalid_type;
 			tp = (*dcl)();
+			goto return_type;
 		} else {
 			next();
 		}
@@ -290,7 +295,7 @@
 newtag(void)
 {
 	Symbol *sym;
-	unsigned tag = yylval.token;
+	int op, tag = yylval.token;
 	static unsigned ns = NS_STRUCTS;
 
 	setnamespace(NS_TAG);
@@ -299,6 +304,7 @@
 	case IDEN:
 	case TYPEIDEN:
 		sym = yylval.sym;
+		install(NS_TAG);
 		next();
 		break;
 	default:
@@ -313,8 +319,8 @@
 	}
 
 	sym->flags |= ISDEFINED;
-	if (sym->type->op != tag)
-		error("'%s' defined as wrong kind of tag", yytext);
+	if ((op = sym->type->op) != tag &&  op != INT)
+		error("'%s' defined as wrong kind of tag", sym->name);
 	return sym;
 }
 
@@ -385,28 +391,36 @@
 enumdcl(void)
 {
 	Type *tp;
-	Symbol *sym;
-	int val = 0;
+	Symbol *sym, *tagsym;
+	int val;
 
-	tp = newtag()->type;
+	tagsym = newtag();
+	tp = tagsym->type;
 
-	if (yytoken == ';')
+	if (!accept('{'))
 		return tp;
-
-	expect('{');
 	if (tp->defined)
-		error("redefinition of enumeration '%s'", yytext);
+		error("redefinition of enumeration '%s'", tagsym->name);
 	tp->defined = 1;
-	while (yytoken != '}') {
+	for (val = 0; yytoken != ')'; ++val) {
 		if (yytoken != IDEN)
 			unexpected();
 		if ((sym = install(NS_IDEN)) == NULL)
 			error("'%s' redeclared as different kind of symbol", yytext);
 		next();
+		sym->flags |= ISCONSTANT;
 		sym->type = inttype;
-		if (accept('='))
-			constexpr();
-		sym->u.i = val++;
+		if (accept('=')) {
+			Node *np = constexpr();
+			/*
+			 * TODO: check that the type of the constant
+			 * expression is the correct, that in this
+			 * case should be int
+			 */
+			val = np->sym->u.i;
+			freetree(np);
+		}
+		sym->u.i = val;
 		if (!accept(','))
 			break;
 	}
--- a/cc1/expr.c
+++ b/cc1/expr.c
@@ -667,6 +667,7 @@
 		}
 		next();
 		np = (*fun)(op, np, cast());
+		np = simplify(np);
 	}
 }
 
--- a/cc1/lex.c
+++ b/cc1/lex.c
@@ -231,6 +231,7 @@
 	tp = ctype(INT, sign, size);
 	sym = newsym(NS_IDEN);
 	sym->type = tp;
+	sym->flags |= ISCONSTANT;
 	v = strtol(s, NULL, base);
 	if (tp == inttype)
 		sym->u.i = v;
@@ -358,6 +359,7 @@
 
 	yylen = bp - yytext + 1;
 	yylval.sym = newsym(NS_IDEN);
+	yylval.sym->flags |= ISCONSTANT;
 	yylval.sym->u.s = xstrdup(yytext+1);
 	yylval.sym->type = mktype(chartype, ARY, yylen - 2, NULL);
 	*bp++ = '"';
@@ -387,6 +389,8 @@
 		 */
 		sym = nextsym(sym, lex_ns);
 	}
+	if (sym->flags & ISCONSTANT)
+		return CONSTANT;
 	if (sym->token != IDEN)
 		yylval.token = sym->u.token;
 	return sym->token;
--- a/cc1/types.c
+++ b/cc1/types.c
@@ -292,10 +292,25 @@
 	type.n.elem = nelem;
 	type.ns = 0;
 
-	if (op == ARY && nelem == 0 || op == STRUCT || op == UNION)
-		type.defined = 0;
-	else
+
+	switch (op) {
+	case ARY:
+		if (nelem == 0)
+			goto no_defined;
+		/* PASSTROUGH */
+	case FTN:
+	case PTR:
 		type.defined = 1;
+		break;
+	case ENUM:
+		type.printed = 1;
+		/* PASSTROUGH */
+	case STRUCT:
+	case UNION:
+	no_defined:
+		type.defined = 0;
+		break;
+	}
 
 	t = (op ^ (uintptr_t) tp >> 3) & NR_TYPE_HASH-1;
 	tbl = &typetab[t];
@@ -336,7 +351,7 @@
 		}
 		return 1;
 	case ENUM:
-		/* TODO: Check when two enum are the same type */
+		break;
 	case INT: case FLOAT:
 		return tp1->letter == tp2->letter;
 	default: