mirror of https://github.com/rusefi/lua.git
integer formats in 'string.format' may need to operate with larger-than-int
types
This commit is contained in:
parent
43c61fc113
commit
9fbefdf69c
57
lstrlib.c
57
lstrlib.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lstrlib.c,v 1.126 2005/10/23 17:46:30 roberto Exp roberto $
|
** $Id: lstrlib.c,v 1.127 2005/10/26 13:28:19 roberto Exp roberto $
|
||||||
** Standard library for string operations and pattern-matching
|
** Standard library for string operations and pattern-matching
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -683,8 +683,13 @@ static int str_gsub (lua_State *L) {
|
||||||
|
|
||||||
/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
|
/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
|
||||||
#define MAX_ITEM 512
|
#define MAX_ITEM 512
|
||||||
/* maximum size of each format specification (such as '%-099.99d') */
|
/* valid flags in a format specification */
|
||||||
#define MAX_FORMAT 20
|
#define FLAGS "-+ #0"
|
||||||
|
/*
|
||||||
|
** maximum size of each format specification (such as '%-099.99d')
|
||||||
|
** (+10 accounts for %99.99x plus margin of error)
|
||||||
|
*/
|
||||||
|
#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10)
|
||||||
|
|
||||||
|
|
||||||
static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
|
static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
|
||||||
|
@ -712,30 +717,37 @@ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
|
||||||
luaL_addchar(b, '"');
|
luaL_addchar(b, '"');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
|
||||||
static const char *scanformat (lua_State *L, const char *strfrmt,
|
|
||||||
char *form, int *hasprecision) {
|
|
||||||
const char *p = strfrmt;
|
const char *p = strfrmt;
|
||||||
while (strchr("-+ #0", *p)) p++; /* skip flags */
|
while (strchr(FLAGS, *p)) p++; /* skip flags */
|
||||||
|
if ((size_t)(p - strfrmt) >= sizeof(FLAGS))
|
||||||
|
luaL_error(L, "invalid format (repeated flags)");
|
||||||
if (isdigit(uchar(*p))) p++; /* skip width */
|
if (isdigit(uchar(*p))) p++; /* skip width */
|
||||||
if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
|
if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
|
||||||
if (*p == '.') {
|
if (*p == '.') {
|
||||||
p++;
|
p++;
|
||||||
*hasprecision = 1;
|
|
||||||
if (isdigit(uchar(*p))) p++; /* skip precision */
|
if (isdigit(uchar(*p))) p++; /* skip precision */
|
||||||
if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
|
if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
|
||||||
}
|
}
|
||||||
if (isdigit(uchar(*p)))
|
if (isdigit(uchar(*p)))
|
||||||
luaL_error(L, "invalid format (width or precision too long)");
|
luaL_error(L, "invalid format (width or precision too long)");
|
||||||
if (p-strfrmt+2 > MAX_FORMAT) /* +2 to include `%' and the specifier */
|
*(form++) = '%';
|
||||||
luaL_error(L, "invalid format (too long)");
|
strncpy(form, strfrmt, p - strfrmt + 1);
|
||||||
form[0] = L_ESC;
|
form += p - strfrmt + 1;
|
||||||
strncpy(form+1, strfrmt, p-strfrmt+1);
|
*form = '\0';
|
||||||
form[p-strfrmt+2] = 0;
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void addintlen (char *form) {
|
||||||
|
int l = strlen(form);
|
||||||
|
char spec = form[l - 1];
|
||||||
|
strcpy(form + l - 1, LUA_INTFRMLEN);
|
||||||
|
form[l + sizeof(LUA_INTFRMLEN) - 2] = spec;
|
||||||
|
form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int str_format (lua_State *L) {
|
static int str_format (lua_State *L) {
|
||||||
int arg = 1;
|
int arg = 1;
|
||||||
size_t sfl;
|
size_t sfl;
|
||||||
|
@ -751,21 +763,26 @@ static int str_format (lua_State *L) {
|
||||||
else { /* format item */
|
else { /* format item */
|
||||||
char form[MAX_FORMAT]; /* to store the format (`%...') */
|
char form[MAX_FORMAT]; /* to store the format (`%...') */
|
||||||
char buff[MAX_ITEM]; /* to store the formatted item */
|
char buff[MAX_ITEM]; /* to store the formatted item */
|
||||||
int hasprecision = 0;
|
|
||||||
arg++;
|
arg++;
|
||||||
strfrmt = scanformat(L, strfrmt, form, &hasprecision);
|
strfrmt = scanformat(L, strfrmt, form);
|
||||||
switch (*strfrmt++) {
|
switch (*strfrmt++) {
|
||||||
case 'c': case 'd': case 'i': {
|
case 'c': {
|
||||||
sprintf(buff, form, luaL_checkint(L, arg));
|
sprintf(buff, form, (int)luaL_checknumber(L, arg));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'd': case 'i': {
|
||||||
|
addintlen(form);
|
||||||
|
sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'o': case 'u': case 'x': case 'X': {
|
case 'o': case 'u': case 'x': case 'X': {
|
||||||
sprintf(buff, form, (unsigned int)(luaL_checknumber(L, arg)));
|
addintlen(form);
|
||||||
|
sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'e': case 'E': case 'f':
|
case 'e': case 'E': case 'f':
|
||||||
case 'g': case 'G': {
|
case 'g': case 'G': {
|
||||||
sprintf(buff, form, luaL_checknumber(L, arg));
|
sprintf(buff, form, (double)luaL_checknumber(L, arg));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'q': {
|
case 'q': {
|
||||||
|
@ -775,7 +792,7 @@ static int str_format (lua_State *L) {
|
||||||
case 's': {
|
case 's': {
|
||||||
size_t l;
|
size_t l;
|
||||||
const char *s = luaL_checklstring(L, arg, &l);
|
const char *s = luaL_checklstring(L, arg, &l);
|
||||||
if (!hasprecision && l >= 100) {
|
if (!strchr(form, '.') && l >= 100) {
|
||||||
/* no precision and string is too long to be formatted;
|
/* no precision and string is too long to be formatted;
|
||||||
keep original string */
|
keep original string */
|
||||||
lua_pushvalue(L, arg);
|
lua_pushvalue(L, arg);
|
||||||
|
|
22
luaconf.h
22
luaconf.h
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: luaconf.h,v 1.74 2005/11/16 16:24:28 roberto Exp roberto $
|
** $Id: luaconf.h,v 1.75 2005/11/25 13:29:11 roberto Exp roberto $
|
||||||
** Configuration file for Lua
|
** Configuration file for Lua
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -708,6 +708,26 @@ union luai_Cast { double l_d; long l_l; };
|
||||||
#define luai_userstateyield(L,n) ((void)L)
|
#define luai_userstateyield(L,n) ((void)L)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ LUA_INTFRMLEN is the length modifier for integer conversions
|
||||||
|
@* in 'string.fomat'.
|
||||||
|
@@ LUA_INTFRM_T is the integer type correspoding to the previous length
|
||||||
|
@* modifier.
|
||||||
|
** CHANGE them if your system supports long long or does not support long.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(LUA_USELONGLONG)
|
||||||
|
|
||||||
|
#define LUA_INTFRMLEN "ll"
|
||||||
|
#define LUA_INTFRM_T long long
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define LUA_INTFRMLEN "l"
|
||||||
|
#define LUA_INTFRM_T long
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* =================================================================== */
|
/* =================================================================== */
|
||||||
|
|
Loading…
Reference in New Issue