ref: 3384b1e35a288f2e197d9ab75942cb5aa74fb5fc
parent: f22a20736e42f365fb4f017ecbcc8ab6033287f7
author: Jacob Moody <moody@posixcafe.org>
date: Sun Jun 25 18:39:25 EDT 2023
cc: support binary constants and refactor C23 now specifies 0[bB] binary constants. In adding these cinap found that the bounds checking in mpatov() was incorrect, both in implementation and concept. So instead lets just accumulate the constant value as we lex.
--- a/sys/src/cmd/cc/lex.c
+++ b/sys/src/cmd/cc/lex.c
@@ -782,16 +782,18 @@
tnum:
c1 = 0;
cp = symb;
+ vv = 0;
if(c != '0') {
c1 |= Numdec;
for(;;) {
+ if(!isdigit(c))
+ goto dc;
+
+ vv = vv*10 + c-'0';
if(cp >= &symb[NSYMB-1])
goto toolong;
*cp++ = c;
c = GETC();
- if(isdigit(c))
- continue;
- goto dc;
}
}
*cp++ = c;
@@ -802,27 +804,47 @@
goto toolong;
*cp++ = c;
c = GETC();
- if(isdigit(c))
+ if(isdigit(c)){
+ vv = vv*16 + c-'0';
continue;
- if(c >= 'a' && c <= 'f')
+ }
+ if(c >= 'a' && c <= 'f'){
+ vv = vv*16 + c + 10 - 'a';
continue;
- if(c >= 'A' && c <= 'F')
+ }
+ if(c >= 'A' && c <= 'F'){
+ vv = vv*16 + c + 10 - 'A';
continue;
+ }
if(cp == symb+2)
yyerror("malformed hex constant");
goto ncu;
}
- if(c < '0' || c > '7')
- goto dc;
- for(;;) {
- if(c >= '0' && c <= '7') {
+ if(c == 'b' || c == 'B')
+ for(;;) {
if(cp >= &symb[NSYMB-1])
goto toolong;
*cp++ = c;
c = GETC();
- continue;
+ if(c == '0' || c == '1'){
+ vv = vv*2 + c-'0';
+ continue;
+ }
+ if(cp == symb+2)
+ yyerror("malformed binary constant");
+ goto ncu;
}
- goto ncu;
+ if(c < '0' || c > '7')
+ goto dc;
+ for(;;) {
+ if(c < '0' || c > '7')
+ goto ncu;
+
+ vv = vv*8 + c-'0';
+ if(cp >= &symb[NSYMB-1])
+ goto toolong;
+ *cp++ = c;
+ c = GETC();
}
dc:
@@ -846,10 +868,7 @@
}
*cp = 0;
peekc = c;
- if(mpatov(symb, &yylval.vval))
- yyerror("overflow in constant");
- vv = yylval.vval;
/*
* c99 is silly: decimal constants stay signed,
* hex and octal go unsigned before widening.
@@ -950,75 +969,6 @@
yyerror("token too long: %.*s...", utfnlen(symb, cp-symb), symb);
errorexit();
return -1;
-}
-
-/*
- * convert a string, s, to vlong in *v
- * return conversion overflow.
- * required syntax is [0[x]]d*
- */
-int
-mpatov(char *s, vlong *v)
-{
- vlong n, nn;
- int c;
-
- n = 0;
- c = *s;
- if(c == '0')
- goto oct;
- while(c = *s++) {
- if(c >= '0' && c <= '9')
- nn = n*10 + c-'0';
- else
- goto bad;
- if(n < 0 && nn >= 0)
- goto bad;
- n = nn;
- }
- goto out;
-
-oct:
- s++;
- c = *s;
- if(c == 'x' || c == 'X')
- goto hex;
- while(c = *s++) {
- if(c >= '0' && c <= '7')
- nn = n*8 + c-'0';
- else
- goto bad;
- if(n < 0 && nn >= 0)
- goto bad;
- n = nn;
- }
- goto out;
-
-hex:
- s++;
- while(c = *s++) {
- if(c >= '0' && c <= '9')
- c += 0-'0';
- else
- if(c >= 'a' && c <= 'f')
- c += 10-'a';
- else
- if(c >= 'A' && c <= 'F')
- c += 10-'A';
- else
- goto bad;
- nn = n*16 + c;
- if(n < 0 && nn >= 0)
- goto bad;
- n = nn;
- }
-out:
- *v = n;
- return 0;
-
-bad:
- *v = ~0;
- return 1;
}
int
--
⑨