shithub: scc

Download patch

ref: 7204b59c338a474645eac83b24a7b37be7eb8b88
parent: 1f4d772a7ff6987171acc1c6c5922123b764c110
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Thu Jul 4 17:54:02 EDT 2013

Allocate ctype in spec function

spec is the place where we read all the tokens which is going
to define the type, so it is a good place for allocate the
ctype struct.

--- a/decl.c
+++ b/decl.c
@@ -70,20 +70,19 @@
 	}
 }
 
-static unsigned char
-spec(register struct ctype *cp)
+struct ctype *
+spec(void)
 {
-	register unsigned char sign, n;
+	static unsigned char sign, type;
+	register struct ctype *tp = NULL;
 
-	for (n = sign = 0; ; ++n, next()) {
+	for (type = sign = 0; ; next()) {
 		switch (yytoken) {
 		case TYPEDEF:  case EXTERN: case STATIC: case AUTO:
 		case REGISTER: case CONST:  case VOLATILE:
-			storage(cp, yytoken);
+			tp = storage(tp, yytoken);
 			break;
-		case UNSIGNED:
-			cp->c_unsigned = 1;
-		case SIGNED:
+		case UNSIGNED: case SIGNED:
 			if (sign == yytoken)
 				error("duplicated '%s'", yytext);
 			if (sign)
@@ -92,7 +91,10 @@
 			case FLOAT: case DOUBLE: case LDOUBLE:
 				goto float_sign;
 			}
-			sign = yytoken;
+			if (!tp)
+				tp = newctype();
+			if ((type = sign = yytoken) == UNSIGNED)
+				tp->c_unsigned = 1;
 			break;
 		case FLOAT: case DOUBLE:
 			if (sign)
@@ -99,15 +101,16 @@
 				goto float_sign;
 		case VOID:   case CHAR:   case SHORT:
 		case INT:    case LONG:   case BOOL:
-			cp->type = btype(cp->type, yytoken);
+			tp = btype(tp, yytoken);
+			type = tp->type;
 			break;
 		case STRUCT:    /* TODO */
 		case UNION:	/* TODO */
 		case ENUM:	/* TODO */
 		default:
-			if (!cp->type && sign)
-				cp->type = INT;
-			return n;
+			if (tp && !tp->type && sign)
+				tp->type = INT;
+			return tp;
 		}
 	}
 float_sign:
@@ -181,7 +184,7 @@
 				      "type defaults to 'int' in declaration of '%s'",
 				      yytext);
 		}
-		linkctype(tp, cursym);
+		(cursym->ctype = tp)->refcnt++;
 		sp = nodesym(cursym);
 		if (tp->type == FTN && yytoken == '{') {
 			np  = node2(ODEF, sp, function(cursym));
@@ -203,8 +206,7 @@
 
 	while (accept(';'))
 		/* nothing */;
-	tp = newctype();
-	if (!spec(tp)) {
+	if (!(tp = spec())) {
 		if (curctx != CTX_OUTER)
 			goto end;
 		warning("data definition has no type or storage class");
--- a/symbol.h
+++ b/symbol.h
@@ -57,7 +57,7 @@
 
 extern struct ctype *decl_type(struct ctype *t);
 extern void pushtype(unsigned mod);
-extern unsigned char btype(unsigned char, unsigned char tok);
+extern struct ctype *btype(struct ctype *tp, unsigned char tok);
 extern void new_ctx(void);
 extern void del_ctx(void);
 extern void freesyms(void);
@@ -64,10 +64,9 @@
 extern struct symbol *lookup(const char *s, char ns);
 extern struct symbol *find(const char *s, char ns);
 extern void insert(struct symbol *sym, unsigned char ctx);
-extern void storage(struct ctype *cp, unsigned char mod);
+extern struct ctype *storage(struct ctype *tp, unsigned char mod);
 extern struct ctype *newctype(void);
 extern void delctype(struct ctype *tp);
-extern void linkctype(struct ctype *tp, struct symbol *sym);
 
 #ifndef NDEBUG
 extern void ptype(register struct ctype *t);
--- a/types.c
+++ b/types.c
@@ -22,15 +22,10 @@
 }
 
 void
-linkctype(register struct ctype *tp, register struct symbol *sym)
-{
-	sym->ctype = tp;
-	++tp->refcnt;
-}
-
-void
 delctype(register struct ctype *tp)
 {
+	if (!tp)
+		return;
 	if (--tp->refcnt == 0) {
 		if (tp->base)
 			delctype(tp->base);
@@ -90,50 +85,66 @@
 	return tp;
 }
 
-unsigned char
-btype(unsigned char type, unsigned char tok)
+struct ctype *
+btype(struct ctype *tp, unsigned char tok)
 {
+	register unsigned char type;
+
+	if (!tp)
+		tp = newctype();
+
+	type = tp->type;
 	switch (tok) {
 	case VOID:
-		if (!type)
-			return VOID;
+		if (type)
+			goto two_or_more;;
+		type = VOID;
 		break;
 	case BOOL:
-		if (!type)
-			return BOOL;
+		if (type)
+			goto two_or_more;
+		type = BOOL;
 		break;
 	case CHAR:
-		if (!type)
-			return CHAR;
+		if (type)
+			goto two_or_more;
+		type = CHAR;
 		break;
 	case SHORT:
-		if (!type || type == INT)
-			return SHORT;
+		if (type && type != INT)
+			goto two_or_more;
+		type = SHORT;
 		break;
 	case INT:
 		switch (type) {
-		case 0:     return INT;
-		case SHORT: return INT;
-		case LONG:  return LONG;
+		case 0:       type = INT;       break;
+		case SHORT:   type = SHORT;     break;
+		case LONG:    type = LONG;      break;
+		default:      goto two_or_more;
 		}
 		break;
 	case LONG:
 		switch (type) {
-		case 0: case INT:          return LONG;
-		case LONG:                 return LLONG;
-		case DOUBLE:               return LDOUBLE;
-		case LLONG: case LDOUBLE:  error("too much long");
+		case 0:
+		case INT:     type = LONG;      break;
+		case LONG:    type = LLONG;     break;
+		case DOUBLE:  type = LDOUBLE;   break;
+		case LLONG:
+		case LDOUBLE:  error("too much long");
 		}
 		break;
 	case FLOAT:
-		if (!type)
-			return FLOAT;
+		if (type)
+			goto two_or_more;
+		type = FLOAT;
 		break;
 	case DOUBLE:
+		if (type)
+			goto two_or_more;
 		if (!type)
-			return DOUBLE;
-		if (type == LONG)
-			return LDOUBLE;
+			type = DOUBLE;
+		else if (type == LONG)
+			type = LDOUBLE;
 		break;
 #ifndef NDEBUG
 	default:
@@ -140,64 +151,70 @@
 		abort();
 #endif
 	}
+	tp->type = type;
+	return tp;
+
+two_or_more:
 	error("two or more basic types");
 }
 
-void
-storage(struct ctype *cp, unsigned char mod)
+struct ctype *
+storage(register struct ctype *tp, unsigned char mod)
 {
 	extern unsigned char curctx;
 
+	if (!tp)
+		tp = newctype();
 	switch (mod) {
 	case TYPEDEF:
-		if (cp->c_type)
+		if (tp->c_type)
 			goto duplicated;
-		if (cp->c_extern | cp->c_auto | cp->c_reg | cp->c_static)
+		if (tp->c_extern | tp->c_auto | tp->c_reg | tp->c_static)
 			goto two_storage;
-		cp->c_type = 1;
-		return;
+		tp->c_type = 1;
+		return tp;
 	case EXTERN:
-		if (cp->c_extern)
+		if (tp->c_extern)
 			goto duplicated;
-		if (cp->c_type | cp->c_auto | cp->c_reg | cp->c_static)
+		if (tp->c_type | tp->c_auto | tp->c_reg | tp->c_static)
 			goto two_storage;
-		cp->c_extern = 1;
-		return;
+		tp->c_extern = 1;
+		return tp;
 	case STATIC:
-		if (cp->c_static)
+		if (tp->c_static)
 			goto duplicated;
-		if (cp->c_type | cp->c_extern | cp->c_auto | cp->c_reg)
+		if (tp->c_type | tp->c_extern | tp->c_auto | tp->c_reg)
 			goto two_storage;
-		cp->c_static = 1;
-		return;
+		tp->c_static = 1;
+		return tp;
 	case AUTO:
 		if (curctx != CTX_OUTER)
 			goto bad_file_scope_storage;
-		if (cp->c_type | cp->c_extern | cp->c_static | cp->c_reg)
+		if (tp->c_type | tp->c_extern | tp->c_static | tp->c_reg)
 			goto two_storage;
-		if (cp->c_auto)
+		if (tp->c_auto)
 			goto duplicated;
-		cp->c_static = 1;
-		return;
+		tp->c_static = 1;
+		return tp;
 	case REGISTER:
 		if (curctx != CTX_OUTER)
 			goto bad_file_scope_storage;
-		if (cp->c_type | cp->c_extern | cp->c_auto | cp->c_static)
+		if (tp->c_type | tp->c_extern | tp->c_auto | tp->c_static)
 			goto two_storage;
-		if (cp->c_reg)
+		if (tp->c_reg)
 			goto duplicated;
-		cp->c_reg = 1;
-		return;
+		tp->c_reg = 1;
+		return tp;
 	case CONST:
-		if (options.repeat && cp->c_const)
+		if (options.repeat && tp->c_const)
 			goto duplicated;
-		cp->c_const = 1;
-		return;
+		tp->c_const = 1;
+		return tp;
 	case VOLATILE:
-		if (options.repeat && cp->c_volatile)
+		if (options.repeat && tp->c_volatile)
 			goto duplicated;
-		cp->c_volatile = 1;
-		return;
+		tp->c_volatile = 1;
+		return tp;
 	}
 bad_file_scope_storage:
 	error("file-scope declaration specifies '%s'", yytext);
--