mirror of
https://github.com/ZDoom/Raze.git
synced 2024-11-16 09:21:36 +00:00
More rebust (and "correct"/expected) decimal number parsing in CON.
The replacement of atoi with strtol in r2374 had the side-effect that numbers out of the range of a 32-bit integer were being returned as LONG_MAX/LONG_MIN instead of being converted by taking the bits and re-interpreting them (note that it was a coincidence that atoi behaved that way; to be strict, the behavior was undefined and there is no regression). Now, we implement parsing decimal integers using strtoll (with assuming "long long" being the same as int64_t) and check in which range the number falls. If it's in the range (INT32_MAX <= x <= UINT32_MAX), issue a warning; if it's not in (INT32_MIN <= x <= UINT32_MAX), warn too (though this better ought to be an error?). In each case, the bit representation is converted to the CON number type (int32 to assume maximum portability) by re-interpreting the bits [this is the same as an int/int cast, with GCC at least; more generally, it's implementation-defined per C99]. git-svn-id: https://svn.eduke32.com/eduke32@2392 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
fc9609928f
commit
edb110b692
1 changed files with 47 additions and 8 deletions
|
@ -1462,6 +1462,37 @@ static int32_t C_GetNextKeyword(void) //Returns its code #
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t parse_decimal_number(void) // (textptr)
|
||||||
|
{
|
||||||
|
// decimal constants -- this is finicky business
|
||||||
|
int64_t num = strtoll(textptr, NULL, 10); // assume long long to be int64_t
|
||||||
|
|
||||||
|
if (num >= INT32_MIN && num <= INT32_MAX)
|
||||||
|
{
|
||||||
|
// all OK
|
||||||
|
}
|
||||||
|
else if (num > INT32_MAX && num <= UINT32_MAX)
|
||||||
|
{
|
||||||
|
// Number interpreted as uint32, but packed as int32 (on 32-bit archs)
|
||||||
|
// (CON code in the wild exists that does this). Note that such conversion
|
||||||
|
// is implementation-defined (C99 6.3.1.3) but GCC does the 'expected' thing.
|
||||||
|
|
||||||
|
initprintf("%s:%d: warning: number greater than INT32_MAX converted to a negative one.\n",
|
||||||
|
g_szScriptFileName,g_lineNumber);
|
||||||
|
g_numCompilerWarnings++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// out of range, this is arguably worse
|
||||||
|
|
||||||
|
initprintf("%s:%d: warning: number out of the range of a 32-bit integer encountered.\n",
|
||||||
|
g_szScriptFileName,g_lineNumber);
|
||||||
|
g_numCompilerWarnings++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int32_t)num;
|
||||||
|
}
|
||||||
|
|
||||||
static void C_GetNextVarType(int32_t type)
|
static void C_GetNextVarType(int32_t type)
|
||||||
{
|
{
|
||||||
int32_t i=0,f=0;
|
int32_t i=0,f=0;
|
||||||
|
@ -1470,14 +1501,19 @@ static void C_GetNextVarType(int32_t type)
|
||||||
|
|
||||||
if (!type && !g_labelsOnly && (isdigit(*textptr) || ((*textptr == '-') && (isdigit(*(textptr+1))))))
|
if (!type && !g_labelsOnly && (isdigit(*textptr) || ((*textptr == '-') && (isdigit(*(textptr+1))))))
|
||||||
{
|
{
|
||||||
if (!(g_numCompilerErrors || g_numCompilerWarnings) && g_scriptDebug)
|
|
||||||
initprintf("%s:%d: debug: accepted constant %ld in place of gamevar.\n",g_szScriptFileName,g_lineNumber,Batol(textptr));
|
|
||||||
bitptr[(g_scriptPtr-script)>>3] &= ~(BITPTR_POINTER<<((g_scriptPtr-script)&7));
|
bitptr[(g_scriptPtr-script)>>3] &= ~(BITPTR_POINTER<<((g_scriptPtr-script)&7));
|
||||||
*g_scriptPtr++=MAXGAMEVARS;
|
|
||||||
if (tolower(textptr[1])=='x')
|
*g_scriptPtr++ = MAXGAMEVARS;
|
||||||
|
|
||||||
|
if (tolower(textptr[1])=='x') // hex constants
|
||||||
sscanf(textptr+2,"%" PRIxPTR "",g_scriptPtr);
|
sscanf(textptr+2,"%" PRIxPTR "",g_scriptPtr);
|
||||||
else
|
else
|
||||||
*g_scriptPtr=Batoi(textptr);
|
*g_scriptPtr = parse_decimal_number();
|
||||||
|
|
||||||
|
if (!(g_numCompilerErrors || g_numCompilerWarnings) && g_scriptDebug)
|
||||||
|
initprintf("%s:%d: debug: accepted constant %ld in place of gamevar.\n",
|
||||||
|
g_szScriptFileName,g_lineNumber,(long)*g_scriptPtr);
|
||||||
|
|
||||||
bitptr[(g_scriptPtr-script)>>3] &= ~(BITPTR_POINTER<<((g_scriptPtr-script)&7));
|
bitptr[(g_scriptPtr-script)>>3] &= ~(BITPTR_POINTER<<((g_scriptPtr-script)&7));
|
||||||
g_scriptPtr++;
|
g_scriptPtr++;
|
||||||
#if 1
|
#if 1
|
||||||
|
@ -1505,6 +1541,7 @@ static void C_GetNextVarType(int32_t type)
|
||||||
|
|
||||||
textptr++;
|
textptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
C_GetNextLabelName();
|
C_GetNextLabelName();
|
||||||
|
|
||||||
if (!g_skipKeywordCheck && hash_find(&h_keywords,label+(g_numLabels<<6))>=0)
|
if (!g_skipKeywordCheck && hash_find(&h_keywords,label+(g_numLabels<<6))>=0)
|
||||||
|
@ -1801,14 +1838,16 @@ static int32_t C_GetNextValue(int32_t type)
|
||||||
}
|
}
|
||||||
while (i > 0);
|
while (i > 0);
|
||||||
|
|
||||||
if (!(g_numCompilerErrors || g_numCompilerWarnings) && g_scriptDebug > 1)
|
|
||||||
initprintf("%s:%d: debug: accepted constant %ld.\n",g_szScriptFileName,g_lineNumber,Batol(textptr));
|
|
||||||
bitptr[(g_scriptPtr-script)>>3] &= ~(BITPTR_POINTER<<((g_scriptPtr-script)&7));
|
bitptr[(g_scriptPtr-script)>>3] &= ~(BITPTR_POINTER<<((g_scriptPtr-script)&7));
|
||||||
|
|
||||||
if (tolower(textptr[1])=='x')
|
if (tolower(textptr[1])=='x')
|
||||||
sscanf(textptr+2,"%" PRIxPTR "",g_scriptPtr);
|
sscanf(textptr+2,"%" PRIxPTR "",g_scriptPtr);
|
||||||
else
|
else
|
||||||
*g_scriptPtr = Batol(textptr);
|
*g_scriptPtr = parse_decimal_number();
|
||||||
|
|
||||||
|
if (!(g_numCompilerErrors || g_numCompilerWarnings) && g_scriptDebug > 1)
|
||||||
|
initprintf("%s:%d: debug: accepted constant %ld.\n",
|
||||||
|
g_szScriptFileName,g_lineNumber,(long)*g_scriptPtr);
|
||||||
|
|
||||||
g_scriptPtr++;
|
g_scriptPtr++;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue