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:
--
⑨