Skip to content

Commit

Permalink
Added hex float support since Cobalt has it
Browse files Browse the repository at this point in the history
  • Loading branch information
MCJack123 committed Dec 3, 2021
1 parent 4afe740 commit c9c4599
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 19 deletions.
11 changes: 11 additions & 0 deletions include/luaconf.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,13 @@
#define LUA_USE_POSIX
#define LUA_USE_DLOPEN /* needs an extra library: -ldl */
#define LUA_USE_READLINE /* needs some extra libraries */
#define LUA_USE_STRTODHEX
#endif

#if defined(LUA_USE_MACOSX)
#define LUA_USE_POSIX
#define LUA_DL_DYLD /* does not need extra library */
#define LUA_USE_STRTODHEX
#endif


Expand Down Expand Up @@ -520,13 +522,22 @@
@@ lua_number2str converts a number to a string.
@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion.
@@ lua_str2number converts a string to a number.
@@ lua_strx2number converts an hexadecimal numeric string to a number.
** In C99, 'strtod' does both conversions. C89, however, has no function
** to convert floating hexadecimal strings to numbers. For these
** systems, you can leave 'lua_strx2number' undefined and Lua will
** provide its own implementation.
*/
#define LUA_NUMBER_SCAN "%lf"
#define LUA_NUMBER_FMT "%.14g"
#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */
#define lua_str2number(s,p) strtod((s), (p))

#if defined(LUA_USE_STRTODHEX)
#define lua_strx2number(s,p) strtod((s), (p))
#endif


