shithub: scc

Download patch

ref: eaf8259846c2b6d77467cddf8fe143c6cce568dd
parent: b2fc11b3d2e07e84e2868f5aab8319612257855c
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Mon Mar 17 12:39:17 EDT 2014

Add definitions for struct and enums

--- a/decl.c
+++ b/decl.c
@@ -11,9 +11,6 @@
 
 int8_t forbid_eof;
 
-static struct dcldata
-	*declarator0(struct dcldata *dp, uint8_t ns, int8_t flags);
-
 struct dcldata {
 	uint8_t op;
 	union {
@@ -24,6 +21,9 @@
 	} u;
 };
 
+static struct dcldata
+	*declarator0(struct dcldata *dp, uint8_t ns, int8_t flags);
+
 static struct dcldata *
 arydcl(struct dcldata *dp)
 {
@@ -90,8 +90,6 @@
 error:	error(err, yytext);
 }
 
-/* TODO: Add a token2 field in yylval to avoid yylval.sym->u.c */
-
 static struct dcldata*
 declarator0(struct dcldata *dp, uint8_t ns, int8_t flags)
 {
@@ -155,13 +153,13 @@
 	return sym;
 }
 
-static struct ctype *structdcl(void), *enumdcl(void);
+static struct ctype *structdcl(uint8_t tag), *enumdcl(uint8_t tag);
 
 static struct ctype *
 specifier(int8_t *sclass)
 {
 	struct ctype *tp = NULL;
-	int8_t qlf, sign, type, cls, cplex, size;
+	int8_t qlf, sign, type, cls, cplex, size, t;
 
 	qlf = sign = type = cls = size = cplex = 0;
 
@@ -177,15 +175,16 @@
 			goto next_token;
 		case TYPE:
 			switch (sym->u.c) {
-			case ENUM:
-				tp = enumdcl();   goto set_type;
-			case STRUCT:   case UNION:
-				tp = structdcl(); goto set_type;
+			case ENUM: case STRUCT: case UNION:
+				t = sym->u.c;
+				tp = (t == UNION) ? enumdcl(t) : structdcl(t);
+				p = &type;
+				goto check_spec;
 			case TYPENAME:
 				tp = yylval.sym->type;
 			case VOID:   case BOOL:  case CHAR:
 			case INT:    case FLOAT: case DOUBLE:
-set_type:			p = &type; break;
+				p = &type; goto next_token;
 			case SIGNED: case UNSIGNED:
 				p = &sign; break;
 			case LONG:
@@ -194,18 +193,18 @@
 					goto next_token;
 				}
 			case SHORT:
-				p = &size; break;
+				p = &size; goto next_token;
 			case COMPLEX: case IMAGINARY:
-				p = &cplex; break;
+				p = &cplex; goto next_token;
 			}
 			break;
 		default:
 			goto check_types;
 		}
-		if (*p)
+next_token:	next();
+check_spec:	if (*p)
 			goto invalid_type;
 		*p = sym->u.c;
-next_token:	next();
 	}
 
 check_types:
@@ -246,19 +245,86 @@
 	}
 }
 
+/* TODO: add define for the 3 parameter of declarator */
+/* TODO: bitfields */
+static short
+fielddcl(uint8_t ns, uint8_t type)
+{
+	struct ctype *tp;
+	struct symbol *sym;
+	short offset = 0;
+
+	switch (yytoken) {
+	case IDEN:
+		warn(options.implicit,
+		     "type defaults to 'int' in declaration");
+		tp = inttype;
+		break;
+	case SCLASS:
+		error("storage class '%s' in struct/union field", yytext);
+	case TYPE: case TQUALIFIER:
+		tp = specifier(NULL);
+		break;
+	case ';':
+		break;
+	default:
+		error("declaration expected");
+	}
+
+	if (yytoken != ';') {
+		do {
+			sym = declarator(tp, ns, 1);
+			sym->u.offset = offset;
+			if (type == STRUCT)
+				offset += sym->type->size;
+		} while (accept(','));
+	}
+
+	expect(';');
+	return offset;
+}
+
 static struct ctype *
