no more use of 'scanf' for reading numbers
This commit is contained in:
98
liolib.c
98
liolib.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: liolib.c,v 2.123 2014/05/13 19:40:28 roberto Exp roberto $
|
** $Id: liolib.c,v 2.124 2014/05/15 15:21:06 roberto Exp $
|
||||||
** Standard I/O (and system) library
|
** Standard I/O (and system) library
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -15,7 +15,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <locale.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -361,26 +363,91 @@ static int io_lines (lua_State *L) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
static int read_integer (lua_State *L, FILE *f) {
|
/* maximum length of a numeral */
|
||||||
lua_Integer d;
|
#define MAXRN 200
|
||||||
if (fscanf(f, LUA_INTEGER_SCAN, &d) == 1) {
|
|
||||||
lua_pushinteger(L, d);
|
/* auxiliary structure used by 'read_number' */
|
||||||
return 1;
|
typedef struct {
|
||||||
}
|
FILE *f; /* file being read */
|
||||||
|
int c; /* current character (look ahead) */
|
||||||
|
int n; /* number of elements in buffer 'buff' */
|
||||||
|
char buff[MAXRN];
|
||||||
|
} RN;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Add current char to buffer (if not out of space) and read next one
|
||||||
|
*/
|
||||||
|
static int nextc (RN *rn) {
|
||||||
|
if (rn->n >= MAXRN) /* buffer overflow? */
|
||||||
|
return 0; /* fail */
|
||||||
else {
|
else {
|
||||||
lua_pushnil(L); /* "result" to be removed */
|
rn->buff[rn->n++] = rn->c; /* save current char */
|
||||||
return 0; /* read fails */
|
rn->c = l_getc(rn->f); /* read next one */
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Accept current char if it is in 'set' (of size 1 or 2)
|
||||||
|
*/
|
||||||
|
static int test2 (RN *rn, const char *set) {
|
||||||
|
if (rn->c == set[0] || (rn->c == set[1] && rn->c != '\0'))
|
||||||
|
return nextc(rn);
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Read a sequence of (hexa)digits
|
||||||
|
*/
|
||||||
|
static int readdigits (RN *rn, int hexa) {
|
||||||
|
int count = 0;
|
||||||
|
while ((hexa ? isxdigit(rn->c) : isdigit(rn->c)) && nextc(rn))
|
||||||
|
count++;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* access to locale "radix character" (decimal point) */
|
||||||
|
#if !defined(getlocaledecpoint)
|
||||||
|
#define getlocaledecpoint() (localeconv()->decimal_point[0])
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Read a number: first reads a valid prefix of a numeral into a buffer.
|
||||||
|
** Then it calls 'lua_strtonum' to check whether the format is correct
|
||||||
|
** and to convert it to a Lua number
|
||||||
|
*/
|
||||||
static int read_number (lua_State *L, FILE *f) {
|
static int read_number (lua_State *L, FILE *f) {
|
||||||
lua_Number d;
|
RN rn;
|
||||||
if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
|
int count = 0;
|
||||||
lua_pushnumber(L, d);
|
int hexa = 0;
|
||||||
return 1;
|
char decp[2] = ".";
|
||||||
|
rn.f = f; rn.n = 0;
|
||||||
|
decp[0] = getlocaledecpoint(); /* get decimal point from locale */
|
||||||
|
l_lockfile(rn.f);
|
||||||
|
do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */
|
||||||
|
test2(&rn, "-+"); /* optional signal */
|
||||||
|
if (test2(&rn, "0")) {
|
||||||
|
if (test2(&rn, "xX")) hexa = 1; /* numeral is hexadecimal */
|
||||||
|
else count = 1; /* count initial '0' as a valid digit */
|
||||||
}
|
}
|
||||||
else {
|
count += readdigits(&rn, hexa); /* integral part */
|
||||||
|
if (test2(&rn, decp)) /* decimal point? */
|
||||||
|
count += readdigits(&rn, hexa); /* fractionary part */
|
||||||
|
if (count > 0 && test2(&rn, (hexa ? "pP" : "eE"))) { /* exponent mark? */
|
||||||
|
test2(&rn, "-+"); /* exponent signal */
|
||||||
|
readdigits(&rn, 0); /* exponent digits */
|
||||||
|
}
|
||||||
|
ungetc(rn.c, rn.f); /* unread look-ahead char */
|
||||||
|
l_unlockfile(rn.f);
|
||||||
|
rn.buff[rn.n] = '\0'; /* finish string */
|
||||||
|
if (lua_strtonum(L, rn.buff)) /* is this a valid number? */
|
||||||
|
return 1; /* ok */
|
||||||
|
else { /* invalid format */
|
||||||
lua_pushnil(L); /* "result" to be removed */
|
lua_pushnil(L); /* "result" to be removed */
|
||||||
return 0; /* read fails */
|
return 0; /* read fails */
|
||||||
}
|
}
|
||||||
@@ -456,9 +523,6 @@ static int g_read (lua_State *L, FILE *f, int first) {
|
|||||||
const char *p = luaL_checkstring(L, n);
|
const char *p = luaL_checkstring(L, n);
|
||||||
if (*p == '*') p++; /* skip optional '*' (for compatibility) */
|
if (*p == '*') p++; /* skip optional '*' (for compatibility) */
|
||||||
switch (*p) {
|
switch (*p) {
|
||||||
case 'i': /* integer */
|
|
||||||
success = read_integer(L, f);
|
|
||||||
break;
|
|
||||||
case 'n': /* number */
|
case 'n': /* number */
|
||||||
success = read_number(L, f);
|
success = read_number(L, f);
|
||||||
break;
|
break;
|
||||||
|
|||||||
11
luaconf.h
11
luaconf.h
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: luaconf.h,v 1.201 2014/05/11 13:03:48 roberto Exp roberto $
|
** $Id: luaconf.h,v 1.202 2014/05/15 15:24:32 roberto Exp roberto $
|
||||||
** Configuration file for Lua
|
** Configuration file for Lua
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -431,7 +431,6 @@
|
|||||||
@@ over a floating number.
|
@@ over a floating number.
|
||||||
**
|
**
|
||||||
@@ LUA_NUMBER_FRMLEN is the length modifier for writing floats.
|
@@ LUA_NUMBER_FRMLEN is the length modifier for writing floats.
|
||||||
@@ LUA_NUMBER_SCAN is the format for reading floats.
|
|
||||||
@@ LUA_NUMBER_FMT is the format for writing floats.
|
@@ LUA_NUMBER_FMT is the format for writing floats.
|
||||||
@@ lua_number2str converts a float to a string.
|
@@ lua_number2str converts a float to a string.
|
||||||
**
|
**
|
||||||
@@ -447,7 +446,6 @@
|
|||||||
#define LUAI_UACNUMBER double
|
#define LUAI_UACNUMBER double
|
||||||
|
|
||||||
#define LUA_NUMBER_FRMLEN ""
|
#define LUA_NUMBER_FRMLEN ""
|
||||||
#define LUA_NUMBER_SCAN "%f"
|
|
||||||
#define LUA_NUMBER_FMT "%.7g"
|
#define LUA_NUMBER_FMT "%.7g"
|
||||||
|
|
||||||
#define l_mathop(op) op##f
|
#define l_mathop(op) op##f
|
||||||
@@ -462,7 +460,6 @@
|
|||||||
#define LUAI_UACNUMBER long double
|
#define LUAI_UACNUMBER long double
|
||||||
|
|
||||||
#define LUA_NUMBER_FRMLEN "L"
|
#define LUA_NUMBER_FRMLEN "L"
|
||||||
#define LUA_NUMBER_SCAN "%Lf"
|
|
||||||
#define LUA_NUMBER_FMT "%.19Lg"
|
#define LUA_NUMBER_FMT "%.19Lg"
|
||||||
|
|
||||||
#define l_mathop(op) op##l
|
#define l_mathop(op) op##l
|
||||||
@@ -476,7 +473,6 @@
|
|||||||
#define LUAI_UACNUMBER double
|
#define LUAI_UACNUMBER double
|
||||||
|
|
||||||
#define LUA_NUMBER_FRMLEN ""
|
#define LUA_NUMBER_FRMLEN ""
|
||||||
#define LUA_NUMBER_SCAN "%lf"
|
|
||||||
#define LUA_NUMBER_FMT "%.14g"
|
#define LUA_NUMBER_FMT "%.14g"
|
||||||
|
|
||||||
#define l_mathop(op) op
|
#define l_mathop(op) op
|
||||||
@@ -552,7 +548,6 @@
|
|||||||
@@ LUAI_UACINT is the result of an 'usual argument conversion'
|
@@ LUAI_UACINT is the result of an 'usual argument conversion'
|
||||||
@@ over a lUA_INTEGER.
|
@@ over a lUA_INTEGER.
|
||||||
@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers.
|
@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers.
|
||||||
@@ LUA_INTEGER_SCAN is the format for reading integers.
|
|
||||||
@@ LUA_INTEGER_FMT is the format for writing integers.
|
@@ LUA_INTEGER_FMT is the format for writing integers.
|
||||||
@@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER.
|
@@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER.
|
||||||
@@ LUA_MININTEGER is the minimum value for a LUA_INTEGER.
|
@@ LUA_MININTEGER is the minimum value for a LUA_INTEGER.
|
||||||
@@ -563,7 +558,6 @@
|
|||||||
|
|
||||||
/* The following definitions are good for most cases here */
|
/* The following definitions are good for most cases here */
|
||||||
|
|
||||||
#define LUA_INTEGER_SCAN "%" LUA_INTEGER_FRMLEN "d"
|
|
||||||
#define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d"
|
#define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d"
|
||||||
#define lua_integer2str(s,n) sprintf((s), LUA_INTEGER_FMT, (n))
|
#define lua_integer2str(s,n) sprintf((s), LUA_INTEGER_FMT, (n))
|
||||||
|
|
||||||
@@ -634,9 +628,6 @@
|
|||||||
#undef LUAI_UACINT
|
#undef LUAI_UACINT
|
||||||
#define LUAI_UACINT int
|
#define LUAI_UACINT int
|
||||||
|
|
||||||
#undef LUA_INTEGER_SCAN
|
|
||||||
#define LUA_INTEGER_SCAN "%hd"
|
|
||||||
|
|
||||||
#undef LUAI_MAXSTACK
|
#undef LUAI_MAXSTACK
|
||||||
#define LUAI_MAXSTACK 15000
|
#define LUAI_MAXSTACK 15000
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user