shithub: scc

Download patch

ref: 2d30362df693b46f67f1515e9d23e56e237410a5
parent: 08c42cdfaea4d0cc3bf0bc00ee3e7cf2e5a9664a
author: Roberto E. Vargas Caballero <[email protected]>
date: Thu Apr 10 03:29:53 EDT 2014

Add shift operators

--- a/cc.h
+++ b/cc.h
@@ -219,7 +219,8 @@
 
 enum {
 	OCAST, OPTR, OADD, OARY, OSIZE, OMUL, OSUB,
-	OINC, ODEC, OPINC, OPDEC, ODIV, OMOD
+	OINC, ODEC, OPINC, OPDEC, ODIV, OMOD, OSHL,
+	OSHR
 };
 
 extern void
--- a/code.c
+++ b/code.c
@@ -15,7 +15,9 @@
 	[OSIZE] = "#",
 	[OPTR] = "@",
 	[OMOD] = "*",
-	[ODIV] = "/'"
+	[ODIV] = "/'",
+	[OSHL] = "l",
+	[OSHR]  = "r"
 };
 
 Node *
--- a/expr.c
+++ b/expr.c
@@ -49,6 +49,7 @@
 static Node *
 arithmetic(char op, Node *np1, Node *np2)
 {
+	char *err;
 	Node *naux;
 	Type *tp1, *tp2, *tp3;
 	uint8_t t1, t2, taux, lvalue = 0;
@@ -56,6 +57,9 @@
 	tp1 = UNQUAL(np1->type), tp2 = UNQUAL(np2->type);
 	t1 = tp1->op, t2 = tp2->op;
 
+	if ((op == OSHL || op == OSHR) && (t1 != INT || t2 != INT))
+		goto bad_shift;
+
 	switch (t1) {
 	case INT:
 		switch (t2) {
@@ -112,10 +116,16 @@
 	np1->b.lvalue = lvalue;
 	return np1;
 
+bad_shift:
+	err = "invalid operands to shift operator";
+	goto error;
 nocomplete:
-	error("invalid use of indefined type");
+	err = "invalid use of indefined type";
+	goto error;
 incorrect:
-	error("incorrect arithmetic operands");
+	err = "incorrect arithmetic operands";
+error:
+	error(err);
 }
 
 static Node *
@@ -283,6 +293,24 @@
 	}
 }
 
+static struct node *
+shift(void)
+{
+	register char op;
+	register Node *np;
+
+	np = add();
+	for (;;) {
+		switch (yytoken) {
+		case SHL: op = OSHL; break;
+		case SHR: op = OSHR; break;
+		default:  return np;
+		}
+		next();
+		np = arithmetic(op, np, add());
+	}
+}
+
 Node *
 expr(void)
 {
@@ -289,7 +317,7 @@
 	register Node *np;
 
 	do
-		np = add();
+		np = shift();
 	while (yytoken == ',');
 	return np;
 }