diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-05-21 12:24:21 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-05-21 12:24:21 -0300 |
commit | e966e5379195a3414c0e8f6be6e25052702305ff (patch) | |
tree | 3207b4865ee1819e268d6577c377738d94d52603 | |
parent | c4eff10322f5e1e8213c9004f8b91c3c7bd36e3f (diff) | |
download | lua-e966e5379195a3414c0e8f6be6e25052702305ff.tar.gz lua-e966e5379195a3414c0e8f6be6e25052702305ff.tar.bz2 lua-e966e5379195a3414c0e8f6be6e25052702305ff.zip |
no more use of 'scanf' for reading numbers
-rw-r--r-- | liolib.c | 98 | ||||
-rw-r--r-- | luaconf.h | 11 |
2 files changed, 82 insertions, 27 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: liolib.c,v 2.123 2014/05/13 19:40:28 roberto Exp roberto $ | 2 | ** $Id: liolib.c,v 2.124 2014/05/15 15:21:06 roberto Exp $ |
3 | ** Standard I/O (and system) library | 3 | ** Standard I/O (and system) library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -15,7 +15,9 @@ | |||
15 | #endif | 15 | #endif |
16 | 16 | ||
17 | 17 | ||
18 | #include <ctype.h> | ||
18 | #include <errno.h> | 19 | #include <errno.h> |
20 | #include <locale.h> | ||
19 | #include <stdio.h> | 21 | #include <stdio.h> |
20 | #include <stdlib.h> | 22 | #include <stdlib.h> |
21 | #include <string.h> | 23 | #include <string.h> |
@@ -361,26 +363,91 @@ static int io_lines (lua_State *L) { | |||
361 | */ | 363 | */ |
362 | 364 | ||
363 | 365 | ||
364 | static int read_integer (lua_State *L, FILE *f) { | 366 | /* maximum length of a numeral */ |
365 | lua_Integer d; | 367 | #define MAXRN 200 |
366 | if (fscanf(f, LUA_INTEGER_SCAN, &d) == 1) { | 368 | |
367 | lua_pushinteger(L, d); | 369 | /* auxiliary structure used by 'read_number' */ |
368 | return 1; | 370 | typedef struct { |
369 | } | 371 | FILE *f; /* file being read */ |
372 | int c; /* current character (look ahead) */ | ||
373 | int n; /* number of elements in buffer 'buff' */ | ||
374 | char buff[MAXRN]; | ||
375 | } RN; | ||
376 | |||
377 | |||
378 | /* | ||
379 | ** Add current char to buffer (if not out of space) and read next one | ||
380 | */ | ||
381 | static int nextc (RN *rn) { | ||
382 | if (rn->n >= MAXRN) /* buffer overflow? */ | ||
383 | return 0; /* fail */ | ||
370 | else { | 384 | else { |
371 | lua_pushnil(L); /* "result" to be removed */ | 385 | rn->buff[rn->n++] = rn->c; /* save current char */ |
372 | return 0; /* read fails */ | 386 | rn->c = l_getc(rn->f); /* read next one */ |
387 | return 1; | ||
373 | } | 388 | } |
374 | } | 389 | } |
375 | 390 | ||
376 | 391 | ||
392 | /* | ||
393 | ** Accept current char if it is in 'set' (of size 1 or 2) | ||
394 | */ | ||
395 | static int test2 (RN *rn, const char *set) { | ||
396 | if (rn->c == set[0] || (rn->c == set[1] && rn->c != '\0')) | ||
397 | return nextc(rn); | ||
398 | else return 0; | ||
399 | } | ||
400 | |||
401 | |||
402 | /* | ||
403 | ** Read a sequence of (hexa)digits | ||
404 | */ | ||
405 | static int readdigits (RN *rn, int hexa) { | ||
406 | int count = 0; | ||
407 | while ((hexa ? isxdigit(rn->c) : isdigit(rn->c)) && nextc(rn)) | ||
408 | count++; | ||
409 | return count; | ||
410 | } | ||
411 | |||
412 | |||
413 | /* access to locale "radix character" (decimal point) */ | ||
414 | #if !defined(getlocaledecpoint) | ||
415 | #define getlocaledecpoint() (localeconv()->decimal_point[0]) | ||
416 | #endif | ||
417 | |||
418 | |||
419 | /* | ||
420 | ** Read a number: first reads a valid prefix of a numeral into a buffer. | ||
421 | ** Then it calls 'lua_strtonum' to check whether the format is correct | ||
422 | ** and to convert it to a Lua number | ||
423 | */ | ||
377 | static int read_number (lua_State *L, FILE *f) { | 424 | static int read_number (lua_State *L, FILE *f) { |
378 | lua_Number d; | 425 | RN rn; |
379 | if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { | 426 | int count = 0; |
380 | lua_pushnumber(L, d); | 427 | int hexa = 0; |
381 | return 1; | 428 | char decp[2] = "."; |
429 | rn.f = f; rn.n = 0; | ||
430 | decp[0] = getlocaledecpoint(); /* get decimal point from locale */ | ||
431 | l_lockfile(rn.f); | ||
432 | do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */ | ||
433 | test2(&rn, "-+"); /* optional signal */ | ||
434 | if (test2(&rn, "0")) { | ||
435 | if (test2(&rn, "xX")) hexa = 1; /* numeral is hexadecimal */ | ||
436 | else count = 1; /* count initial '0' as a valid digit */ | ||
382 | } | 437 | } |
383 | else { | 438 | count += readdigits(&rn, hexa); /* integral part */ |
439 | if (test2(&rn, decp)) /* decimal point? */ | ||
440 | count += readdigits(&rn, hexa); /* fractionary part */ | ||
441 | if (count > 0 && test2(&rn, (hexa ? "pP" : "eE"))) { /* exponent mark? */ | ||
442 | test2(&rn, "-+"); /* exponent signal */ | ||
443 | readdigits(&rn, 0); /* exponent digits */ | ||
444 | } | ||
445 | ungetc(rn.c, rn.f); /* unread look-ahead char */ | ||
446 | l_unlockfile(rn.f); | ||
447 | rn.buff[rn.n] = '\0'; /* finish string */ | ||
448 | if (lua_strtonum(L, rn.buff)) /* is this a valid number? */ | ||
449 | return 1; /* ok */ | ||
450 | else { /* invalid format */ | ||
384 | lua_pushnil(L); /* "result" to be removed */ | 451 | lua_pushnil(L); /* "result" to be removed */ |
385 | return 0; /* read fails */ | 452 | return 0; /* read fails */ |
386 | } | 453 | } |
@@ -456,9 +523,6 @@ static int g_read (lua_State *L, FILE *f, int first) { | |||
456 | const char *p = luaL_checkstring(L, n); | 523 | const char *p = luaL_checkstring(L, n); |
457 | if (*p == '*') p++; /* skip optional '*' (for compatibility) */ | 524 | if (*p == '*') p++; /* skip optional '*' (for compatibility) */ |
458 | switch (*p) { | 525 | switch (*p) { |
459 | case 'i': /* integer */ | ||
460 | success = read_integer(L, f); | ||
461 | break; | ||
462 | case 'n': /* number */ | 526 | case 'n': /* number */ |
463 | success = read_number(L, f); | 527 | success = read_number(L, f); |
464 | break; | 528 | break; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: luaconf.h,v 1.201 2014/05/11 13:03:48 roberto Exp roberto $ | 2 | ** $Id: luaconf.h,v 1.202 2014/05/15 15:24:32 roberto Exp roberto $ |
3 | ** Configuration file for Lua | 3 | ** Configuration file for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -431,7 +431,6 @@ | |||
431 | @@ over a floating number. | 431 | @@ over a floating number. |
432 | ** | 432 | ** |
433 | @@ LUA_NUMBER_FRMLEN is the length modifier for writing floats. | 433 | @@ LUA_NUMBER_FRMLEN is the length modifier for writing floats. |
434 | @@ LUA_NUMBER_SCAN is the format for reading floats. | ||
435 | @@ LUA_NUMBER_FMT is the format for writing floats. | 434 | @@ LUA_NUMBER_FMT is the format for writing floats. |
436 | @@ lua_number2str converts a float to a string. | 435 | @@ lua_number2str converts a float to a string. |
437 | ** | 436 | ** |
@@ -447,7 +446,6 @@ | |||
447 | #define LUAI_UACNUMBER double | 446 | #define LUAI_UACNUMBER double |
448 | 447 | ||
449 | #define LUA_NUMBER_FRMLEN "" | 448 | #define LUA_NUMBER_FRMLEN "" |
450 | #define LUA_NUMBER_SCAN "%f" | ||
451 | #define LUA_NUMBER_FMT "%.7g" | 449 | #define LUA_NUMBER_FMT "%.7g" |
452 | 450 | ||
453 | #define l_mathop(op) op##f | 451 | #define l_mathop(op) op##f |
@@ -462,7 +460,6 @@ | |||
462 | #define LUAI_UACNUMBER long double | 460 | #define LUAI_UACNUMBER long double |
463 | 461 | ||
464 | #define LUA_NUMBER_FRMLEN "L" | 462 | #define LUA_NUMBER_FRMLEN "L" |
465 | #define LUA_NUMBER_SCAN "%Lf" | ||
466 | #define LUA_NUMBER_FMT "%.19Lg" | 463 | #define LUA_NUMBER_FMT "%.19Lg" |
467 | 464 | ||
468 | #define l_mathop(op) op##l | 465 | #define l_mathop(op) op##l |
@@ -476,7 +473,6 @@ | |||
476 | #define LUAI_UACNUMBER double | 473 | #define LUAI_UACNUMBER double |
477 | 474 | ||
478 | #define LUA_NUMBER_FRMLEN "" | 475 | #define LUA_NUMBER_FRMLEN "" |
479 | #define LUA_NUMBER_SCAN "%lf" | ||
480 | #define LUA_NUMBER_FMT "%.14g" | 476 | #define LUA_NUMBER_FMT "%.14g" |
481 | 477 | ||
482 | #define l_mathop(op) op | 478 | #define l_mathop(op) op |
@@ -552,7 +548,6 @@ | |||
552 | @@ LUAI_UACINT is the result of an 'usual argument conversion' | 548 | @@ LUAI_UACINT is the result of an 'usual argument conversion' |
553 | @@ over a lUA_INTEGER. | 549 | @@ over a lUA_INTEGER. |
554 | @@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers. | 550 | @@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers. |
555 | @@ LUA_INTEGER_SCAN is the format for reading integers. | ||
556 | @@ LUA_INTEGER_FMT is the format for writing integers. | 551 | @@ LUA_INTEGER_FMT is the format for writing integers. |
557 | @@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER. | 552 | @@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER. |
558 | @@ LUA_MININTEGER is the minimum value for a LUA_INTEGER. | 553 | @@ LUA_MININTEGER is the minimum value for a LUA_INTEGER. |
@@ -563,7 +558,6 @@ | |||
563 | 558 | ||
564 | /* The following definitions are good for most cases here */ | 559 | /* The following definitions are good for most cases here */ |
565 | 560 | ||
566 | #define LUA_INTEGER_SCAN "%" LUA_INTEGER_FRMLEN "d" | ||
567 | #define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d" | 561 | #define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d" |
568 | #define lua_integer2str(s,n) sprintf((s), LUA_INTEGER_FMT, (n)) | 562 | #define lua_integer2str(s,n) sprintf((s), LUA_INTEGER_FMT, (n)) |
569 | 563 | ||
@@ -634,9 +628,6 @@ | |||
634 | #undef LUAI_UACINT | 628 | #undef LUAI_UACINT |
635 | #define LUAI_UACINT int | 629 | #define LUAI_UACINT int |
636 | 630 | ||
637 | #undef LUA_INTEGER_SCAN | ||
638 | #define LUA_INTEGER_SCAN "%hd" | ||
639 | |||
640 | #undef LUAI_MAXSTACK | 631 | #undef LUAI_MAXSTACK |
641 | #define LUAI_MAXSTACK 15000 | 632 | #define LUAI_MAXSTACK 15000 |
642 | 633 | ||