shithub: riscv

Download patch

ref: 0e4ab4312eb9ec7264f9c4b97b4aef028e879788
parent: b049bb81adf2e6b0e2ef30973195a5ced06d2185
author: Jacob Moody <moody@posixcafe.org>
date: Mon Feb 17 16:00:07 EST 2025

cc: add case ranges extension

Add an extension for cases to specify a range ie:

switch(c){
case 'a' ... 'z':
	break;
}

Also now that we have a specific token for '...'
update variadic function definitions to prevent
things like func(int, .. /* whatever */.);

--- a/sys/src/cmd/cc/cc.y
+++ b/sys/src/cmd/cc/cc.y
@@ -64,7 +64,7 @@
 %token	LIF LINT LLONG LREGISTER LRETURN LSHORT LSIZEOF LUSED
 %token	LSTATIC LSTRUCT LSWITCH LTYPEDEF LTYPESTR LUNION LUNSIGNED
 %token	LWHILE LVOID LENUM LSIGNED LCONSTNT LVOLATILE LSET LSIGNOF
-%token	LRESTRICT LINLINE LNORET
+%token	LRESTRICT LINLINE LNORET LDOTDOTDOT
 %%
 prog:
 |	prog xdecl
@@ -353,7 +353,7 @@
 		$$ = new(OPROTO, $2, Z);
 		$$->type = $1;
 	}
-|	'.' '.' '.'
+|	LDOTDOTDOT
 	{
 		$$ = new(ODOTDOT, Z, Z);
 	}
@@ -393,7 +393,11 @@
 	}
 
 label:
-	LCASE expr ':'
+	LCASE expr LDOTDOTDOT expr ':'	/* extension */
+	{
+		$$ = new(OCASE, $2, $4);
+	}
+|	LCASE expr ':'
 	{
 		$$ = new(OCASE, $2, Z);
 	}
--- a/sys/src/cmd/cc/lex.c
+++ b/sys/src/cmd/cc/lex.c
@@ -516,7 +516,14 @@
 
 	case '.':
 		c1 = GETC();
-		if(isdigit(c1)) {
+		if(c1 == '.'){
+			c = GETC();
+			if(c == '.')
+				return LDOTDOTDOT;
+			else
+				yyerror(".. instead of ...");
+				
+		} else if(isdigit(c1)) {
 			cp = symb;
 			*cp++ = c;
 			c = c1;
--- a/sys/src/cmd/cc/pgen.c
+++ b/sys/src/cmd/cc/pgen.c
@@ -127,12 +127,13 @@
 void
 gen(Node *n)
 {
-	Node *l, nod, rn;
+	Node *l, *r, nod, rn;
 	Prog *sp, *spc, *spb;
 	Case *cn;
 	long sbc, scc;
 	int snbreak, sncontin;
 	int f, o, oldreach;
+	vlong i, end;
 
 loop:
 	if(n == Z)
@@ -279,6 +280,7 @@
 	case OCASE:
 		canreach = 1;
 		l = n->left;
+		r = n->right;
 		if(cases == C)
 			diag(n, "case/default outside a switch");
 		if(l == Z) {
@@ -296,11 +298,27 @@
 			diag(n, "case expression must be integer constant");
 			goto rloop;
 		}
-		casf();
-		cases->val = l->vconst;
-		cases->def = 0;
-		cases->label = pc;
-		cases->isv = typev[l->type->etype];
+		if(r != Z){
+			complex(r);
+			if(r->op != OCONST || !typeswitch[r->type->etype]) {
+				diag(n, "case expression must be integer constant");
+				goto rloop;
+			}
+			if(r->vconst < l->vconst){
+				diag(n, "case range must be increasing");
+				goto rloop;
+			}
+			end = r->vconst;
+		} else
+			end = l->vconst;
+
+		for(i = l->vconst; i <= end; i++){
+			casf();
+			cases->val = i;
+			cases->def = 0;
+			cases->label = pc;
+			cases->isv = typev[l->type->etype];
+		}
 		goto rloop;
 
 	case OSWITCH:
--