/* * Convert string numbers to unsigned long long and check overflow. */ static void cvtdig(int rad) { unsigned long long rv = 0; unsigned long long rv2 = 0; usch *y = yytext; int c; c = *y++; if (rad == 16) y++; while ((spechr[c] & C_HEX)) { rv = rv * rad + dig2num(c); /* check overflow */ if (rv / rad < rv2) error("constant \"%s\" is out of range", yytext); rv2 = rv; c = *y++; } y--; while (*y == 'l' || *y == 'L') y++; yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER; yylval.node.nd_uval = rv; if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0) yylval.node.op = UNUMBER; if (yylval.node.op == NUMBER && yylval.node.nd_val < 0) /* too large for signed, see 6.4.4.1 */ error("constant \"%s\" is out of range", yytext); }
/* * Convert string numbers to unsigned long long and check overflow. */ static void cvtdig(usch **yyp) { unsigned long long rv = 0; unsigned long long rv2 = 0; usch *y = *yyp; int rad; y--; rad = *y != '0' ? 10 : y[1] == 'x' || y[1] == 'X' ? 16 : 8; if (rad == 16) y += 2; while ((spechr[*y] & C_HEX)) { rv = rv * rad + dig2num(*y); /* check overflow */ if (rv / rad < rv2) error("constant is out of range"); rv2 = rv; y++; } yynode.op = NUMBER; while (*y == 'l' || *y == 'L' || *y == 'u' || *y == 'U') { if (*y == 'u' || *y == 'U') yynode.op = UNUMBER; y++; } yynode.nd_uval = rv; if ((rad == 8 || rad == 16) && yynode.nd_val < 0) yynode.op = UNUMBER; if (yynode.op == NUMBER && yynode.nd_val < 0) /* too large for signed, see 6.4.4.1 */ error("constant is out of range"); *yyp = y; }
/* * check for universal-character-name on input, and * unput to the pushback buffer encoded as UTF-8. */ static int chkucn(void) { unsigned long cp, m; int ch, n; if ((ch = inch()) == -1) return 0; if (ch == 'u') n = 4; else if (ch == 'U') n = 8; else { unch(ch); return 0; } cp = 0; while (n-- > 0) { if ((ch = inch()) == -1 || (spechr[ch] & C_HEX) == 0) { warning("invalid universal character name"); // XXX should actually unput the chars and return 0 unch(ch); // XXX eof break; } cp = cp * 16 + dig2num(ch); } if ((cp < 0xa0 && cp != 0x24 && cp != 0x40 && cp != 0x60) || (cp >= 0xd800 && cp <= 0xdfff)) /* 6.4.3.2 */ error("universal character name cannot be used"); if (cp > 0x7fffffff) error("universal character name out of range"); n = 0; m = 0x7f; while (cp > m) { unch(0x80 | (cp & 0x3f)); cp >>= 6; m >>= (n++ ? 1 : 2); } unch(((m << 1) ^ 0xfe) | cp); return 1; }
static int charcon(usch **yyp) { int val, c; usch *p = *yyp; val = 0; if (*p++ == '\\') { switch (*p++) { case 'a': val = '\a'; break; case 'b': val = '\b'; break; case 'f': val = '\f'; break; case 'n': val = '\n'; break; case 'r': val = '\r'; break; case 't': val = '\t'; break; case 'v': val = '\v'; break; case '\"': val = '\"'; break; case '\'': val = '\''; break; case '\\': val = '\\'; break; case 'x': while ((spechr[c = *p] & C_HEX)) { val = val * 16 + dig2num(c); p++; } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': p--; while ((spechr[c = *p] & C_DIGIT)) { val = val * 8 + (c - '0'); p++; } break; default: val = p[-1]; } } else val = p[-1]; if (*p != '\'') error("bad charcon"); *yyp = ++p; return val; }
/* * check for universal-character-name on input, and * unput to the pushback buffer encoded as UTF-8. */ static void ucn(int n) { unsigned long cp, m; int ch; if (incmnt) { struct iobuf *ib = ifiles->ib; ib->cptr--; /* [uU] */ ib->buf[--ib->cptr] = '\\'; return; } cp = 0; while (n-- > 0) { if ((ch = qcchar()) == 0 || (spechr[ch] & C_HEX) == 0) { warning("invalid universal character name"); // XXX should actually unput the chars and return 0 unch(ch); // XXX eof break; } cp = cp * 16 + dig2num(ch); } if ((cp < 0xa0 && cp != 0x24 && cp != 0x40 && cp != 0x60) || (cp >= 0xd800 && cp <= 0xdfff)) /* 6.4.3.2 */ error("universal character name cannot be used"); if (cp > 0x7fffffff) error("universal character name out of range"); n = 0; m = 0x7f; while (cp > m) { unch(0x80 | (cp & 0x3f)); cp >>= 6; m >>= (n++ ? 1 : 2); } unch(((m << 1) ^ 0xfe) | cp); }
static int charcon(usch *p) { int val, c; p++; /* skip first ' */ val = 0; if (*p++ == '\\') { switch (*p++) { case 'a': val = '\a'; break; case 'b': val = '\b'; break; case 'f': val = '\f'; break; case 'n': val = '\n'; break; case 'r': val = '\r'; break; case 't': val = '\t'; break; case 'v': val = '\v'; break; case '\"': val = '\"'; break; case '\'': val = '\''; break; case '\\': val = '\\'; break; case 'x': while (isxdigit(c = *p)) { val = val * 16 + dig2num(c); p++; } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': p--; while (isdigit(c = *p)) { val = val * 8 + (c - '0'); p++; } break; default: val = p[-1]; } } else val = p[-1]; return val; }