diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-07-04 17:11:58 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-07-04 17:11:58 -0300 |
| commit | 366c85564874d560b3608349f752e9e490f9002d (patch) | |
| tree | 77426f1c700cf4c7aa15b0742cf6669c9166af7a /lua.c | |
| parent | 781219dbe16fc327f5b828e1ff6fa45ec3265cba (diff) | |
| download | lua-366c85564874d560b3608349f752e9e490f9002d.tar.gz lua-366c85564874d560b3608349f752e9e490f9002d.tar.bz2 lua-366c85564874d560b3608349f752e9e490f9002d.zip | |
lua.c loads 'readline' dynamically
(See comments in luaconf.h.) This change allows easier compilation,
as Lua compiles and works even if the package 'readline' is absent
from the system. Moreover, non-interactive uses don't load the library,
making the stand-alone slightly faster for small loads.
Diffstat (limited to 'lua.c')
| -rw-r--r-- | lua.c | 88 |
1 files changed, 70 insertions, 18 deletions
| @@ -437,27 +437,80 @@ static int handle_luainit (lua_State *L) { | |||
| 437 | ** lua_saveline defines how to "save" a read line in a "history". | 437 | ** lua_saveline defines how to "save" a read line in a "history". |
| 438 | ** lua_freeline defines how to free a line read by lua_readline. | 438 | ** lua_freeline defines how to free a line read by lua_readline. |
| 439 | */ | 439 | */ |
| 440 | #if !defined(lua_readline) /* { */ | ||
| 441 | 440 | ||
| 442 | #if defined(LUA_USE_READLINE) /* { */ | 441 | #if defined(LUA_USE_READLINE) |
| 443 | 442 | ||
| 444 | #include <readline/readline.h> | 443 | #include <readline/readline.h> |
| 445 | #include <readline/history.h> | 444 | #include <readline/history.h> |
| 446 | #define lua_initreadline(L) ((void)L, rl_readline_name="lua") | 445 | #define lua_initreadline(L) ((void)L, rl_readline_name="lua") |
| 447 | #define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) | 446 | #define lua_readline(b,p) ((void)b, readline(p)) |
| 448 | #define lua_saveline(L,line) ((void)L, add_history(line)) | 447 | #define lua_saveline(line) add_history(line) |
| 449 | #define lua_freeline(L,b) ((void)L, free(b)) | 448 | #define lua_freeline(b) free(b) |
| 449 | |||
| 450 | #endif | ||
| 451 | |||
| 452 | |||
| 453 | #if !defined(lua_readline) /* { */ | ||
| 454 | |||
| 455 | /* pointer to dynamically loaded 'readline' function (if any) */ | ||
| 456 | typedef char *(*l_readline_t) (const char *prompt); | ||
| 457 | static l_readline_t l_readline = NULL; | ||
| 458 | |||
| 459 | static char *lua_readline (char *buff, const char *prompt) { | ||
| 460 | if (l_readline != NULL) /* is there a dynamic 'readline'? */ | ||
| 461 | return (*l_readline)(prompt); /* use it */ | ||
| 462 | else { /* emulate 'readline' over 'buff' */ | ||
| 463 | fputs(prompt, stdout); | ||
| 464 | fflush(stdout); /* show prompt */ | ||
| 465 | return fgets(buff, LUA_MAXINPUT, stdin); /* read line */ | ||
| 466 | } | ||
| 467 | } | ||
| 468 | |||
| 469 | |||
| 470 | /* pointer to dynamically loaded 'add_history' function (if any) */ | ||
| 471 | typedef void (*l_addhist_t) (const char *string); | ||
| 472 | static l_addhist_t l_addhist = NULL; | ||
| 473 | |||
| 474 | static void lua_saveline (const char *line) { | ||
| 475 | if (l_addhist != NULL) /* is there a dynamic 'add_history'? */ | ||
| 476 | (*l_addhist)(line); /* use it */ | ||
| 477 | /* else nothing to be done */ | ||
| 478 | } | ||
| 450 | 479 | ||
| 451 | #else /* }{ */ | 480 | |
| 481 | static void lua_freeline (char *line) { | ||
| 482 | if (l_readline != NULL) /* is there a dynamic 'readline'? */ | ||
| 483 | free(line); /* free line created by it */ | ||
| 484 | /* else 'lua_readline' used an automatic buffer; nothing to free */ | ||
| 485 | } | ||
| 486 | |||
| 487 | |||
| 488 | #if !defined(LUA_USE_DLOPEN) || !defined(LUA_READLINELIB) | ||
| 452 | 489 | ||
| 453 | #define lua_initreadline(L) ((void)L) | 490 | #define lua_initreadline(L) ((void)L) |
| 454 | #define lua_readline(L,b,p) \ | ||
| 455 | ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ | ||
| 456 | fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ | ||
| 457 | #define lua_saveline(L,line) { (void)L; (void)line; } | ||
| 458 | #define lua_freeline(L,b) { (void)L; (void)b; } | ||
| 459 | 491 | ||
| 460 | #endif /* } */ | 492 | #else /* { */ |
| 493 | |||
| 494 | #include <dlfcn.h> | ||
| 495 | |||
| 496 | |||
| 497 | static void lua_initreadline (lua_State *L) { | ||
| 498 | void *lib = dlopen(LUA_READLINELIB, RTLD_NOW | RTLD_LOCAL); | ||
| 499 | if (lib == NULL) | ||
| 500 | lua_warning(L, "library '" LUA_READLINELIB "'not found", 0); | ||
| 501 | else { | ||
| 502 | const char **name = cast(const char**, dlsym(lib, "rl_readline_name")); | ||
| 503 | if (name != NULL) | ||
| 504 | *name = "Lua"; | ||
| 505 | l_readline = cast(l_readline_t, cast_func(dlsym(lib, "readline"))); | ||
| 506 | if (l_readline == NULL) | ||
| 507 | lua_warning(L, "unable to load 'readline'", 0); | ||
| 508 | else | ||
| 509 | l_addhist = cast(l_addhist_t, cast_func(dlsym(lib, "add_history"))); | ||
| 510 | } | ||
| 511 | } | ||
| 512 | |||
| 513 | #endif /* } */ | ||
| 461 | 514 | ||
| 462 | #endif /* } */ | 515 | #endif /* } */ |
| 463 | 516 | ||
| @@ -505,11 +558,10 @@ static int incomplete (lua_State *L, int status) { | |||
| 505 | */ | 558 | */ |
| 506 | static int pushline (lua_State *L, int firstline) { | 559 | static int pushline (lua_State *L, int firstline) { |
| 507 | char buffer[LUA_MAXINPUT]; | 560 | char buffer[LUA_MAXINPUT]; |
| 508 | char *b = buffer; | ||
| 509 | size_t l; | 561 | size_t l; |
| 510 | const char *prmt = get_prompt(L, firstline); | 562 | const char *prmt = get_prompt(L, firstline); |
| 511 | int readstatus = lua_readline(L, b, prmt); | 563 | char *b = lua_readline(buffer, prmt); |
| 512 | if (readstatus == 0) | 564 | if (b == NULL) |
| 513 | return 0; /* no input (prompt will be popped by caller) */ | 565 | return 0; /* no input (prompt will be popped by caller) */ |
| 514 | lua_pop(L, 1); /* remove prompt */ | 566 | lua_pop(L, 1); /* remove prompt */ |
| 515 | l = strlen(b); | 567 | l = strlen(b); |
| @@ -519,7 +571,7 @@ static int pushline (lua_State *L, int firstline) { | |||
| 519 | lua_pushfstring(L, "return %s", b + 1); /* change '=' to 'return' */ | 571 | lua_pushfstring(L, "return %s", b + 1); /* change '=' to 'return' */ |
| 520 | else | 572 | else |
| 521 | lua_pushlstring(L, b, l); | 573 | lua_pushlstring(L, b, l); |
| 522 | lua_freeline(L, b); | 574 | lua_freeline(b); |
| 523 | return 1; | 575 | return 1; |
| 524 | } | 576 | } |
| 525 | 577 | ||
| @@ -535,7 +587,7 @@ static int addreturn (lua_State *L) { | |||
| 535 | if (status == LUA_OK) { | 587 | if (status == LUA_OK) { |
| 536 | lua_remove(L, -2); /* remove modified line */ | 588 | lua_remove(L, -2); /* remove modified line */ |
| 537 | if (line[0] != '\0') /* non empty? */ | 589 | if (line[0] != '\0') /* non empty? */ |
| 538 | lua_saveline(L, line); /* keep history */ | 590 | lua_saveline(line); /* keep history */ |
| 539 | } | 591 | } |
| 540 | else | 592 | else |
| 541 | lua_pop(L, 2); /* pop result from 'luaL_loadbuffer' and modified line */ | 593 | lua_pop(L, 2); /* pop result from 'luaL_loadbuffer' and modified line */ |
| @@ -552,7 +604,7 @@ static int multiline (lua_State *L) { | |||
| 552 | const char *line = lua_tolstring(L, 1, &len); /* get what it has */ | 604 | const char *line = lua_tolstring(L, 1, &len); /* get what it has */ |
| 553 | int status = luaL_loadbuffer(L, line, len, "=stdin"); /* try it */ | 605 | int status = luaL_loadbuffer(L, line, len, "=stdin"); /* try it */ |
| 554 | if (!incomplete(L, status) || !pushline(L, 0)) { | 606 | if (!incomplete(L, status) || !pushline(L, 0)) { |
| 555 | lua_saveline(L, line); /* keep history */ | 607 | lua_saveline(line); /* keep history */ |
| 556 | return status; /* cannot or should not try to add continuation line */ | 608 | return status; /* cannot or should not try to add continuation line */ |
| 557 | } | 609 | } |
| 558 | lua_pushliteral(L, "\n"); /* add newline... */ | 610 | lua_pushliteral(L, "\n"); /* add newline... */ |