/*
@@ The luai_num* macros define the primitive operations over numbers.
Expand Down
23 changes: 14 additions & 9 deletions src/llex.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ static void trydecpoint (LexState *ls, SemInfo *seminfo) {
char old = ls->decpoint;
ls->decpoint = (cv ? cv->decimal_point[0] : '.');
buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */
if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) {
if (!luaO_str2d(luaZ_buffer(ls->buff), luaZ_sizebuffer(ls->buff), &seminfo->r)) {
/* format error with correct decimal point: no more options */
buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */
luaX_lexerror(ls, "malformed number", TK_NUMBER);
Expand All @@ -193,17 +193,22 @@ static void trydecpoint (LexState *ls, SemInfo *seminfo) {

/* LUA_NUMBER */
static void read_numeral (LexState *ls, SemInfo *seminfo) {
const char *expo = "Ee";
int first = ls->current;
lua_assert(isdigit(ls->current));
do {
save_and_next(ls);
} while (isdigit(ls->current) || ls->current == '.');
if (check_next(ls, "Ee")) /* `E'? */
check_next(ls, "+-"); /* optional exponent sign */
while (isalnum(ls->current) || ls->current == '_')
save_and_next(ls);
save_and_next(ls);
if (first == '0' && check_next(ls, "Xx")) /* hexadecimal? */
expo = "Pp";
for (;;) {
if (check_next(ls, expo)) /* exponent part? */
check_next(ls, "+-"); /* optional exponent sign */
if (isxdigit(ls->current) || ls->current == '.')
save_and_next(ls);
else break;
}
save(ls, '\0');
buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */
if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */
if (!luaO_str2d(luaZ_buffer(ls->buff), luaZ_bufflen(ls->buff) - 1, &seminfo->r)) /* format error? */
trydecpoint(ls, seminfo); /* try to update decimal point separator */
}

Expand Down
88 changes: 80 additions & 8 deletions src/lobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,88 @@ int luaO_rawequalObj (const TValue *t1, const TValue *t2) {
}


int luaO_str2d (const char *s, lua_Number *result) {
int luaO_hexavalue (int c) {
if (isdigit(c)) return c - '0';
else return tolower(c) - 'a' + 10;
}


#if !defined(lua_strx2number)

#include <math.h>


static int isneg (const char **s) {
if (**s == '-') { (*s)++; return 1; }
else if (**s == '+') (*s)++;
return 0;
}


static lua_Number readhexa (const char **s, lua_Number r, int *count) {
for (; isxdigit(cast(unsigned char, **s)); (*s)++) { /* read integer part */
r = (r * cast_num(16.0)) + cast_num(luaO_hexavalue(cast(unsigned char, **s)));
(*count)++;
}
return r;
}


/*
** convert an hexadecimal numeric string to a number, following
** C99 specification for 'strtod'
*/
static lua_Number lua_strx2number (const char *s, char **endptr) {
lua_Number r = 0.0;
int e = 0, i = 0;
int neg = 0; /* 1 if number is negative */
*endptr = cast(char *, s); /* nothing is valid yet */
while (isspace(cast(unsigned char, *s))) s++; /* skip initial spaces */
neg = isneg(&s); /* check signal */
if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */
return 0.0; /* invalid format (no '0x') */
s += 2; /* skip '0x' */
r = readhexa(&s, r, &i); /* read integer part */
if (*s == '.') {
s++; /* skip dot */
r = readhexa(&s, r, &e); /* read fractional part */
}
if (i == 0 && e == 0)
return 0.0; /* invalid format (no digit) */
e *= -4; /* each fractional digit divides value by 2^-4 */
*endptr = cast(char *, s); /* valid up to here */
if (*s == 'p' || *s == 'P') { /* exponent part? */
int exp1 = 0;
int neg1;
s++; /* skip 'p' */
neg1 = isneg(&s); /* signal */
if (!isdigit(cast(unsigned char, *s)))
goto ret; /* must have at least one digit */
while (isdigit(cast(unsigned char, *s))) /* read exponent */
exp1 = exp1 * 10 + *(s++) - '0';
if (neg1) exp1 = -exp1;
e += exp1;
}
*endptr = cast(char *, s); /* valid up to here */
ret:
if (neg) r = -r;
return ldexp(r, e);
}

#endif


int luaO_str2d (const char *s, size_t len, lua_Number *result) {
char *endptr;
*result = lua_str2number(s, &endptr);
if (endptr == s) return 0; /* conversion failed */
if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */
*result = cast_num(strtoul(s, &endptr, 16));
if (*endptr == '\0') return 1; /* most common case */
if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */
return 0;
else if (strpbrk(s, "xX")) /* hexa? */
*result = lua_strx2number(s, &endptr);
else
*result = lua_str2number(s, &endptr);
if (endptr == s) return 0; /* nothing recognized */
while (isspace(cast(unsigned char, *endptr))) endptr++;
if (*endptr != '\0') return 0; /* invalid trailing characters? */
return 1;
return (endptr == s + len); /* OK if no trailing characters */
}


Expand Down
2 changes: 1 addition & 1 deletion src/lobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ LUAI_FUNC int luaO_log2 (unsigned int x);
LUAI_FUNC int luaO_int2fb (unsigned int x);
LUAI_FUNC int luaO_fb2int (int x);
LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2);
LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result);
LUAI_FUNC int luaO_str2d (const char *s, size_t len, lua_Number *result);
LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
va_list argp);
LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
Expand Down
11 changes: 11 additions & 0 deletions src/luaconf.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,13 @@
#define LUA_USE_POSIX
#define LUA_USE_DLOPEN /* needs an extra library: -ldl */
#define LUA_USE_READLINE /* needs some extra libraries */
#define LUA_USE_STRTODHEX
#endif

#if defined(LUA_USE_MACOSX)
#define LUA_USE_POSIX
#define LUA_DL_DYLD /* does not need extra library */
#define LUA_USE_STRTODHEX
#endif


Expand Down Expand Up @@ -520,13 +522,22 @@
@@ lua_number2str converts a number to a string.
@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion.
@@ lua_str2number converts a string to a number.
@@ lua_strx2number converts an hexadecimal numeric string to a number.
** In C99, 'strtod' does both conversions. C89, however, has no function
** to convert floating hexadecimal strings to numbers. For these
** systems, you can leave 'lua_strx2number' undefined and Lua will
** provide its own implementation.
*/
#define LUA_NUMBER_SCAN "%lf"
#define LUA_NUMBER_FMT "%.14g"
#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */
#define lua_str2number(s,p) strtod((s), (p))

#if defined(LUA_USE_STRTODHEX)
#define lua_strx2number(s,p) strtod((s), (p))
#endif


/*
@@ The luai_num* macros define the primitive operations over numbers.
Expand Down
2 changes: 1 addition & 1 deletion src/lvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const TValue *luaV_tonumber (lua_State *L, const TValue *obj, TValue *n) {
if (ttisnumber(obj)) return obj;
resolverope(L, obj);
resolvesubstr(L, obj);
if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {
if (ttisstring(obj) && luaO_str2d(svalue(obj), tsvalue(obj)->len, &num)) {
setnvalue(n, num);
return n;
}
Expand Down

0 comments on commit c9c4599

Please sign in to comment.