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... */ |