PP: Clean up and rationalize floating-point-number scanner.
This encapsulates where the string could overflow, removing 40 lines of fragile code. It also improves handling of numbers that are too long. There are a couple of open issues that could related to this function being more rational (locale dependence, 1.#INF).
This commit is contained in:
parent
e86fc0946f
commit
913e3b686a
3 changed files with 73 additions and 112 deletions
|
|
@ -100,36 +100,26 @@ namespace glslang {
|
|||
int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
|
||||
{
|
||||
bool HasDecimalOrExponent = false;
|
||||
int declen;
|
||||
int str_len;
|
||||
int isDouble = 0;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
int isFloat16 = 0;
|
||||
bool enableFloat16 = parseContext.version >= 450 && parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float);
|
||||
#endif
|
||||
|
||||
declen = 0;
|
||||
const auto saveName = [&](int ch) {
|
||||
if (len <= MaxTokenLength)
|
||||
ppToken->name[len++] = static_cast<char>(ch);
|
||||
};
|
||||
|
||||
// Decimal:
|
||||
|
||||
str_len=len;
|
||||
char* str = ppToken->name;
|
||||
if (ch == '.') {
|
||||
HasDecimalOrExponent = true;
|
||||
str[len++] = (char)ch;
|
||||
saveName(ch);
|
||||
ch = getChar();
|
||||
while (ch >= '0' && ch <= '9') {
|
||||
if (len < MaxTokenLength) {
|
||||
declen++;
|
||||
if (len > 0 || ch != '0') {
|
||||
str[len] = (char)ch;
|
||||
len++;
|
||||
str_len++;
|
||||
}
|
||||
ch = getChar();
|
||||
} else {
|
||||
parseContext.ppError(ppToken->loc, "float literal too long", "", "");
|
||||
len = 1;
|
||||
str_len = 1;
|
||||
}
|
||||
saveName(ch);
|
||||
ch = getChar();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -137,101 +127,74 @@ int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
|
|||
|
||||
if (ch == 'e' || ch == 'E') {
|
||||
HasDecimalOrExponent = true;
|
||||
if (len >= MaxTokenLength) {
|
||||
parseContext.ppError(ppToken->loc, "float literal too long", "", "");
|
||||
len = 1;
|
||||
str_len = 1;
|
||||
} else {
|
||||
str[len++] = (char)ch;
|
||||
saveName(ch);
|
||||
ch = getChar();
|
||||
if (ch == '+' || ch == '-') {
|
||||
saveName(ch);
|
||||
ch = getChar();
|
||||
if (ch == '+') {
|
||||
str[len++] = (char)ch;
|
||||
ch = getChar();
|
||||
} else if (ch == '-') {
|
||||
str[len++] = (char)ch;
|
||||
}
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
while (ch >= '0' && ch <= '9') {
|
||||
saveName(ch);
|
||||
ch = getChar();
|
||||
}
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
while (ch >= '0' && ch <= '9') {
|
||||
if (len < MaxTokenLength) {
|
||||
str[len++] = (char)ch;
|
||||
ch = getChar();
|
||||
} else {
|
||||
parseContext.ppError(ppToken->loc, "float literal too long", "", "");
|
||||
len = 1;
|
||||
str_len = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
parseContext.ppError(ppToken->loc, "bad character in float exponent", "", "");
|
||||
}
|
||||
} else {
|
||||
parseContext.ppError(ppToken->loc, "bad character in float exponent", "", "");
|
||||
}
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
ppToken->dval = 0.0;
|
||||
strcpy(str, "0.0");
|
||||
} else {
|
||||
if (ch == 'l' || ch == 'L') {
|
||||
parseContext.doubleCheck(ppToken->loc, "double floating-point suffix");
|
||||
if (! HasDecimalOrExponent)
|
||||
parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", "");
|
||||
int ch2 = getChar();
|
||||
if (ch2 != 'f' && ch2 != 'F') {
|
||||
ungetChar();
|
||||
ungetChar();
|
||||
} else {
|
||||
if (len < MaxTokenLength) {
|
||||
str[len++] = (char)ch;
|
||||
str[len++] = (char)ch2;
|
||||
isDouble = 1;
|
||||
} else {
|
||||
parseContext.ppError(ppToken->loc, "float literal too long", "", "");
|
||||
len = 1,str_len=1;
|
||||
}
|
||||
}
|
||||
#ifdef AMD_EXTENSIONS
|
||||
} else if (enableFloat16 && (ch == 'h' || ch == 'H')) {
|
||||
parseContext.float16Check(ppToken->loc, "half floating-point suffix");
|
||||
if (!HasDecimalOrExponent)
|
||||
parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", "");
|
||||
int ch2 = getChar();
|
||||
if (ch2 != 'f' && ch2 != 'F') {
|
||||
ungetChar();
|
||||
ungetChar();
|
||||
}
|
||||
else {
|
||||
if (len < MaxTokenLength) {
|
||||
str[len++] = (char)ch;
|
||||
str[len++] = (char)ch2;
|
||||
isFloat16 = 1;
|
||||
}
|
||||
else {
|
||||
parseContext.ppError(ppToken->loc, "float literal too long", "", "");
|
||||
len = 1, str_len = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else if (ch == 'f' || ch == 'F') {
|
||||
parseContext.profileRequires(ppToken->loc, EEsProfile, 300, nullptr, "floating-point suffix");
|
||||
if (! parseContext.relaxedErrors())
|
||||
parseContext.profileRequires(ppToken->loc, ~EEsProfile, 120, nullptr, "floating-point suffix");
|
||||
if (! HasDecimalOrExponent)
|
||||
parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", "");
|
||||
if (len < MaxTokenLength)
|
||||
str[len++] = (char)ch;
|
||||
else {
|
||||
parseContext.ppError(ppToken->loc, "float literal too long", "", "");
|
||||
len = 1,str_len=1;
|
||||
}
|
||||
} else
|
||||
// Suffix:
|
||||
|
||||
if (ch == 'l' || ch == 'L') {
|
||||
parseContext.doubleCheck(ppToken->loc, "double floating-point suffix");
|
||||
if (! HasDecimalOrExponent)
|
||||
parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", "");
|
||||
int ch2 = getChar();
|
||||
if (ch2 != 'f' && ch2 != 'F') {
|
||||
ungetChar();
|
||||
ungetChar();
|
||||
} else {
|
||||
saveName(ch);
|
||||
saveName(ch2);
|
||||
isDouble = 1;
|
||||
}
|
||||
#ifdef AMD_EXTENSIONS
|
||||
} else if (enableFloat16 && (ch == 'h' || ch == 'H')) {
|
||||
parseContext.float16Check(ppToken->loc, "half floating-point suffix");
|
||||
if (!HasDecimalOrExponent)
|
||||
parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", "");
|
||||
int ch2 = getChar();
|
||||
if (ch2 != 'f' && ch2 != 'F') {
|
||||
ungetChar();
|
||||
ungetChar();
|
||||
} else {
|
||||
saveName(ch);
|
||||
saveName(ch2);
|
||||
isFloat16 = 1;
|
||||
}
|
||||
#endif
|
||||
} else if (ch == 'f' || ch == 'F') {
|
||||
parseContext.profileRequires(ppToken->loc, EEsProfile, 300, nullptr, "floating-point suffix");
|
||||
if (! parseContext.relaxedErrors())
|
||||
parseContext.profileRequires(ppToken->loc, ~EEsProfile, 120, nullptr, "floating-point suffix");
|
||||
if (! HasDecimalOrExponent)
|
||||
parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", "");
|
||||
saveName(ch);
|
||||
} else
|
||||
ungetChar();
|
||||
|
||||
str[len]='\0';
|
||||
// Patch up the name, length, etc.
|
||||
|
||||
ppToken->dval = strtod(str, nullptr);
|
||||
if (len > MaxTokenLength) {
|
||||
len = MaxTokenLength;
|
||||
parseContext.ppError(ppToken->loc, "float literal too long", "", "");
|
||||
}
|
||||
ppToken->name[len] = '\0';
|
||||
|
||||
// Get the numerical value
|
||||
ppToken->dval = strtod(ppToken->name, nullptr);
|
||||
|
||||
// Return the right token type
|
||||
if (isDouble)
|
||||
return PpAtomConstDouble;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue