1 /* 2 Copyright (C) 2014 - 2018 by Chris Beck <render787@gmail.com> 3 Part of the Battle for Wesnoth Project https://www.wesnoth.org/ 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY. 11 12 See the COPYING file for more details. 13 */ 14 15 #pragma once 16 17 #include <sstream> 18 #include <string> 19 #include <vector> 20 #include "utils/functional.hpp" 21 #include <cstdint> 22 23 struct lua_State; 24 class config; 25 26 class lua_kernel_base { 27 public: 28 lua_kernel_base(); 29 virtual ~lua_kernel_base(); 30 31 /** Runs a [lua] tag. Doesn't throw lua_error.*/ 32 void run_lua_tag(const config& cfg); 33 34 /** Runs a plain script. Doesn't throw lua_error.*/ 35 void run(char const *prog, int nArgs = 0); 36 37 /** Runs a plain script, but reports errors by throwing lua_error.*/ 38 void throwing_run(char const * prog, int nArgs); 39 40 /** Tests if a program resolves to an expression, and pretty prints it if it is, otherwise it runs it normally. Throws exceptions.*/ 41 void interactive_run(char const * prog); 42 43 /** Loads the `package` library into lua environment. Only in allow in `unsafe` modes. */ 44 void load_package(); 45 /** Loads the "core" library into the Lua environment. Without this, most Wesnoth Lua won't work. 46 * Cannot be called from the constructor because it needs to call virtual functions. 47 */ 48 void load_core(); 49 50 /** Get tab completion strings */ 51 std::vector<std::string> get_global_var_names(); 52 std::vector<std::string> get_attribute_names(const std::string & var_path); 53 54 /** User-visible name of the lua kernel that they are talking to */ my_name()55 virtual std::string my_name() { return "Basic Lua Kernel"; } 56 57 /** Access / manipulate logging of lua kernel activities */ get_log()58 const std::stringstream & get_log() { cmd_log_.log_ << std::flush; return cmd_log_.log_; } clear_log()59 void clear_log() { cmd_log_.log_.str(""); cmd_log_.log_.clear(); } 60 61 using external_log_type = std::function<void(const std::string &)>; set_external_log(external_log_type lg)62 void set_external_log( external_log_type lg ) { cmd_log_.external_log_ = lg; } 63 64 /** Error reporting mechanisms, used by virtual methods protected_call and load_string*/ 65 virtual void log_error(char const* msg, char const* context = "Lua error"); 66 virtual void throw_exception(char const* msg, char const* context = "Lua error"); //throws game::lua_error 67 68 typedef std::function<void(char const*, char const*)> error_handler; 69 70 template<typename T> get_lua_kernel(lua_State * L)71 static T& get_lua_kernel(lua_State *L) 72 { 73 return *static_cast<T*>(get_lua_kernel_base_ptr(L)); 74 } 75 76 virtual uint32_t get_random_seed(); get_state()77 lua_State * get_state() { return mState; } add_widget_definition(const std::string & type,const std::string & id)78 void add_widget_definition(const std::string& type, const std::string& id) { registered_widget_definitions_.emplace_back(type, id); } 79 protected: 80 lua_State *mState; 81 82 /** Log implementation */ 83 struct command_log { 84 85 std::stringstream log_; 86 external_log_type external_log_; 87 command_loglua_kernel_base::command_log88 command_log() 89 : log_() 90 , external_log_(nullptr) 91 {} 92 operator <<lua_kernel_base::command_log93 inline command_log & operator<< (const std::string & str) { 94 log_ << str; 95 if (external_log_) { 96 external_log_(str); 97 } 98 return *this; 99 } 100 operator <<lua_kernel_base::command_log101 inline command_log & operator<< (char const* str) { 102 if (str != nullptr) { 103 log_ << str; 104 if (external_log_) { 105 external_log_(str); 106 } 107 } 108 return *this; 109 } 110 }; 111 112 command_log cmd_log_; 113 114 // Print text to the command log for this lua kernel. Used as a replacement impl for lua print. 115 int intf_print(lua_State * L); 116 117 // Show the interactive lua console (for debugging purposes) 118 int intf_show_lua_console(lua_State * L); 119 120 // Execute a protected call. Error handler is called in case of an error, using syntax for log_error and throw_exception above. Returns true if successful. 121 bool protected_call(int nArgs, int nRets, error_handler); 122 // Execute a protected call, taking a lua_State as argument. For functions pushed into the lua environment, this version should be used, or the function cannot be used by coroutines without segfaulting (since they have a different lua_State pointer). This version is called by the above version. 123 static bool protected_call(lua_State * L, int nArgs, int nRets, error_handler); 124 // Load a string onto the stack as a function. Returns true if successful, error handler is called if not. 125 bool load_string(char const * prog, error_handler); 126 127 virtual bool protected_call(int nArgs, int nRets); // select default error handler polymorphically 128 virtual bool load_string(char const * prog); // select default error handler polymorphically 129 130 // dofile (using lua_fileops) 131 int intf_dofile(lua_State * L); 132 133 // require (using lua_fileops, protected_call) 134 int intf_require(lua_State * L); 135 136 int intf_kernel_type(lua_State* L); 137 138 virtual int impl_game_config_get(lua_State* L); 139 virtual int impl_game_config_set(lua_State* L); 140 private: 141 static lua_kernel_base*& get_lua_kernel_base_ptr(lua_State *L); 142 std::vector<std::tuple<std::string, std::string>> registered_widget_definitions_; 143 }; 144