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 | ||
