diff options
| author | Philipp Janda <siffiejoe@gmx.net> | 2017-09-16 17:27:20 +0200 |
|---|---|---|
| committer | Philipp Janda <siffiejoe@gmx.net> | 2017-09-16 17:27:20 +0200 |
| commit | c381aa35a9ca135aba4f512728c11e7fe14b12d0 (patch) | |
| tree | e56be07e08699f920482212f07342acf8f9526ae | |
| parent | 9435c6c2e1f1373a5a9ffdb85a1a63ee0b7e6057 (diff) | |
| parent | 09b201c87c904066e1de5d44cf1e02538970c168 (diff) | |
| download | lua-compat-5.3-c381aa35a9ca135aba4f512728c11e7fe14b12d0.tar.gz lua-compat-5.3-c381aa35a9ca135aba4f512728c11e7fe14b12d0.tar.bz2 lua-compat-5.3-c381aa35a9ca135aba4f512728c11e7fe14b12d0.zip | |
Merge branch 'ThePhD-feature/luaL_loadfilebufferx'
| -rw-r--r-- | README.md | 7 | ||||
| -rw-r--r-- | c-api/compat-5.3.c | 289 | ||||
| -rw-r--r-- | c-api/compat-5.3.h | 11 | ||||
| -rwxr-xr-x | tests/test.lua | 157 | ||||
| -rw-r--r-- | tests/testmod.c | 29 |
5 files changed, 421 insertions, 72 deletions
| @@ -151,6 +151,7 @@ For Lua 5.1 additionally: | |||
| 151 | * `lua_arith` (see [here][20]) | 151 | * `lua_arith` (see [here][20]) |
| 152 | * `lua_compare` | 152 | * `lua_compare` |
| 153 | * `lua_len`, `lua_rawlen`, and `luaL_len` | 153 | * `lua_len`, `lua_rawlen`, and `luaL_len` |
| 154 | * `lua_load` (mode argument) | ||
| 154 | * `lua_pushstring`, `lua_pushlstring` (return value) | 155 | * `lua_pushstring`, `lua_pushlstring` (return value) |
| 155 | * `lua_copy` | 156 | * `lua_copy` |
| 156 | * `lua_pushglobaltable` | 157 | * `lua_pushglobaltable` |
| @@ -161,6 +162,8 @@ For Lua 5.1 additionally: | |||
| 161 | * `luaL_traceback` | 162 | * `luaL_traceback` |
| 162 | * `luaL_execresult` | 163 | * `luaL_execresult` |
| 163 | * `luaL_fileresult` | 164 | * `luaL_fileresult` |
| 165 | * `luaL_loadbufferx` | ||
| 166 | * `luaL_loadfilex` | ||
| 164 | * `luaL_checkversion` (with empty body, only to avoid compile errors, | 167 | * `luaL_checkversion` (with empty body, only to avoid compile errors, |
| 165 | see [here][21]) | 168 | see [here][21]) |
| 166 | * `luaL_tolstring` | 169 | * `luaL_tolstring` |
| @@ -188,8 +191,6 @@ For Lua 5.1 additionally: | |||
| 188 | * `lua_upvaluejoin` (5.1) | 191 | * `lua_upvaluejoin` (5.1) |
| 189 | * `lua_version` (5.1) | 192 | * `lua_version` (5.1) |
| 190 | * `lua_yieldk` (5.1) | 193 | * `lua_yieldk` (5.1) |
| 191 | * `luaL_loadbufferx` (5.1) | ||
| 192 | * `luaL_loadfilex` (5.1) | ||
| 193 | 194 | ||
| 194 | ## See also | 195 | ## See also |
| 195 | 196 | ||
| @@ -206,6 +207,8 @@ This package contains code written by: | |||
| 206 | * Tomás Guisasola Gorham ([@tomasguisasola](http://github.com/tomasguisasola)) | 207 | * Tomás Guisasola Gorham ([@tomasguisasola](http://github.com/tomasguisasola)) |
| 207 | * Hisham Muhammad ([@hishamhm](http://github.com/hishamhm)) | 208 | * Hisham Muhammad ([@hishamhm](http://github.com/hishamhm)) |
| 208 | * Renato Maia ([@renatomaia](http://github.com/renatomaia)) | 209 | * Renato Maia ([@renatomaia](http://github.com/renatomaia)) |
| 210 | * [@ThePhD](http://github.com/ThePhD) | ||
| 211 | * [@Daurnimator](http://github.com/Daurnimator) | ||
| 209 | 212 | ||
| 210 | 213 | ||
| 211 | [1]: http://www.inf.puc-rio.br/~roberto/struct/ | 214 | [1]: http://www.inf.puc-rio.br/~roberto/struct/ |
diff --git a/c-api/compat-5.3.c b/c-api/compat-5.3.c index 811f248..e87808c 100644 --- a/c-api/compat-5.3.c +++ b/c-api/compat-5.3.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | #include <string.h> | 3 | #include <string.h> |
| 4 | #include <ctype.h> | 4 | #include <ctype.h> |
| 5 | #include <errno.h> | 5 | #include <errno.h> |
| 6 | #include <stdio.h> | ||
| 6 | #include "compat-5.3.h" | 7 | #include "compat-5.3.h" |
| 7 | 8 | ||
| 8 | /* don't compile it again if it already is included via compat53.h */ | 9 | /* don't compile it again if it already is included via compat53.h */ |
| @@ -14,6 +15,94 @@ | |||
| 14 | /* definitions for Lua 5.1 only */ | 15 | /* definitions for Lua 5.1 only */ |
| 15 | #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 | 16 | #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 |
| 16 | 17 | ||
| 18 | #ifndef COMPAT53_FOPEN_NO_LOCK | ||
| 19 | # if defined(_MSC_VER) | ||
| 20 | # define COMPAT53_FOPEN_NO_LOCK 1 | ||
| 21 | # else /* otherwise */ | ||
| 22 | # define COMPAT53_FOPEN_NO_LOCK 0 | ||
| 23 | # endif /* VC++ only so far */ | ||
| 24 | #endif /* No-lock fopen_s usage if possible */ | ||
| 25 | |||
| 26 | #if defined(_MSC_VER) && COMPAT53_FOPEN_NO_LOCK | ||
| 27 | #include <share.h> | ||
| 28 | #endif /* VC++ _fsopen for share-allowed file read */ | ||
| 29 | |||
| 30 | #ifndef COMPAT53_HAVE_STRERROR_R | ||
| 31 | # if defined(__GLIBC__) || defined(_POSIX_VERSION) || defined(__APPLE__) || \ | ||
| 32 | (!defined (__MINGW32__) && defined(__GNUC__) && (__GNUC__ < 6)) | ||
| 33 | # define COMPAT53_HAVE_STRERROR_R 1 | ||
| 34 | # if ((defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || \ | ||
| 35 | (defined(_XOPEN_SOURCE) || _XOPEN_SOURCE >= 600)) && \ | ||
| 36 | (!defined(_GNU_SOURCE) || !_GNU_SOURCE) | ||
| 37 | # ifndef COMPAT53_HAVE_STRERROR_R_XSI | ||
| 38 | # define COMPAT53_HAVE_STRERROR_R_XSI 1 | ||
| 39 | # endif /* XSI-Compliant strerror_r */ | ||
| 40 | # ifndef COMPAT53_HAVE_STRERROR_R_GNU | ||
| 41 | # define COMPAT53_HAVE_STRERROR_R_GNU 0 | ||
| 42 | # endif /* GNU strerror_r */ | ||
| 43 | # else /* XSI/Posix vs. GNU strerror_r */ | ||
| 44 | # ifndef COMPAT53_HAVE_STRERROR_R_GNU | ||
| 45 | # define COMPAT53_HAVE_STRERROR_R_GNU 1 | ||
| 46 | # endif /* GNU variant strerror_r */ | ||
| 47 | # ifndef COMPAT53_HAVE_STRERROR_R_XSI | ||
| 48 | # define COMPAT53_HAVE_STRERROR_R_XSI 0 | ||
| 49 | # endif /* XSI strerror_r */ | ||
| 50 | # endif /* XSI/Posix vs. GNU strerror_r */ | ||
| 51 | # else /* none of the defines matched: define to 0 */ | ||
| 52 | # define COMPAT53_HAVE_STRERROR_R 0 | ||
| 53 | # ifndef COMPAT53_HAVE_STRERROR_R_XSI | ||
| 54 | # define COMPAT53_HAVE_STRERROR_R_XSI 0 | ||
| 55 | # endif /* XSI strerror_r */ | ||
| 56 | # ifndef COMPAT53_HAVE_STRERROR_R_GNU | ||
| 57 | # define COMPAT53_HAVE_STRERROR_R_GNU 0 | ||
| 58 | # endif /* GNU strerror_r */ | ||
| 59 | # endif /* have strerror_r of some form */ | ||
| 60 | #endif /* strerror_r */ | ||
| 61 | |||
| 62 | #ifndef COMPAT53_HAVE_STRERROR_S | ||
| 63 | # if defined(_MSC_VER) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \ | ||
| 64 | (defined(__STDC_LIB_EXT1__) && __STDC_LIB_EXT1__) | ||
| 65 | # define COMPAT53_HAVE_STRERROR_S 1 | ||
| 66 | # else /* not VC++ or C11 */ | ||
| 67 | # define COMPAT53_HAVE_STRERROR_S 0 | ||
| 68 | # endif /* strerror_s from VC++ or C11 */ | ||
| 69 | #endif /* strerror_s */ | ||
| 70 | |||
| 71 | #ifndef COMPAT53_LUA_FILE_BUFFER_SIZE | ||
| 72 | #define COMPAT53_LUA_FILE_BUFFER_SIZE 4096 | ||
| 73 | #endif /* Lua File Buffer Size */ | ||
| 74 | |||
| 75 | |||
| 76 | static char* compat53_strerror (int en, char* buff, size_t sz) { | ||
| 77 | #if COMPAT53_HAVE_STRERROR_R | ||
| 78 | /* use strerror_r here, because it's available on these specific platforms */ | ||
| 79 | #if COMPAT53_HAVE_STRERROR_R_XSI | ||
| 80 | /* XSI Compliant */ | ||
| 81 | strerror_r(en, buff, sz); | ||
| 82 | return buff; | ||
| 83 | #else | ||
| 84 | /* GNU-specific which returns const char* */ | ||
| 85 | return strerror_r(en, buff, sz); | ||
| 86 | #endif | ||
| 87 | #elif COMPAT53_HAVE_STRERROR_S | ||
| 88 | /* for MSVC and other C11 implementations, use strerror_s | ||
| 89 | * since it's provided by default by the libraries | ||
| 90 | */ | ||
| 91 | strerror_s(buff, sz, en); | ||
| 92 | return buff; | ||
| 93 | #else | ||
| 94 | /* fallback, but | ||
| 95 | * strerror is not guaranteed to be threadsafe due to modifying | ||
| 96 | * errno itself and some impls not locking a static buffer for it | ||
| 97 | * ... but most known systems have threadsafe errno: this might only change | ||
| 98 | * if the locale is changed out from under someone while this function is being called | ||
| 99 | */ | ||
| 100 | (void)buff; | ||
| 101 | (void)sz; | ||
| 102 | return strerror(en); | ||
| 103 | #endif | ||
| 104 | } | ||
| 105 | |||
| 17 | 106 | ||
| 18 | COMPAT53_API int lua_absindex (lua_State *L, int i) { | 107 | COMPAT53_API int lua_absindex (lua_State *L, int i) { |
| 19 | if (i < 0 && i > LUA_REGISTRYINDEX) | 108 | if (i < 0 && i > LUA_REGISTRYINDEX) |
| @@ -336,23 +425,219 @@ COMPAT53_API void luaL_traceback (lua_State *L, lua_State *L1, | |||
| 336 | 425 | ||
| 337 | 426 | ||
| 338 | COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { | 427 | COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { |
| 428 | const char *serr = NULL; | ||
| 339 | int en = errno; /* calls to Lua API may change this value */ | 429 | int en = errno; /* calls to Lua API may change this value */ |
| 430 | char buf[512] = { 0 }; | ||
| 340 | if (stat) { | 431 | if (stat) { |
| 341 | lua_pushboolean(L, 1); | 432 | lua_pushboolean(L, 1); |
| 342 | return 1; | 433 | return 1; |
| 343 | } | 434 | } |
| 344 | else { | 435 | else { |
| 345 | lua_pushnil(L); | 436 | lua_pushnil(L); |
| 437 | serr = compat53_strerror(en, buf, sizeof(buf)); | ||
| 346 | if (fname) | 438 | if (fname) |
| 347 | lua_pushfstring(L, "%s: %s", fname, strerror(en)); | 439 | lua_pushfstring(L, "%s: %s", fname, serr); |
| 348 | else | 440 | else |
| 349 | lua_pushstring(L, strerror(en)); | 441 | lua_pushstring(L, serr); |
| 350 | lua_pushnumber(L, (lua_Number)en); | 442 | lua_pushnumber(L, (lua_Number)en); |
| 351 | return 3; | 443 | return 3; |
| 352 | } | 444 | } |
| 353 | } | 445 | } |
| 354 | 446 | ||
| 355 | 447 | ||
| 448 | static int compat53_checkmode (lua_State *L, const char *mode, const char *modename, int err) { | ||
| 449 | if (mode && strchr(mode, modename[0]) == NULL) { | ||
| 450 | lua_pushfstring(L, "attempt to load a %s chunk (mode is '%s')", modename, mode); | ||
| 451 | return err; | ||
| 452 | } | ||
| 453 | return LUA_OK; | ||
| 454 | } | ||
| 455 | |||
| 456 | |||
| 457 | typedef struct { | ||
| 458 | lua_Reader reader; | ||
| 459 | void *ud; | ||
| 460 | int has_peeked_data; | ||
| 461 | const char *peeked_data; | ||
| 462 | size_t peeked_data_size; | ||
| 463 | } compat53_reader_data; | ||
| 464 | |||
| 465 | |||
| 466 | static const char *compat53_reader (lua_State *L, void *ud, size_t *size) { | ||
| 467 | compat53_reader_data *data = (compat53_reader_data *)ud; | ||
| 468 | if (data->has_peeked_data) { | ||
| 469 | data->has_peeked_data = 0; | ||
| 470 | *size = data->peeked_data_size; | ||
| 471 | return data->peeked_data; | ||
| 472 | } else | ||
| 473 | return data->reader(L, data->ud, size); | ||
| 474 | } | ||
| 475 | |||
| 476 | |||
| 477 | COMPAT53_API int lua_load (lua_State *L, lua_Reader reader, void *data, const char *source, const char *mode) { | ||
| 478 | int status = LUA_OK; | ||
| 479 | compat53_reader_data compat53_data = { reader, data, 1, 0, 0 }; | ||
| 480 | compat53_data.peeked_data = reader(L, data, &(compat53_data.peeked_data_size)); | ||
| 481 | if (compat53_data.peeked_data && compat53_data.peeked_data_size && | ||
| 482 | compat53_data.peeked_data[0] == LUA_SIGNATURE[0]) /* binary file? */ | ||
| 483 | status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX); | ||
| 484 | else | ||
| 485 | status = compat53_checkmode(L, mode, "text", LUA_ERRSYNTAX); | ||
| 486 | if (status != LUA_OK) | ||
| 487 | return status; | ||
| 488 | /* we need to call the original 5.1 version of lua_load! */ | ||
| 489 | #undef lua_load | ||
| 490 | return lua_load(L, compat53_reader, &compat53_data, source); | ||
| 491 | #define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53) | ||
| 492 | } | ||
| 493 | |||
| 494 | |||
| 495 | typedef struct { | ||
| 496 | int n; /* number of pre-read characters */ | ||
| 497 | FILE *f; /* file being read */ | ||
| 498 | char buff[COMPAT53_LUA_FILE_BUFFER_SIZE]; /* area for reading file */ | ||
| 499 | } compat53_LoadF; | ||
| 500 | |||
| 501 | |||
| 502 | static const char *compat53_getF (lua_State *L, void *ud, size_t *size) { | ||
| 503 | compat53_LoadF *lf = (compat53_LoadF *)ud; | ||
| 504 | (void)L; /* not used */ | ||
| 505 | if (lf->n > 0) { /* are there pre-read characters to be read? */ | ||
| 506 | *size = lf->n; /* return them (chars already in buffer) */ | ||
| 507 | lf->n = 0; /* no more pre-read characters */ | ||
| 508 | } | ||
| 509 | else { /* read a block from file */ | ||
| 510 | /* 'fread' can return > 0 *and* set the EOF flag. If next call to | ||
| 511 | 'compat53_getF' called 'fread', it might still wait for user input. | ||
| 512 | The next check avoids this problem. */ | ||
| 513 | if (feof(lf->f)) return NULL; | ||
| 514 | *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */ | ||
| 515 | } | ||
| 516 | return lf->buff; | ||
| 517 | } | ||
| 518 | |||
| 519 | |||
| 520 | static int compat53_errfile (lua_State *L, const char *what, int fnameindex) { | ||
| 521 | char buf[512] = {0}; | ||
| 522 | const char *serr = compat53_strerror(errno, buf, sizeof(buf)); | ||
| 523 | const char *filename = lua_tostring(L, fnameindex) + 1; | ||
| 524 | lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); | ||
| 525 | lua_remove(L, fnameindex); | ||
| 526 | return LUA_ERRFILE; | ||
| 527 | } | ||
| 528 | |||
| 529 | |||
| 530 | static int compat53_skipBOM (compat53_LoadF *lf) { | ||
| 531 | const char *p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */ | ||
| 532 | int c; | ||
| 533 | lf->n = 0; | ||
| 534 | do { | ||
| 535 | c = getc(lf->f); | ||
| 536 | if (c == EOF || c != *(const unsigned char *)p++) return c; | ||
| 537 | lf->buff[lf->n++] = c; /* to be read by the parser */ | ||
| 538 | } while (*p != '\0'); | ||
| 539 | lf->n = 0; /* prefix matched; discard it */ | ||
| 540 | return getc(lf->f); /* return next character */ | ||
| 541 | } | ||
| 542 | |||
| 543 | |||
| 544 | /* | ||
| 545 | ** reads the first character of file 'f' and skips an optional BOM mark | ||
| 546 | ** in its beginning plus its first line if it starts with '#'. Returns | ||
| 547 | ** true if it skipped the first line. In any case, '*cp' has the | ||
| 548 | ** first "valid" character of the file (after the optional BOM and | ||
| 549 | ** a first-line comment). | ||
| 550 | */ | ||
| 551 | static int compat53_skipcomment (compat53_LoadF *lf, int *cp) { | ||
| 552 | int c = *cp = compat53_skipBOM(lf); | ||
| 553 | if (c == '#') { /* first line is a comment (Unix exec. file)? */ | ||
| 554 | do { /* skip first line */ | ||
| 555 | c = getc(lf->f); | ||
| 556 | } while (c != EOF && c != '\n'); | ||
| 557 | *cp = getc(lf->f); /* skip end-of-line, if present */ | ||
| 558 | return 1; /* there was a comment */ | ||
| 559 | } | ||
| 560 | else return 0; /* no comment */ | ||
| 561 | } | ||
| 562 | |||
| 563 | |||
| 564 | COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode) { | ||
| 565 | compat53_LoadF lf; | ||
| 566 | int status, readstatus; | ||
| 567 | int c; | ||
| 568 | int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ | ||
| 569 | if (filename == NULL) { | ||
| 570 | lua_pushliteral(L, "=stdin"); | ||
| 571 | lf.f = stdin; | ||
| 572 | } | ||
| 573 | else { | ||
| 574 | lua_pushfstring(L, "@%s", filename); | ||
| 575 | #if defined(_MSC_VER) | ||
| 576 | /* This code is here to stop a deprecation error that stops builds | ||
| 577 | * if a certain macro is defined. While normally not caring would | ||
| 578 | * be best, some header-only libraries and builds can't afford to | ||
| 579 | * dictate this to the user. A quick check shows that fopen_s this | ||
| 580 | * goes back to VS 2005, and _fsopen goes back to VS 2003 .NET, | ||
| 581 | * possibly even before that so we don't need to do any version | ||
| 582 | * number checks, since this has been there since forever. | ||
| 583 | */ | ||
| 584 | |||
| 585 | /* TO USER: if you want the behavior of typical fopen_s/fopen, | ||
| 586 | * which does lock the file on VC++, define the macro used below to 0 | ||
| 587 | */ | ||
| 588 | #if COMPAT53_FOPEN_NO_LOCK | ||
| 589 | lf.f = _fsopen(filename, "r", _SH_DENYNO); /* do not lock the file in any way */ | ||
| 590 | if (lf.f == NULL) | ||
| 591 | return compat53_errfile(L, "open", fnameindex); | ||
| 592 | #else /* use default locking version */ | ||
| 593 | if (fopen_s(&lf.f, filename, "r") != 0) | ||
| 594 | return compat53_errfile(L, "open", fnameindex); | ||
| 595 | #endif /* Locking vs. No-locking fopen variants */ | ||
| 596 | #else | ||
| 597 | lf.f = fopen(filename, "r"); /* default stdlib doesn't forcefully lock files here */ | ||
| 598 | if (lf.f == NULL) return compat53_errfile(L, "open", fnameindex); | ||
| 599 | #endif | ||
| 600 | } | ||
| 601 | if (compat53_skipcomment(&lf, &c)) /* read initial portion */ | ||
| 602 | lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ | ||
| 603 | if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ | ||
| 604 | #if defined(_MSC_VER) | ||
| 605 | if (freopen_s(&lf.f, filename, "rb", lf.f) != 0) | ||
| 606 | return compat53_errfile(L, "reopen", fnameindex); | ||
| 607 | #else | ||
| 608 | lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ | ||
| 609 | if (lf.f == NULL) return compat53_errfile(L, "reopen", fnameindex); | ||
| 610 | #endif | ||
| 611 | compat53_skipcomment(&lf, &c); /* re-read initial portion */ | ||
| 612 | } | ||
| 613 | if (c != EOF) | ||
| 614 | lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ | ||
| 615 | status = lua_load(L, &compat53_getF, &lf, lua_tostring(L, -1), mode); | ||
| 616 | readstatus = ferror(lf.f); | ||
| 617 | if (filename) fclose(lf.f); /* close file (even in case of errors) */ | ||
| 618 | if (readstatus) { | ||
| 619 | lua_settop(L, fnameindex); /* ignore results from 'lua_load' */ | ||
| 620 | return compat53_errfile(L, "read", fnameindex); | ||
| 621 | } | ||
| 622 | lua_remove(L, fnameindex); | ||
| 623 | return status; | ||
| 624 | } | ||
| 625 | |||
| 626 | |||
| 627 | COMPAT53_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode) { | ||
| 628 | int status = LUA_OK; | ||
| 629 | if (sz > 0 && buff[0] == LUA_SIGNATURE[0]) { | ||
| 630 | status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX); | ||
| 631 | } | ||
| 632 | else { | ||
| 633 | status = compat53_checkmode(L, mode, "text", LUA_ERRSYNTAX); | ||
| 634 | } | ||
| 635 | if (status != LUA_OK) | ||
| 636 | return status; | ||
| 637 | return luaL_loadbuffer(L, buff, sz, name); | ||
| 638 | } | ||
| 639 | |||
| 640 | |||
| 356 | #if !defined(l_inspectstat) && \ | 641 | #if !defined(l_inspectstat) && \ |
| 357 | (defined(unix) || defined(__unix) || defined(__unix__) || \ | 642 | (defined(unix) || defined(__unix) || defined(__unix__) || \ |
| 358 | defined(__TOS_AIX__) || defined(_SYSTYPE_BSD) || \ | 643 | defined(__TOS_AIX__) || defined(_SYSTYPE_BSD) || \ |
diff --git a/c-api/compat-5.3.h b/c-api/compat-5.3.h index d8e6827..755c23e 100644 --- a/c-api/compat-5.3.h +++ b/c-api/compat-5.3.h | |||
| @@ -51,8 +51,6 @@ extern "C" { | |||
| 51 | * lua_upvaluejoin | 51 | * lua_upvaluejoin |
| 52 | * lua_version | 52 | * lua_version |
| 53 | * lua_yieldk | 53 | * lua_yieldk |
| 54 | * luaL_loadbufferx | ||
| 55 | * luaL_loadfilex | ||
| 56 | */ | 54 | */ |
| 57 | 55 | ||
| 58 | #ifndef LUA_OK | 56 | #ifndef LUA_OK |
| @@ -176,6 +174,15 @@ COMPAT53_API lua_Number lua_tonumberx (lua_State *L, int i, int *isnum); | |||
| 176 | #define luaL_checkversion COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkversion) | 174 | #define luaL_checkversion COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkversion) |
| 177 | COMPAT53_API void luaL_checkversion (lua_State *L); | 175 | COMPAT53_API void luaL_checkversion (lua_State *L); |
| 178 | 176 | ||
| 177 | #define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53) | ||
| 178 | COMPAT53_API int lua_load (lua_State *L, lua_Reader reader, void *data, const char* source, const char* mode); | ||
| 179 | |||
| 180 | #define luaL_loadfilex COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadfilex) | ||
| 181 | COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode); | ||
| 182 | |||
| 183 | #define luaL_loadbufferx COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadbufferx) | ||
| 184 | COMPAT53_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode); | ||
| 185 | |||
| 179 | #define luaL_checkstack COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkstack_53) | 186 | #define luaL_checkstack COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkstack_53) |
| 180 | COMPAT53_API void luaL_checkstack (lua_State *L, int sp, const char *msg); | 187 | COMPAT53_API void luaL_checkstack (lua_State *L, int sp, const char *msg); |
| 181 | 188 | ||
diff --git a/tests/test.lua b/tests/test.lua index 582f55e..8fafdf3 100755 --- a/tests/test.lua +++ b/tests/test.lua | |||
| @@ -657,133 +657,158 @@ ___'' | |||
| 657 | print("testing C API ...") | 657 | print("testing C API ...") |
| 658 | local mod = require("testmod") | 658 | local mod = require("testmod") |
| 659 | ___'' | 659 | ___'' |
| 660 | print(mod.isinteger(1)) | 660 | print("isinteger", mod.isinteger(1)) |
| 661 | print(mod.isinteger(0)) | 661 | print("isinteger", mod.isinteger(0)) |
| 662 | print(mod.isinteger(1234567)) | 662 | print("isinteger", mod.isinteger(1234567)) |
| 663 | print(mod.isinteger(12.3)) | 663 | print("isinteger", mod.isinteger(12.3)) |
| 664 | print(mod.isinteger(math.huge)) | 664 | print("isinteger", mod.isinteger(math.huge)) |
| 665 | print(mod.isinteger(math.sqrt(-1))) | 665 | print("isinteger", mod.isinteger(math.sqrt(-1))) |
| 666 | 666 | ||
| 667 | 667 | ||
| 668 | ___'' | 668 | ___'' |
| 669 | print(mod.rotate(1, 1, 2, 3, 4, 5, 6)) | 669 | print("rotate", mod.rotate(1, 1, 2, 3, 4, 5, 6)) |
| 670 | print(mod.rotate(-1, 1, 2, 3, 4, 5, 6)) | 670 | print("rotate", mod.rotate(-1, 1, 2, 3, 4, 5, 6)) |
| 671 | print(mod.rotate(4, 1, 2, 3, 4, 5, 6)) | 671 | print("rotate", mod.rotate(4, 1, 2, 3, 4, 5, 6)) |
| 672 | print(mod.rotate(-4, 1, 2, 3, 4, 5, 6)) | 672 | print("rotate", mod.rotate(-4, 1, 2, 3, 4, 5, 6)) |
| 673 | 673 | ||
| 674 | 674 | ||
| 675 | ___'' | 675 | ___'' |
| 676 | print(mod.strtonum("+123")) | 676 | print("strtonum", mod.strtonum("+123")) |
| 677 | print(mod.strtonum(" 123 ")) | 677 | print("strtonum", mod.strtonum(" 123 ")) |
| 678 | print(mod.strtonum("-1.23")) | 678 | print("strtonum", mod.strtonum("-1.23")) |
| 679 | print(mod.strtonum(" 123 abc")) | 679 | print("strtonum", mod.strtonum(" 123 abc")) |
| 680 | print(mod.strtonum("jkl")) | 680 | print("strtonum", mod.strtonum("jkl")) |
| 681 | 681 | ||
| 682 | 682 | ||
| 683 | ___'' | 683 | ___'' |
| 684 | local a, b, c = mod.requiref() | 684 | local a, b, c = mod.requiref() |
| 685 | print( type(a), type(b), type(c), | 685 | print("requiref", type(a), type(b), type(c), |
| 686 | a.boolean, b.boolean, c.boolean, | 686 | a.boolean, b.boolean, c.boolean, |
| 687 | type(requiref1), type(requiref2), type(requiref3)) | 687 | type(requiref1), type(requiref2), type(requiref3)) |
| 688 | 688 | ||
| 689 | ___'' | 689 | ___'' |
| 690 | local proxy, backend = {}, {} | 690 | local proxy, backend = {}, {} |
| 691 | setmetatable(proxy, { __index = backend, __newindex = backend }) | 691 | setmetatable(proxy, { __index = backend, __newindex = backend }) |
| 692 | print(rawget(proxy, 1), rawget(backend, 1)) | 692 | print("geti/seti", rawget(proxy, 1), rawget(backend, 1)) |
| 693 | print(mod.getseti(proxy, 1)) | 693 | print("geti/seti", mod.getseti(proxy, 1)) |
| 694 | print(rawget(proxy, 1), rawget(backend, 1)) | 694 | print("geti/seti", rawget(proxy, 1), rawget(backend, 1)) |
| 695 | print(mod.getseti(proxy, 1)) | 695 | print("geti/seti", mod.getseti(proxy, 1)) |
| 696 | print(rawget(proxy, 1), rawget(backend, 1)) | 696 | print("geti/seti", rawget(proxy, 1), rawget(backend, 1)) |
| 697 | 697 | ||
| 698 | -- tests for Lua 5.1 | 698 | -- tests for Lua 5.1 |
| 699 | ___'' | 699 | ___'' |
| 700 | print(mod.tonumber(12)) | 700 | print("tonumber", mod.tonumber(12)) |
| 701 | print(mod.tonumber("12")) | 701 | print("tonumber", mod.tonumber("12")) |
| 702 | print(mod.tonumber("0")) | 702 | print("tonumber", mod.tonumber("0")) |
| 703 | print(mod.tonumber(false)) | 703 | print("tonumber", mod.tonumber(false)) |
| 704 | print(mod.tonumber("error")) | 704 | print("tonumber", mod.tonumber("error")) |
| 705 | 705 | ||
| 706 | ___'' | 706 | ___'' |
| 707 | print(mod.tointeger(12)) | 707 | print("tointeger", mod.tointeger(12)) |
| 708 | print(mod.tointeger("12")) | 708 | print("tointeger", mod.tointeger("12")) |
| 709 | print(mod.tointeger("0")) | 709 | print("tointeger", mod.tointeger("0")) |
| 710 | print( "aaa" ) | 710 | print("tointeger", mod.tointeger(math.pi)) |
| 711 | print(mod.tointeger(math.pi)) | 711 | print("tointeger", mod.tointeger(false)) |
| 712 | print( "bbb" ) | 712 | print("tointeger", mod.tointeger("error")) |
| 713 | print(mod.tointeger(false)) | ||
| 714 | print(mod.tointeger("error")) | ||
| 715 | 713 | ||
| 716 | ___'' | 714 | ___'' |
| 717 | print(mod.len("123")) | 715 | print("len", mod.len("123")) |
| 718 | print(mod.len({ 1, 2, 3})) | 716 | print("len", mod.len({ 1, 2, 3})) |
| 719 | print(pcall(mod.len, true)) | 717 | print("len", pcall(mod.len, true)) |
| 720 | local ud, meta = mod.newproxy() | 718 | local ud, meta = mod.newproxy() |
| 721 | meta.__len = function() return 5 end | 719 | meta.__len = function() return 5 end |
| 722 | print(mod.len(ud)) | 720 | print("len", mod.len(ud)) |
| 723 | meta.__len = function() return true end | 721 | meta.__len = function() return true end |
| 724 | print(pcall(mod.len, ud)) | 722 | print("len", pcall(mod.len, ud)) |
| 725 | 723 | ||
| 726 | ___'' | 724 | ___'' |
| 727 | print(mod.copy(true, "string", {}, 1)) | 725 | print("copy", mod.copy(true, "string", {}, 1)) |
| 728 | 726 | ||
| 729 | ___'' | 727 | ___'' |
| 730 | print(mod.rawxetp()) | 728 | print("rawgetp/rawsetp", mod.rawxetp()) |
| 731 | print(mod.rawxetp("I'm back")) | 729 | print("rawgetp/rawsetp", mod.rawxetp("I'm back")) |
| 732 | 730 | ||
| 733 | ___'' | 731 | ___'' |
| 734 | print(F(mod.globals()), mod.globals() == _G) | 732 | print("globals", F(mod.globals()), mod.globals() == _G) |
| 735 | 733 | ||
| 736 | ___'' | 734 | ___'' |
| 737 | local t = {} | 735 | local t = {} |
| 738 | print(F(mod.subtable(t))) | 736 | print("getsubtable", F(mod.subtable(t))) |
| 739 | local x, msg = mod.subtable(t) | 737 | local x, msg = mod.subtable(t) |
| 740 | print(F(x, msg, x == t.xxx)) | 738 | print("getsubtable", F(x, msg, x == t.xxx)) |
| 741 | 739 | ||
| 742 | ___'' | 740 | ___'' |
| 743 | print(F(mod.udata())) | 741 | print("udata", F(mod.udata())) |
| 744 | print(mod.udata("nosuchtype")) | 742 | print("udata", mod.udata("nosuchtype")) |
| 745 | 743 | ||
| 746 | ___'' | 744 | ___'' |
| 747 | print(F(mod.uservalue())) | 745 | print("uservalue", F(mod.uservalue())) |
| 748 | 746 | ||
| 749 | ___'' | 747 | ___'' |
| 750 | print(mod.getupvalues()) | 748 | print("upvalues", mod.getupvalues()) |
| 751 | 749 | ||
| 752 | ___'' | 750 | ___'' |
| 753 | print(mod.absindex("hi", true)) | 751 | print("absindex", mod.absindex("hi", true)) |
| 754 | 752 | ||
| 755 | ___'' | 753 | ___'' |
| 756 | print(mod.arith(2, 1)) | 754 | print("arith", mod.arith(2, 1)) |
| 757 | print(mod.arith(3, 5)) | 755 | print("arith", mod.arith(3, 5)) |
| 758 | 756 | ||
| 759 | ___'' | 757 | ___'' |
| 760 | print(mod.compare(1, 1)) | 758 | print("compare", mod.compare(1, 1)) |
| 761 | print(mod.compare(2, 1)) | 759 | print("compare", mod.compare(2, 1)) |
| 762 | print(mod.compare(1, 2)) | 760 | print("compare", mod.compare(1, 2)) |
| 763 | 761 | ||
| 764 | ___'' | 762 | ___'' |
| 765 | print(mod.tolstring("string")) | 763 | print("tolstring", mod.tolstring("string")) |
| 766 | local t = setmetatable({}, { | 764 | local t = setmetatable({}, { |
| 767 | __tostring = function(v) return "mytable" end | 765 | __tostring = function(v) return "mytable" end |
| 768 | }) | 766 | }) |
| 769 | print(mod.tolstring(t)) | 767 | print("tolstring", mod.tolstring(t)) |
| 770 | local t = setmetatable({}, { | 768 | local t = setmetatable({}, { |
| 771 | __tostring = function(v) return nil end | 769 | __tostring = function(v) return nil end |
| 772 | }) | 770 | }) |
| 773 | print(pcall(mod.tolstring, t)) | 771 | print("tolstring", pcall(mod.tolstring, t)) |
| 774 | local ud, meta = mod.newproxy() | 772 | local ud, meta = mod.newproxy() |
| 775 | meta.__name = "XXX" | 773 | meta.__name = "XXX" |
| 776 | print(mod.tolstring(ud):gsub(":.*$", ": yyy")) | 774 | print("tolstring", mod.tolstring(ud):gsub(":.*$", ": yyy")) |
| 777 | 775 | ||
| 778 | ___'' | 776 | ___'' |
| 779 | print(mod.pushstring()) | 777 | print("pushstring", mod.pushstring()) |
| 780 | 778 | ||
| 781 | ___'' | 779 | ___'' |
| 782 | print(mod.buffer()) | 780 | print("Buffer", mod.buffer()) |
| 783 | 781 | ||
| 784 | ___'' | 782 | ___'' |
| 785 | print(mod.exec("exit 0")) | 783 | print("execresult", mod.exec("exit 0")) |
| 786 | print(mod.exec("exit 1")) | 784 | print("execresult", mod.exec("exit 1")) |
| 787 | print(mod.exec("exit 25")) | 785 | print("execresult", mod.exec("exit 25")) |
| 786 | |||
| 787 | ___'' | ||
| 788 | do | ||
| 789 | local bin = string.dump(function() end) | ||
| 790 | local modes = { "t", "b", "bt" } | ||
| 791 | local codes = { | ||
| 792 | "", "return true", bin, "invalidsource", "\27invalidbinary" | ||
| 793 | } | ||
| 794 | for _,m in ipairs(modes) do | ||
| 795 | for i,c in ipairs(codes) do | ||
| 796 | print("loadbufferx", m, i, F(mod.loadstring(c, m))) | ||
| 797 | end | ||
| 798 | end | ||
| 799 | |||
| 800 | ___'' | ||
| 801 | local bom = "\239\187\191" | ||
| 802 | local shebang = "#!/usr/bin/env lua\n" | ||
| 803 | codes[#codes+1] = bom .. shebang .. "return true" | ||
| 804 | codes[#codes+1] = bom .. shebang .. bin | ||
| 805 | codes[#codes+1] = bom .. shebang .. "invalidsource" | ||
| 806 | codes[#codes+1] = bom .. shebang .. "\027invalidbinary" | ||
| 807 | for _,m in ipairs(modes) do | ||
| 808 | for i,c in ipairs(codes) do | ||
| 809 | print("loadfilex", m, i, F(mod.loadfile(c, m))) | ||
| 810 | end | ||
| 811 | end | ||
| 812 | end | ||
| 788 | ___'' | 813 | ___'' |
| 789 | 814 | ||
diff --git a/tests/testmod.c b/tests/testmod.c index 868136b..1034d20 100644 --- a/tests/testmod.c +++ b/tests/testmod.c | |||
| @@ -274,6 +274,33 @@ static int test_exec (lua_State *L) { | |||
| 274 | return luaL_execresult(L, system(cmd)); | 274 | return luaL_execresult(L, system(cmd)); |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | static int test_loadstring (lua_State *L) { | ||
| 278 | size_t len = 0; | ||
| 279 | char const* s = luaL_checklstring(L, 1, &len); | ||
| 280 | char const* mode = luaL_optstring(L, 2, "bt"); | ||
| 281 | lua_pushinteger(L, luaL_loadbufferx(L, s, len, s, mode)); | ||
| 282 | return 2; | ||
| 283 | } | ||
| 284 | |||
| 285 | static int test_loadfile (lua_State *L) { | ||
| 286 | char filename[L_tmpnam+1] = { 0 }; | ||
| 287 | size_t len = 0; | ||
| 288 | char const* s = luaL_checklstring(L, 1, &len); | ||
| 289 | char const* mode = luaL_optstring(L, 2, "bt"); | ||
| 290 | if (tmpnam(filename)) { | ||
| 291 | FILE* f = fopen(filename, "wb"); | ||
| 292 | if (f) { | ||
| 293 | fwrite(s, 1, len, f); | ||
| 294 | fclose(f); | ||
| 295 | lua_pushinteger(L, luaL_loadfilex(L, filename, mode)); | ||
| 296 | remove(filename); | ||
| 297 | return 2; | ||
| 298 | } else | ||
| 299 | remove(filename); | ||
| 300 | } | ||
| 301 | return 0; | ||
| 302 | } | ||
| 303 | |||
| 277 | 304 | ||
| 278 | static const luaL_Reg funcs[] = { | 305 | static const luaL_Reg funcs[] = { |
| 279 | { "isinteger", test_isinteger }, | 306 | { "isinteger", test_isinteger }, |
| @@ -297,6 +324,8 @@ static const luaL_Reg funcs[] = { | |||
| 297 | { "pushstring", test_pushstring }, | 324 | { "pushstring", test_pushstring }, |
| 298 | { "buffer", test_buffer }, | 325 | { "buffer", test_buffer }, |
| 299 | { "exec", test_exec }, | 326 | { "exec", test_exec }, |
| 327 | { "loadstring", test_loadstring }, | ||
| 328 | { "loadfile", test_loadfile }, | ||
| 300 | { NULL, NULL } | 329 | { NULL, NULL } |
| 301 | }; | 330 | }; |
| 302 | 331 | ||
