1 #include "lua/internal.hpp"
2 #include "library/minmax.hpp"
3 #include "library/zip.hpp"
4 #include "core/memorymanip.hpp"
9 std::string
dashstring(char ch
, int dashes
)
12 return std::string(1, ch
) + std::string(dashes
, '=') + std::string(1, ch
);
14 return std::string(1, ch
) + std::string(1, ch
);
30 replace(const std::string
& _target
)
35 std::pair
<const char*, size_t> run(std::function
<std::pair
<const char*, size_t>()> fn
);
42 const char* upper_buf
;
48 std::string pattern
= "@@LUA_SCRIPT_FILENAME@@";
50 std::pair
<const char*, size_t> replace::run(std::function
<std::pair
<const char*, size_t>()> fn
)
53 while(emitted
< sizeof(buffer
)) {
54 while(upper_ptr
== upper_size
&& !upper_eof
) {
57 upper_size
= g
.second
;
59 if(!upper_buf
&& !upper_size
)
62 if(upper_ptr
== upper_size
&& source
== 0) {
70 if(upper_buf
[upper_ptr
] == pattern
[matched
]) {
73 if(matched
== pattern
.length()) {
82 buffer
[emitted
++] = upper_buf
[upper_ptr
++];
86 if(matched
== 2 && upper_ptr
< upper_size
&& upper_buf
[upper_ptr
] == '@') {
87 //This is exceptional, just flush the first '@'.
88 buffer
[emitted
++] = '@';
92 } else if(copied
== matched
) {
97 buffer
[emitted
++] = pattern
[copied
++];
101 if(copied
== target
.size()) {
106 buffer
[emitted
++] = target
[copied
++];
112 return std::make_pair(reinterpret_cast<const char*>(NULL
), 0);
113 return std::make_pair(buffer
, emitted
);
118 reader(std::istream
& _s
, const std::string
& fn
)
123 std::string tmpl
= dashstring(']', dashes
);
124 if(fn
.find(tmpl
) == std::string::npos
)
127 rpl
= replace(dashstring('[', dashes
) + fn
+ dashstring(']', dashes
));
129 const char* rfn(lua_State
* L
, size_t* size
);
130 static const char* rfn(lua_State
* L
, void* data
, size_t* size
)
132 return reinterpret_cast<reader
*>(data
)->rfn(L
, size
);
139 const char* reader::rfn(lua_State
* L
, size_t* size
)
141 auto g
= rpl
.run([this]() -> std::pair
<const char*, size_t> {
143 static char buffer
[4096];
145 return std::make_pair(reinterpret_cast<const char*>(NULL
), 0);
146 this->s
.read(buffer
, sizeof(buffer
));
147 size
= this->s
.gcount();
149 return std::make_pair(reinterpret_cast<const char*>(NULL
), 0);
151 return std::make_pair(buffer
, size
);
157 void load_chunk(lua_state
& L
, const std::string
& fname
)
160 std::string file1
= L
.get_string(1, fname
.c_str());
161 if(L
.type(2) != LUA_TNIL
&& L
.type(2) != LUA_TNONE
)
162 file2
= L
.get_string(2, fname
.c_str());
163 std::string absfilename
= resolve_file_relative(file1
, file2
);
164 std::istream
& file
= open_file_relative(file1
, file2
);
165 std::string chunkname
;
167 chunkname
= file2
+ "[" + file1
+ "]";
170 reader
rc(file
, absfilename
);
171 int r
= lua_load(L
.handle(), reader::rfn
, &rc
, chunkname
.c_str()
172 #if LUA_VERSION_NUM == 502
179 } else if(r
== LUA_ERRSYNTAX
) {
180 (stringfmt() << "Syntax error: " << L
.tostring(-1)).throwex();
181 } else if(r
== LUA_ERRMEM
) {
182 (stringfmt() << "Out of memory: " << L
.tostring(-1)).throwex();
184 (stringfmt() << "Unknown error: " << L
.tostring(-1)).throwex();
188 function_ptr_luafun
loadfile2(LS
, "loadfile2", [](lua_state
& L
, const std::string
& fname
)
190 load_chunk(L
, fname
);
194 function_ptr_luafun
dofile2(LS
, "dofile2", [](lua_state
& L
, const std::string
& fname
)
196 load_chunk(L
, fname
);
197 int old_sp
= lua_gettop(L
.handle());
198 lua_call(L
.handle(), 0, LUA_MULTRET
);
199 int new_sp
= lua_gettop(L
.handle());
200 return new_sp
- (old_sp
- 1);