mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-14 16:31:38 +00:00
Fix up an __int64 networking issue. allow qc's sprintf builtin to print them ('q' modifier, also works for doubles when paired with the 'float' modifier as appropriate).
This commit is contained in:
parent
e48e9c67ad
commit
75166b0815
3 changed files with 110 additions and 36 deletions
|
@ -2264,9 +2264,9 @@ quint64_t MSG_ReadUInt64 (void)
|
|||
v-=l;
|
||||
b++;
|
||||
}
|
||||
r = v<<(b*8);
|
||||
r = (quint64_t)v<<(b*8);
|
||||
while(b --> 0)
|
||||
r |= MSG_ReadByte()<<(b*8);
|
||||
r |= (quint64_t)MSG_ReadByte()<<(b*8);
|
||||
return r;
|
||||
}
|
||||
qint64_t MSG_ReadInt64 (void)
|
||||
|
|
|
@ -7011,7 +7011,7 @@ void QCBUILTIN PF_sprintf_internal (pubprogfuncs_t *prinst, struct globalvars_s
|
|||
char formatbuf[16];
|
||||
char *f;
|
||||
int argpos = firstarg;
|
||||
int isfloat;
|
||||
int isfloat, is64bit;
|
||||
static int dummyivec[3] = {0, 0, 0};
|
||||
static float dummyvec[3] = {0, 0, 0};
|
||||
|
||||
|
@ -7024,11 +7024,18 @@ void QCBUILTIN PF_sprintf_internal (pubprogfuncs_t *prinst, struct globalvars_s
|
|||
formatbuf[0] = '%';
|
||||
|
||||
#define GETARG_FLOAT(a) (((a)>=firstarg && (a)<prinst->callargc) ? (G_FLOAT(OFS_PARM0 + 3 * (a))) : 0)
|
||||
#define GETARG_DOUBLE(a) (((a)>=firstarg && (a)<prinst->callargc) ? (G_FLOAT(OFS_PARM0 + 3 * (a))) : 0)
|
||||
#define GETARG_VECTOR(a) (((a)>=firstarg && (a)<prinst->callargc) ? (G_VECTOR(OFS_PARM0 + 3 * (a))) : dummyvec)
|
||||
#define GETARG_INT(a) (((a)>=firstarg && (a)<prinst->callargc) ? (G_INT(OFS_PARM0 + 3 * (a))) : 0)
|
||||
#define GETARG_INT64(a) (((a)>=firstarg && (a)<prinst->callargc) ? (G_INT64(OFS_PARM0 + 3 * (a))) : 0)
|
||||
#define GETARG_UINT(a) (((a)>=firstarg && (a)<prinst->callargc) ? (G_UINT(OFS_PARM0 + 3 * (a))) : 0)
|
||||
#define GETARG_UINT64(a) (((a)>=firstarg && (a)<prinst->callargc) ? (G_UINT64(OFS_PARM0 + 3 * (a))) : 0)
|
||||
#define GETARG_INTVECTOR(a) (((a)>=firstarg && (a)<prinst->callargc) ? ((int*) G_VECTOR(OFS_PARM0 + 3 * (a))) : dummyivec)
|
||||
#define GETARG_STRING(a) (((a)>=firstarg && (a)<prinst->callargc) ? (PR_GetStringOfs(prinst, OFS_PARM0 + 3 * (a))) : "")
|
||||
|
||||
#define GETARG_SNUMERIC(t, a) (is64bit?(isfloat ? (t) GETARG_DOUBLE(a) : (t) GETARG_INT64 (a)):(isfloat ? (t) GETARG_FLOAT(a) : (t) GETARG_INT (a)))
|
||||
#define GETARG_UNUMERIC(t, a) (is64bit?(isfloat ? (t) GETARG_DOUBLE(a) : (t) GETARG_UINT64(a)):(isfloat ? (t) GETARG_FLOAT(a) : (t) GETARG_UINT(a)))
|
||||
|
||||
for(;;)
|
||||
{
|
||||
s0 = s;
|
||||
|
@ -7050,6 +7057,7 @@ void QCBUILTIN PF_sprintf_internal (pubprogfuncs_t *prinst, struct globalvars_s
|
|||
thisarg = -1;
|
||||
flags = 0;
|
||||
isfloat = -1;
|
||||
is64bit = 0;
|
||||
|
||||
// is number following?
|
||||
if(*s >= '0' && *s <= '9')
|
||||
|
@ -7176,10 +7184,18 @@ noflags:
|
|||
{
|
||||
switch(*s)
|
||||
{
|
||||
/* note: this is technically a dp extension, so for our inputs:
|
||||
dp defined %lx for entity numbers (it not having actual ints)
|
||||
it later defined %llx for Actual ints, not that it makes a difference in DP.
|
||||
This leaves us unable to use C's 'l' for our int64 type (aka long), nor 'll' either.
|
||||
So lean on BSD's 'q'.
|
||||
|
||||
for our outputs, %llx is standard for int64 with MS violating c99 and requiring %I64x instead.
|
||||
*/
|
||||
case 'h': isfloat = 1; break; //short in C, interpreted as float here. doubled for char.
|
||||
case 'l': isfloat = 0; break; //long, twice for long long... we interpret as int32.
|
||||
case 'L': isfloat = 0; break; //'long double'
|
||||
//case 'q': isfloat = 0; break; //synonym for long long.
|
||||
case 'q': is64bit = 1; break; //BSD synonym for long long. or more specifically int64 and NOT int128.
|
||||
case 'j': break; //intmax_t
|
||||
//case 'Z': //synonym for 'z'. do not use
|
||||
case 'z': break; //size_t
|
||||
|
@ -7229,6 +7245,24 @@ nolength:
|
|||
*f++ = '.';
|
||||
*f++ = '*';
|
||||
}
|
||||
|
||||
switch(*s)
|
||||
{
|
||||
case 'd': case 'i': case 'I':
|
||||
case 'o': case 'u': case 'x': case 'X': case 'p': case 'P':
|
||||
#ifdef _WIN32 //not c99
|
||||
*f++ = 'I';
|
||||
*f++ = '6';
|
||||
*f++ = '4';
|
||||
#else //c99
|
||||
*f++ = 'l';
|
||||
if (sizeof(long) == 4)
|
||||
*f++ = 'l'; //go for long long instead
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (*s == 'p')
|
||||
*f++ = 'x';
|
||||
else if (*s == 'P')
|
||||
|
@ -7246,23 +7280,23 @@ nolength:
|
|||
{
|
||||
case 'd': case 'i': case 'I':
|
||||
if(precision < 0) // not set
|
||||
Q_snprintfz(o, end - o, formatbuf, width, (isfloat ? (int) GETARG_FLOAT(thisarg) : (int) GETARG_INT(thisarg)));
|
||||
Q_snprintfz(o, end - o, formatbuf, width, GETARG_SNUMERIC(qint64_t, thisarg));
|
||||
else
|
||||
Q_snprintfz(o, end - o, formatbuf, width, precision, (isfloat ? (int) GETARG_FLOAT(thisarg) : (int) GETARG_INT(thisarg)));
|
||||
Q_snprintfz(o, end - o, formatbuf, width, precision, GETARG_SNUMERIC(qint64_t, thisarg));
|
||||
o += strlen(o);
|
||||
break;
|
||||
case 'o': case 'u': case 'x': case 'X': case 'p': case 'P':
|
||||
if(precision < 0) // not set
|
||||
Q_snprintfz(o, end - o, formatbuf, width, (isfloat ? (unsigned int) GETARG_FLOAT(thisarg) : (unsigned int) GETARG_INT(thisarg)));
|
||||
Q_snprintfz(o, end - o, formatbuf, width, GETARG_UNUMERIC(quint64_t, thisarg));
|
||||
else
|
||||
Q_snprintfz(o, end - o, formatbuf, width, precision, (isfloat ? (unsigned int) GETARG_FLOAT(thisarg) : (unsigned int) GETARG_INT(thisarg)));
|
||||
Q_snprintfz(o, end - o, formatbuf, width, precision, GETARG_UNUMERIC(quint64_t, thisarg));
|
||||
o += strlen(o);
|
||||
break;
|
||||
case 'e': case 'E': case 'f': case 'F': case 'g': case 'G':
|
||||
if(precision < 0) // not set
|
||||
Q_snprintfz(o, end - o, formatbuf, width, (isfloat ? (double) GETARG_FLOAT(thisarg) : (double) GETARG_INT(thisarg)));
|
||||
Q_snprintfz(o, end - o, formatbuf, width, GETARG_SNUMERIC(double, thisarg));
|
||||
else
|
||||
Q_snprintfz(o, end - o, formatbuf, width, precision, (isfloat ? (double) GETARG_FLOAT(thisarg) : (double) GETARG_INT(thisarg)));
|
||||
Q_snprintfz(o, end - o, formatbuf, width, precision, GETARG_SNUMERIC(double, thisarg));
|
||||
o += strlen(o);
|
||||
break;
|
||||
case 'v': case 'V':
|
||||
|
|
|
@ -5919,7 +5919,7 @@ static void QCC_VerifyFormatString (const char *funcname, QCC_ref_t **arglist, u
|
|||
char formatbuf[16];
|
||||
char temp[256];
|
||||
int argpos = firstarg, argn_last = firstarg;
|
||||
int isfloat;
|
||||
int isfloat, is64bit;
|
||||
const QCC_eval_t *formatstring = QCC_SRef_EvalConst(arglist[0]->base);
|
||||
if (!formatstring) //can't check variables.
|
||||
return;
|
||||
|
@ -5952,6 +5952,7 @@ static void QCC_VerifyFormatString (const char *funcname, QCC_ref_t **arglist, u
|
|||
width = -1;
|
||||
thisarg = -1;
|
||||
isfloat = -1;
|
||||
is64bit = 0;
|
||||
|
||||
// is number following?
|
||||
if(*s >= '0' && *s <= '9')
|
||||
|
@ -6078,7 +6079,7 @@ noflags:
|
|||
//case 'll': //long long
|
||||
case 'l': isfloat = 0; break; //long
|
||||
case 'L': isfloat = 0; break; //long double
|
||||
//case 'q': break; //long long in c
|
||||
case 'q': is64bit = 1; break; //BSD's int64
|
||||
case 'j': //[u]intmax_t
|
||||
case 'z': //size_t
|
||||
case 't': //ptrdiff_t
|
||||
|
@ -6125,21 +6126,38 @@ nolength:
|
|||
case 'e': case 'E': case 'f': case 'F': case 'g': case 'G':
|
||||
if (isfloat)
|
||||
{
|
||||
switch(ARGTYPE(thisarg))
|
||||
if (is64bit)
|
||||
{
|
||||
case ev_float:
|
||||
case ev_variant:
|
||||
break;
|
||||
default:
|
||||
reqtype = "float";
|
||||
break;
|
||||
switch(ARGTYPE(thisarg))
|
||||
{
|
||||
case ev_double:
|
||||
case ev_variant:
|
||||
break;
|
||||
default:
|
||||
reqtype = "double";
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(ARGTYPE(thisarg))
|
||||
{
|
||||
case ev_float:
|
||||
case ev_variant:
|
||||
break;
|
||||
default:
|
||||
reqtype = "float";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*s == 'p' || *s == 'P')
|
||||
{
|
||||
switch(ARGTYPE(thisarg))
|
||||
if (is64bit)
|
||||
reqtype = "some kind of double-size pointer! oh noes!";
|
||||
else switch(ARGTYPE(thisarg))
|
||||
{
|
||||
case ev_pointer:
|
||||
case ev_variant:
|
||||
|
@ -6151,20 +6169,37 @@ nolength:
|
|||
}
|
||||
else
|
||||
{
|
||||
switch(ARGTYPE(thisarg))
|
||||
if (is64bit)
|
||||
{
|
||||
case ev_integer:
|
||||
case ev_uint:
|
||||
case ev_variant:
|
||||
break;
|
||||
case ev_entity: //accept ents ONLY for %i
|
||||
if (*s == 'i')
|
||||
switch(ARGTYPE(thisarg))
|
||||
{
|
||||
case ev_int64:
|
||||
case ev_uint64:
|
||||
case ev_variant:
|
||||
break;
|
||||
//fallthrough
|
||||
default:
|
||||
reqtype = "int";
|
||||
QCC_PR_ParseWarning(WARN_FORMATSTRING, "%s: %s%s%s requires int at arg %i (got %s%s%s)", funcname, col_name, formatbuf, col_none, thisarg+1, col_type, TypeName(ARGCTYPE(thisarg), temp, sizeof(temp)), col_none);
|
||||
break;
|
||||
default:
|
||||
reqtype = "__int64";
|
||||
QCC_PR_ParseWarning(WARN_FORMATSTRING, "%s: %s%s%s requires __int64 at arg %i (got %s%s%s)", funcname, col_name, formatbuf, col_none, thisarg+1, col_type, TypeName(ARGCTYPE(thisarg), temp, sizeof(temp)), col_none);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(ARGTYPE(thisarg))
|
||||
{
|
||||
case ev_integer:
|
||||
case ev_uint:
|
||||
case ev_variant:
|
||||
break;
|
||||
case ev_entity: //accept ents ONLY for %i
|
||||
if (*s == 'i')
|
||||
break;
|
||||
//fallthrough
|
||||
default:
|
||||
reqtype = "int";
|
||||
QCC_PR_ParseWarning(WARN_FORMATSTRING, "%s: %s%s%s requires int at arg %i (got %s%s%s)", funcname, col_name, formatbuf, col_none, thisarg+1, col_type, TypeName(ARGCTYPE(thisarg), temp, sizeof(temp)), col_none);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6228,14 +6263,19 @@ nolength:
|
|||
case ev_uint:
|
||||
QCC_PR_Note(WARN_FORMATSTRING, s_filen, pr_source_line, "%s", "use %lu or or %lx for 32bit ints");
|
||||
break;
|
||||
|
||||
case ev_int64:
|
||||
QCC_PR_Note(WARN_FORMATSTRING, s_filen, pr_source_line, "%s", "use %qi or %lqx for 64bit ints");
|
||||
break;
|
||||
case ev_uint64:
|
||||
QCC_PR_Note(WARN_FORMATSTRING, s_filen, pr_source_line, "%s", "use %lqu or or %lqx for 64bit ints");
|
||||
break;
|
||||
case ev_double:
|
||||
QCC_PR_Note(WARN_FORMATSTRING, s_filen, pr_source_line, "%s", "use %qg or %qf or %hqx for doubles");
|
||||
break;
|
||||
case ev_void: //coder's problem
|
||||
case ev_field: //cast to int
|
||||
case ev_function: //cast to int
|
||||
case ev_variant: //should be accepted by anything...
|
||||
case ev_int64: //specification problem
|
||||
case ev_uint64: //specification problem
|
||||
case ev_double: //specification problem
|
||||
case ev_struct: //coder's problem
|
||||
case ev_union: //coder's problem
|
||||
case ev_accessor: //should be unreachable
|
||||
|
|
Loading…
Reference in a new issue