-structdcl(void)
+structdcl(uint8_t tag)
 {
-	uint8_t type = yylval.sym->u.c;
+	register struct symbol *sym;
+	struct ctype *tp;
+	short size;
+	extern uint8_t namespace;
 
 	next();
 	if (yytoken == IDEN) {
+		sym = lookup(yytext, NS_TAG);
+		if (sym) {
+			if (sym->type->op != tag)
+				goto bad_tag;
+		} else {
+			sym = install(yytext, NS_TAG);
+		}
+		next();
+	} else {
+		sym = install(NULL, NS_TAG);
 	}
-	return NULL;
+	sym->type = tp = mktype(NULL, tag, NULL, 0);
+	++namespace;
+
+	if (yytoken != ';') {
+		expect('{');
+		while (!accept('}'))
+			size = fielddcl(namespace, tag);
+	} else {
+		size = 0;
+	}
+	tp->size = size;
+
+	return tp;
+
+bad_tag:
+	error("error '%s' defined as wrong kind of tag", yytext);
 }
 
 static struct ctype *
-enumdcl(void)
+enumdcl(uint8_t token)
 {
 	return NULL;
 }
@@ -277,42 +343,6 @@
 			/* assign storage class */
 			if (accept('='))
 				initializer(sym->type);
-		} while (accept(','));
-	}
-
-	expect(';');
-	return NULL;
-}
-
-static struct symbol *
-fielddcl(void)
-{
-	struct ctype *tp;
-	struct symbol *sym;
-
-	switch (yytoken) {
-	case IDEN:
-		warn(options.implicit,
-		     "type defaults to 'int' in declaration");
-		tp = inttype;
-		break;
-	case SCLASS:
-		error("storage class '%s' in struct/union field", yytext);
-	case TYPE: case TQUALIFIER:
-		tp = specifier(NULL);
-		break;
-	case ';':
-		break;
-	default:
-		error("declaration expected");
-	}
-
-	if (yytoken != ';') {
-		do {
-			sym = declarator(tp, 0, 1);
-			if (accept(':'))
-				; /* TODO: bitfields */
-			/* TODO: add to the aggregate */
 		} while (accept(','));
 	}
 
--- a/symbol.c
+++ b/symbol.c
@@ -101,9 +101,12 @@
 	tbl = &symtab[(ns >= NR_NAMESPACES) ? NS_IDEN : ns];
 	sym->next = tbl->head;
 	tbl->head = sym;
-	t = &tbl->htab[hash(s)];
-	sym->hash = *t;
-	*t = sym;
+
+	if (s != NULL) {
+		t = &tbl->htab[hash(s)];
+		sym->hash = *t;
+		*t = sym;
+	}
 
 	return sym;
 }
--- a/symbol.h
+++ b/symbol.h
@@ -23,10 +23,10 @@
 	uint8_t op;           /* type builder operator */
 	uint8_t size;         /* size of variables */
 	uint16_t nelem;       /* number of elements in arrays */
-	unsigned forward : 1;     /* forward type */
+	unsigned forward : 1; /* forward type */
 	unsigned cplex : 1;   /* complex specifier */
 	unsigned imag : 1;
-	unsigned sign : 1;        /* sign type */
+	unsigned sign : 1;    /* sign type */
 	struct symbol *sym;   /* symbol of the tag identifier */
 	struct ctype *type;   /* base type */
 	struct ctype *next;   /* next element in the hash */
@@ -46,6 +46,7 @@
 	uint8_t ns;
 	union {
 		char c;
+		short offset;
 	} u;
 	struct symbol *next;
 	struct symbol *hash;
--- a/syntax.h
+++ b/syntax.h
@@ -6,6 +6,7 @@
 #endif
 
 extern unsigned char curctx;
+extern uint8_t namespace;
 
 enum opcode {
 	OARY, OCALL, OFIELD, OPTR, OPOSTINC, OPOSTDEC,
--- a/types.c
+++ b/types.c
@@ -162,7 +162,7 @@
 	t = (op  ^  (uint8_t) ((unsigned short) tp >> 3))
 	         & NR_TYPE_HASH-1;
 	tbl = &typetab[t];
-	if (op != FTN) {
+	if (op != FTN || op != STRUCT || op != UNION || op != ENUM) {
 		for (bp = *tbl; bp; bp = bp->next) {
 			if (bp->type == tp && bp->op == op &&
 			    bp->sym == sym && bp->nelem == nelem) {
@@ -175,6 +175,8 @@
 	case PTR: size = PTRSIZE; break;
 	case FTN: size = 0; break;
 	case ARY: size = tp->size * nelem; break;
+	case ENUM: size = INTSIZE;
+	case STRUCT: case UNION: size = 0; break;
 	default:  size = tp->size; break;
 	}
 	bp = xmalloc(sizeof(*bp));
--