64 Commits

Author SHA1 Message Date
Enyby
6694c375c9 Fix build errors for j2me. #32 2019-03-09 17:38:32 +02:00
Enyby
e70eb5edc2 Fix build bug. #32 2019-03-09 15:49:56 +02:00
Enyby
9688d3c5fc Remove libs dependency from PackageLib. 2019-01-13 19:23:44 +02:00
Enyby
6f5af581e8 Fix string.gsub for invalid use '%' in replacement string
Check code:
```
print(pcall(load('string.gsub("test", "%S", "A%")')))
print(pcall(load('string.gsub("test", "%S", "%A")')))
```
2019-01-03 18:09:00 +02:00
Enyby
870aee2cae Improved opt methods for numbers in LuaString 2018-12-29 19:49:43 +02:00
Enyby
c2ec9edf39 Deny use NaN as index in rawset. 2018-12-24 22:34:49 +02:00
Enyby
cfb3aaca61 Fix math.min and math.max.
Now similar to native Lua and reference: `Returns the argument with the maximum value, according to the Lua operator <. (integer/float) `
2018-12-24 20:52:23 +02:00
Enyby
4105cebf1e Fix math.fmod for int values. 2018-12-24 20:37:39 +02:00
Enyby
339f004eb7 More compat with lua tests. 2018-12-24 19:30:11 +02:00
Enyby
05a604645d Fix modulo for edge cases.
Reference code:
```
for i,lhs in ipairs({-math.huge, -10.0, 0.0, 10.0, math.huge}) do
for j,rhs in ipairs({-math.huge, -10.0, 0.0, 10.0, math.huge}) do
print(lhs, rhs, lhs % rhs)
end
end
```
2018-12-24 18:30:35 +02:00
Enyby
63ead7aac7 Fix string.format for long integers. 2018-12-24 11:45:06 +02:00
Enyby
c9ba2d4bb1 Fix math.modf for inf/-inf and int values. 2018-12-23 17:48:31 +02:00
Enyby
92cee0812d Fix JSE math.log for second arg. 2018-12-23 17:06:34 +02:00
Enyby
e61e5694fa Fix string.match for empty pattern 2018-12-16 06:38:23 +02:00
Enyby
47f8d6e6fc Fix a frontier pattern match
We're not in C anymore. LuaString are not null terminated.
Also need quotes in error messages.
2018-12-11 23:44:39 +02:00
Enyby
14ac4bb7f9 Merge pull request #21 from lorenzos/patch-1
Check the type before reusing a NumberValueEntry
2018-11-02 23:11:36 +02:00
Lorenzo Stanco
b8aaaafb68 Check the type before reusing a NumberValueEntry
Fixes #20
2018-10-31 15:57:02 +01:00
Enyby
88a557033b Optimize get new stack for calls. 2018-09-20 20:14:02 +03:00
Enyby
24a8559ceb Fix make LuaString from copy. 2018-09-17 16:32:09 +03:00
Enyby
028e03e4bc Avoid synthetic methods 2018-09-16 18:49:26 +03:00
Enyby
5c1f7d2ab2 Make const final 2018-09-16 18:45:52 +03:00
Enyby
9db1254160 Avoid synthetic methods 2018-09-16 18:44:36 +03:00
Enyby
f899c709ff Remove unused var. 2018-09-16 18:43:39 +03:00
Enyby
9c9e193cc4 Make consts final. 2018-09-16 18:40:06 +03:00
Enyby
e9db487d97 Improve convert function to string. 2018-09-16 18:38:49 +03:00
Enyby
c6fe5d3ed3 Avoid synthetic methods 2018-09-16 17:15:54 +03:00
Enyby
52ab872d08 Improve rawopenfile 2018-09-16 17:11:28 +03:00
Enyby
5d3041c6be Improved get/setLocal. 2018-09-16 17:09:18 +03:00
Enyby
8d544729a8 Avoid synthetic methods. 2018-09-16 17:05:52 +03:00
Enyby
bd57dddef0 Imrove traceback build. 2018-09-16 17:03:35 +03:00
Enyby
d509e21cc6 Make static classes. 2018-09-16 17:02:24 +03:00
Enyby
5b67841232 Avoid synthetic methods 2018-09-16 16:58:51 +03:00
Enyby
bd4dac18ff Make classes static to avoid leak parent instance. 2018-09-16 16:56:53 +03:00
Enyby
e02a82ef8d Improve print. 2018-09-16 16:53:20 +03:00
Enyby
70a5086097 Make constants final. 2018-09-16 16:47:17 +03:00
Enyby
ad20f939b1 Fixed typo in JseOsLib 2018-09-16 16:46:13 +03:00
Enyby
e7058bcd6a Improved math.atan/atan2. 2018-09-16 16:44:21 +03:00
Enyby
00c7e266ba Used BufferedInputStream for JseBaseLib 2018-09-16 16:36:40 +03:00
Enyby
e75c5e2fca Fix Visitor bug. 2018-09-16 16:33:42 +03:00
Enyby
ed46675a25 Improved concat values. 2018-09-16 16:08:53 +03:00
Enyby
8fbca25dce Fixed table.unpack 2018-09-16 16:03:09 +03:00
Enyby
d0ed5b80e5 Improved error messages. 2018-09-16 15:52:14 +03:00
Enyby
9b77084109 Improved error messages. 2018-09-16 15:39:24 +03:00
Enyby
4f410fba6e Fixed metatag processing for equality. 2018-09-16 15:30:41 +03:00
Enyby
f164c1cd28 Added optional param stripDebug to string.dump 2018-09-16 15:21:16 +03:00
Enyby
63ca0f94af Removed synthetic accessors. 2018-09-16 15:13:06 +03:00
Enyby
5bd9827af1 Improve error message for string.char. 2018-09-16 15:09:36 +03:00
Enyby
0a5cccc50f Fix issue with frontier patterns #3 2018-09-16 15:02:29 +03:00
Enyby
12aded74ca Removed unused objects. 2018-09-16 10:01:39 +03:00
Enyby
48dd90f6d7 Removed unnecessary override. 2018-09-16 09:58:16 +03:00
Enyby
6333d9acf7 Merge pull request #17 from Enyby/patch-9
Fix format float numbers
2018-09-16 09:24:04 +03:00
Benjamin P. Jung
d61ed707ef Merge pull request #18 from Enyby/patch-1
Rename README.html to README.md
2018-09-15 21:40:22 +02:00
Enyby
1e521d8900 Rename README.html to README.md 2018-09-14 15:46:14 +03:00
Benjamin P. Jung
bf8ef8d1a9 Merge pull request #15 from Enyby/patch-7
Fix gmatch for pass testsuites
2018-09-14 12:13:34 +02:00
Benjamin P. Jung
69498dbb7c Merge pull request #16 from Enyby/patch-8
Fix build stack traceback in DebugLib

Fixes #7
2018-09-14 12:12:42 +02:00
Benjamin P. Jung
4cc5f4270d Merge pull request #14 from Enyby/patch-6
Fix for proper print OP_SETLIST additional opcode

Closes #7
2018-09-14 12:12:10 +02:00
Enyby
75fa98d13f Fix format float numbers
Fix bug: https://sourceforge.net/p/luaj/bugs/53/ if System support String.format or fallback to old way.
2018-09-14 02:16:42 +03:00
Enyby
a627a868d5 Fix build stack traceback in DebugLib #7
If create huge table with a lot items (> 28000) then additional op code for store `c` out of range of op codes and this loop crash.
This PR add case for OP_SETLIST for skip next op if in it stored `c`.
OP_SETLIST not AMode OP 
70cb74b4d6/src/core/org/luaj/vm2/Lua.java (L319)
70cb74b4d6/src/core/org/luaj/vm2/Lua.java (L335)
2018-09-14 02:13:21 +03:00
Enyby
f073919f64 Print any code 2018-09-14 02:09:43 +03:00
Enyby
27a1dcdd11 Fix gmatch for pass testsuites
Test suites from lua.org:
```
-- tests for gmatch
local a = 0
for i in string.gmatch('abcde', '()') do assert(i == a+1); a=i end
assert(a==6)

t = {n=0}
for w in string.gmatch("first second word", "%w+") do
      t.n=t.n+1; t[t.n] = w
end
assert(t[1] == "first" and t[2] == "second" and t[3] == "word")

t = {3, 6, 9}
for i in string.gmatch ("xuxx uu ppar r", "()(.)%2") do
  assert(i == table.remove(t, 1))
end
assert(#t == 0)

t = {}
for i,j in string.gmatch("13 14 10 = 11, 15= 16, 22=23", "(%d+)%s*=%s*(%d+)") do
  t[tonumber(i)] = tonumber(j)
end
a = 0
for k,v in pairs(t) do assert(k+1 == v+0); a=a+1 end
assert(a == 3)


-- tests for `%f' (`frontiers')

assert(string.gsub("aaa aa a aaa a", "%f[%w]a", "x") == "xaa xa x xaa x")
assert(string.gsub("[[]] [][] [[[[", "%f[[].", "x") == "x[]] x]x] x[[[")
assert(string.gsub("01abc45de3", "%f[%d]", ".") == ".01abc.45de.3")
assert(string.gsub("01abc45 de3x", "%f[%D]%w", ".") == "01.bc45 de3.")
assert(string.gsub("function", "%f[\1-\255]%w", ".") == ".unction")
assert(string.gsub("function", "%f[^\1-\255]", ".") == "function.")

assert(string.find("a", "%f[a]") == 1)
assert(string.find("a", "%f[^%z]") == 1)
assert(string.find("a", "%f[^%l]") == 2)
assert(string.find("aba", "%f[a%z]") == 3)
assert(string.find("aba", "%f[%z]") == 4)
assert(not string.find("aba", "%f[%l%z]"))
assert(not string.find("aba", "%f[^%l%z]"))

local i, e = string.find(" alo aalo allo", "%f[%S].-%f[%s].-%f[%S]")
assert(i == 2 and e == 5)
local k = string.match(" alo aalo allo", "%f[%S](.-%f[%s].-%f[%S])")
assert(k == 'alo ')

local a = {1, 5, 9, 14, 17,}
for k in string.gmatch("alo alo th02 is 1hat", "()%f[%w%d]") do
  assert(table.remove(a, 1) == k)
end
assert(#a == 0)
```
Code from lua:
https://www.lua.org/source/5.2/lstrlib.c.html
```
static int gmatch_aux (lua_State *L) {
  MatchState ms;
  size_t ls, lp;
  const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
  const char *p = lua_tolstring(L, lua_upvalueindex(2), &lp);
  const char *src;
  ms.L = L;
  ms.matchdepth = MAXCCALLS;
  ms.src_init = s;
  ms.src_end = s+ls;
  ms.p_end = p + lp;
  for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3));
       src <= ms.src_end;
       src++) {
    const char *e;
    ms.level = 0;
    lua_assert(ms.matchdepth == MAXCCALLS);
    if ((e = match(&ms, src, p)) != NULL) {
      lua_Integer newstart = e-s;
      if (e == src) newstart++;  /* empty match? go at least one position */
      lua_pushinteger(L, newstart);
      lua_replace(L, lua_upvalueindex(3));
      return push_captures(&ms, src, e);
    }
  }
  return 0;  /* not found */
}
```
On empty match need increase string offset.
2018-09-14 02:04:56 +03:00
Enyby
b459724103 Fix for proper print OP_SETLIST additional opcode #7 2018-09-14 01:59:35 +03:00
Benjamin P. Jung
3d22990e3c Migrate CVS project to Git
* Delete .svnignore and move stuff to .gitignore
* Add note to README to show that this is an inofficial fork as of now.
* Change file suffix of README file from .html to .md for better
  Github integration and readability
2018-09-13 11:56:02 +02:00
James Roseborough
194b776317 Add synchronization to CoerceJavaToLua.COERCIONS map. 2018-09-13 11:53:24 +02:00
James Roseborough
828e4be019 Fix JsePlatform.luaMain() to provide an "arg" table in the chunk's environment. 2018-09-13 11:53:00 +02:00
31 changed files with 782 additions and 629 deletions

View File

@@ -1,22 +1,22 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
# This is a fork!
<div style="border: 1px dotted red; margin: 1.em 0.5em; font-weight: bold; color: red;">
This repository has been forked from the original CVS sources of Luaj.
The commit history has been converted to make sure that the original work of
James Roseborough and Ian Farmer is not lost.
Unfortunately, I was not able to contact either James or Ian to hand over
ownership of the Github organization/repo as I have originally intended to.
The community however seems interested enough to continue work on the original
sources and therefore I have decided to make sure that any useful pull requests
that may add some value to the original code base shall be merged in from now
on.<br>
-- Benjamin P. Jung, Jan. 26th 2018
</div>
<head>
<title>Getting Started with LuaJ</title>
<link rel="stylesheet" type="text/css" href="http://www.lua.org/lua.css">
<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=iso-8859-1">
</head>
<h1>Getting Started with LuaJ</h1>
<body>
<hr>
<h1>
<a href="README.html"><img src="http://sourceforge.net/dbimage.php?id=196139" alt="" border="0"></a>
Getting Started with LuaJ
</h1>
James Roseborough, Ian Farmer, Version 3.0.1
<h1>Getting Started with LuaJ</h1>
James Roseborough, Ian Farmer, Version 3.0.2
<p>
<small>
Copyright &copy; 2009-2014 Luaj.org.
@@ -120,7 +120,7 @@ in comparison with the standard C distribution.
<td>16.794</td>
<td>11.274</td>
<td>Java</td>
<td>java -cp luaj-jse-3.0.1.jar;bcel-5.2.jar lua <b>-b</b> fannkuch.lua 10</td></tr>
<td>java -cp luaj-jse-3.0.2.jar;bcel-5.2.jar lua <b>-b</b> fannkuch.lua 10</td></tr>
<tr valign="top">
<td></td>
<td></td>
@@ -130,7 +130,7 @@ in comparison with the standard C distribution.
<td>36.894</td>
<td>15.163</td>
<td></td>
<td>java -cp luaj-jse-3.0.1.jar lua -n fannkuch.lua 10</td></tr>
<td>java -cp luaj-jse-3.0.2.jar lua -n fannkuch.lua 10</td></tr>
<tr valign="top">
<td>lua</td>
<td>5.1.4</td>
@@ -186,7 +186,7 @@ It is also faster than Java-lua implementations Jill, Kahlua, and Mochalua for a
From the main distribution directory line type:
<pre>
java -cp lib/luaj-jse-3.0.1.jar lua examples/lua/hello.lua
java -cp lib/luaj-jse-3.0.2.jar lua examples/lua/hello.lua
</pre>
<p>
@@ -198,7 +198,7 @@ You should see the following output:
To see how luaj can be used to acccess most Java API's including swing, try:
<pre>
java -cp lib/luaj-jse-3.0.1.jar lua examples/lua/swingapp.lua
java -cp lib/luaj-jse-3.0.2.jar lua examples/lua/swingapp.lua
</pre>
<p>
@@ -213,8 +213,8 @@ Links to sources:<pre>
From the main distribution directory line type:
<pre>
java -cp lib/luaj-jse-3.0.1.jar luac examples/lua/hello.lua
java -cp lib/luaj-jse-3.0.1.jar lua luac.out
java -cp lib/luaj-jse-3.0.2.jar luac examples/lua/hello.lua
java -cp lib/luaj-jse-3.0.2.jar lua luac.out
</pre>
<p>
@@ -228,8 +228,8 @@ Luaj can compile lua sources or binaries directly to java bytecode if the bcel l
<pre>
ant bcel-lib
java -cp &quot;lib/luaj-jse-3.0.1.jar;lib/bcel-5.2.jar&quot; luajc -s examples/lua -d . hello.lua
java -cp &quot;lib/luaj-jse-3.0.1.jar;.&quot; lua -l hello
java -cp &quot;lib/luaj-jse-3.0.2.jar;lib/bcel-5.2.jar&quot; luajc -s examples/lua -d . hello.lua
java -cp &quot;lib/luaj-jse-3.0.2.jar;.&quot; lua -l hello
</pre>
<p>
@@ -240,7 +240,7 @@ but the compiled classes must be in the class path at runtime, unless runtime ji
<p>
Lua scripts can also be run directly in this mode without precompiling using the <em>lua</em> command with the <b><em>-b</em></b> option and providing the <em>bcel</em> library in the class path:
<pre>
java -cp &quot;lib/luaj-jse-3.0.1.jar;lib/bcel-5.2.jar&quot; lua -b examples/lua/hello.lua
java -cp &quot;lib/luaj-jse-3.0.2.jar;lib/bcel-5.2.jar&quot; lua -b examples/lua/hello.lua
</pre>
@@ -284,7 +284,7 @@ A simple example may be found in
</pre>
<p>
You must include the library <b>lib/luaj-jse-3.0.1.jar</b> in your class path.
You must include the library <b>lib/luaj-jse-3.0.2.jar</b> in your class path.
<h2>Run a script in a MIDlet</h2>
@@ -311,7 +311,7 @@ A simple example may be found in
</pre>
<p>
You must include the library <b>lib/luaj-jme-3.0.1.jar</b> in your midlet jar.
You must include the library <b>lib/luaj-jme-3.0.2.jar</b> in your midlet jar.
<p>
An ant script to build and run the midlet is in
@@ -341,7 +341,7 @@ You can also look up the engine by language "lua" or mimetypes "text/lua" or "ap
All standard aspects of script engines including compiled statements are supported.
<p>
You must include the library <b>lib/luaj-jse-3.0.1.jar</b> in your class path.
You must include the library <b>lib/luaj-jse-3.0.2.jar</b> in your class path.
<p>
A working example may be found in
@@ -352,8 +352,8 @@ A working example may be found in
To compile and run it using Java 1.6 or higher:
<pre>
javac -cp lib/luaj-jse-3.0.1.jar examples/jse/ScriptEngineSample.java
java -cp &quot;lib/luaj-jse-3.0.1.jar;examples/jse&quot; ScriptEngineSample
javac -cp lib/luaj-jse-3.0.2.jar examples/jse/ScriptEngineSample.java
java -cp &quot;lib/luaj-jse-3.0.2.jar;examples/jse&quot; ScriptEngineSample
</pre>
<h2>Excluding the lua bytecode compiler</h2>
@@ -593,7 +593,7 @@ The following lua script will open a swing frame on Java SE:
See a longer sample in <em>examples/lua/swingapp.lua</em> for details, including a simple animation loop, rendering graphics, mouse and key handling, and image loading.
Or try running it using:
<pre>
java -cp lib/luaj-jse-3.0.1.jar lua examples/lua/swingapp.lua
java -cp lib/luaj-jse-3.0.2.jar lua examples/lua/swingapp.lua
</pre>
<p>
@@ -842,7 +842,7 @@ For JSE projects, add this dependency for the luaj-jse jar:
&lt;dependency&gt;
&lt;groupId&gt;org.luaj&lt;/groupId&gt;
&lt;artifactId&gt;luaj-jse&lt;/artifactId&gt;
&lt;version&gt;3.0.1&lt;/version&gt;
&lt;version&gt;3.0.2&lt;/version&gt;
&lt;/dependency&gt;
</pre>
while for JME projects, use the luaj-jme jar:
@@ -850,7 +850,7 @@ while for JME projects, use the luaj-jme jar:
&lt;dependency&gt;
&lt;groupId&gt;org.luaj&lt;/groupId&gt;
&lt;artifactId&gt;luaj-jme&lt;/artifactId&gt;
&lt;version&gt;3.0.1&lt;/version&gt;
&lt;version&gt;3.0.2&lt;/version&gt;
&lt;/dependency&gt;
</pre>
@@ -880,7 +880,7 @@ Unit test scripts can be found in these locations
test/lua/*.lua
test/lua/errors/*.lua
test/lua/perf/*.lua
test/lua/luaj3.0.1-tests.zip
test/lua/luaj3.0.2-tests.zip
</pre>
<h2>Code coverage</h2>
@@ -1017,6 +1017,11 @@ and at <a href="http://luaj.sourceforge.net/api/2.0/index.html">http://luaj.sour
<li>Move online docs to <a href="http://luaj.org/luaj/3.0/api/index.html">http://luaj.org/luaj/3.0/api/</a></li>
<li>Fix os.time() conversions for pm times.</li>
<tr valign="top"><td>&nbsp;&nbsp;<b>3.0.2</b></td><td><ul>
<li>Fix JsePlatform.luaMain() to provide an "arg" table in the chunk's environment.</li>
<li>Let JsePlatform.luaMain() return values returned by the main chunk.</li>
<li>Add synchronization to CoerceJavaToLua.COERCIONS map.</li>
</ul></td></tr>
</table></td></tr></table>

View File

@@ -11,13 +11,13 @@ import org.luaj.vm2.lib.Bit32Lib;
import org.luaj.vm2.lib.CoroutineLib;
import org.luaj.vm2.lib.PackageLib;
import org.luaj.vm2.lib.ResourceFinder;
import org.luaj.vm2.lib.StringLib;
import org.luaj.vm2.lib.TableLib;
import org.luaj.vm2.lib.jse.CoerceJavaToLua;
import org.luaj.vm2.lib.jse.JseBaseLib;
import org.luaj.vm2.lib.jse.JseIoLib;
import org.luaj.vm2.lib.jse.JseMathLib;
import org.luaj.vm2.lib.jse.JseOsLib;
import org.luaj.vm2.lib.jse.JseStringLib;
import org.luaj.vm2.lib.jse.LuajavaLib;
/**
@@ -76,7 +76,7 @@ public class SampleApplet extends Applet implements ResourceFinder {
globals.load(new PackageLib());
globals.load(new Bit32Lib());
globals.load(new TableLib());
globals.load(new StringLib());
globals.load(new JseStringLib());
globals.load(new CoroutineLib());
globals.load(new JseMathLib());
globals.load(new JseIoLib());

View File

@@ -1,12 +1,26 @@
import org.luaj.vm2.*;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LoadState;
import org.luaj.vm2.LuaBoolean;
import org.luaj.vm2.LuaString;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaThread;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.lib.*;
import org.luaj.vm2.lib.jse.*;
import org.luaj.vm2.lib.Bit32Lib;
import org.luaj.vm2.lib.DebugLib;
import org.luaj.vm2.lib.PackageLib;
import org.luaj.vm2.lib.TableLib;
import org.luaj.vm2.lib.TwoArgFunction;
import org.luaj.vm2.lib.ZeroArgFunction;
import org.luaj.vm2.lib.jse.JseBaseLib;
import org.luaj.vm2.lib.jse.JseMathLib;
import org.luaj.vm2.lib.jse.JseStringLib;
/** Simple program that illustrates basic sand-boxing of client scripts
* in a server environment.
*
* <p>Although this sandboxing is done primarily in Java here, these
* <p>Although this sandboxing is done primarily in Java here, these
* same techniques should all be possible directly from lua using metatables,
* and examples are shown in examples/lua/samplesandboxed.lua.
*
@@ -29,7 +43,7 @@ public class SampleSandboxed {
server_globals = new Globals();
server_globals.load(new JseBaseLib());
server_globals.load(new PackageLib());
server_globals.load(new StringLib());
server_globals.load(new JseStringLib());
// To load scripts, we occasionally need a math library in addition to compiler support.
// To limit scripts using the debug library, they must be closures, so we only install LuaC.
@@ -47,7 +61,7 @@ public class SampleSandboxed {
runScriptInSandbox( "return getmetatable('abc').len" );
runScriptInSandbox( "return getmetatable('abc').__index" );
// Example user scripts that attempt rogue operations, and will fail.
// Example user scripts that attempt rogue operations, and will fail.
runScriptInSandbox( "return setmetatable('abc', {})" );
runScriptInSandbox( "getmetatable('abc').len = function() end" );
runScriptInSandbox( "getmetatable('abc').__index = {}" );
@@ -61,9 +75,9 @@ public class SampleSandboxed {
LuaValue.ADD, new TwoArgFunction() {
public LuaValue call(LuaValue x, LuaValue y) {
return LuaValue.valueOf(
(x == TRUE ? 1.0 : x.todouble()) +
(x == TRUE ? 1.0 : x.todouble()) +
(y == TRUE ? 1.0 : y.todouble()) );
}
}
},
}));
runScriptInSandbox( "return 5 + 6, 5 + true, false + 6" );
@@ -75,21 +89,21 @@ public class SampleSandboxed {
// that contain functions that can be abused.
static void runScriptInSandbox(String script) {
// Each script will have it's own set of globals, which should
// Each script will have it's own set of globals, which should
// prevent leakage between scripts running on the same server.
Globals user_globals = new Globals();
user_globals.load(new JseBaseLib());
user_globals.load(new PackageLib());
user_globals.load(new Bit32Lib());
user_globals.load(new TableLib());
user_globals.load(new StringLib());
user_globals.load(new JseStringLib());
user_globals.load(new JseMathLib());
// This library is dangerous as it gives unfettered access to the
// entire Java VM, so it's not suitable within this lightweight sandbox.
// entire Java VM, so it's not suitable within this lightweight sandbox.
// user_globals.load(new LuajavaLib());
// Starting coroutines in scripts will result in threads that are
// Starting coroutines in scripts will result in threads that are
// not under the server control, so this libary should probably remain out.
// user_globals.load(new CoroutineLib());
@@ -98,12 +112,12 @@ public class SampleSandboxed {
// user_globals.load(new JseIoLib());
// user_globals.load(new JseOsLib());
// Loading and compiling scripts from within scripts may also be
// Loading and compiling scripts from within scripts may also be
// prohibited, though in theory it should be fairly safe.
// LoadState.install(user_globals);
// LuaC.install(user_globals);
// The debug library must be loaded for hook functions to work, which
// The debug library must be loaded for hook functions to work, which
// allow us to limit scripts to run a certain number of instructions at a time.
// However we don't wish to expose the library in the user globals,
// so it is immediately removed from the user globals once created.
@@ -111,18 +125,18 @@ public class SampleSandboxed {
LuaValue sethook = user_globals.get("debug").get("sethook");
user_globals.set("debug", LuaValue.NIL);
// Set up the script to run in its own lua thread, which allows us
// Set up the script to run in its own lua thread, which allows us
// to set a hook function that limits the script to a specific number of cycles.
// Note that the environment is set to the user globals, even though the
// Note that the environment is set to the user globals, even though the
// compiling is done with the server globals.
LuaValue chunk = server_globals.load(script, "main", user_globals);
LuaThread thread = new LuaThread(user_globals, chunk);
// Set the hook function to immediately throw an Error, which will not be
// Set the hook function to immediately throw an Error, which will not be
// handled by any Lua code other than the coroutine.
LuaValue hookfunc = new ZeroArgFunction() {
public LuaValue call() {
// A simple lua error may be caught by the script, but a
// A simple lua error may be caught by the script, but a
// Java Error will pass through to top and stop the script.
throw new Error("Script overran resource limits.");
}

View File

@@ -97,14 +97,19 @@ public class LuaClosure extends LuaFunction {
*/
public LuaClosure(Prototype p, LuaValue env) {
this.p = p;
this.initupvalue1(env);
globals = env instanceof Globals? (Globals) env: null;
}
public void initupvalue1(LuaValue env) {
if (p.upvalues == null || p.upvalues.length == 0)
this.upValues = NOUPVALUES;
else {
this.upValues = new UpValue[p.upvalues.length];
this.upValues[0] = new UpValue(new LuaValue[] {env}, 0);
}
globals = env instanceof Globals? (Globals) env: null;
}
public boolean isclosure() {
return true;
@@ -118,26 +123,24 @@ public class LuaClosure extends LuaFunction {
return this;
}
public LuaValue getmetatable() {
return s_metatable;
}
public String tojstring() {
return "function: " + p.toString();
}
private LuaValue[] getNewStack() {
int max = p.maxstacksize;
LuaValue[] stack = new LuaValue[max];
System.arraycopy(NILS, 0, stack, 0, max);
return stack;
}
public final LuaValue call() {
LuaValue[] stack = new LuaValue[p.maxstacksize];
for (int i = 0; i < p.numparams; ++i )
stack[i] = NIL;
LuaValue[] stack = getNewStack();
return execute(stack,NONE).arg1();
}
public final LuaValue call(LuaValue arg) {
LuaValue[] stack = new LuaValue[p.maxstacksize];
System.arraycopy(NILS, 0, stack, 0, p.maxstacksize);
for (int i = 1; i < p.numparams; ++i )
stack[i] = NIL;
LuaValue[] stack = getNewStack();
switch ( p.numparams ) {
default: stack[0]=arg; return execute(stack,NONE).arg1();
case 0: return execute(stack,arg).arg1();
@@ -145,9 +148,7 @@ public class LuaClosure extends LuaFunction {
}
public final LuaValue call(LuaValue arg1, LuaValue arg2) {
LuaValue[] stack = new LuaValue[p.maxstacksize];
for (int i = 2; i < p.numparams; ++i )
stack[i] = NIL;
LuaValue[] stack = getNewStack();
switch ( p.numparams ) {
default: stack[0]=arg1; stack[1]=arg2; return execute(stack,NONE).arg1();
case 1: stack[0]=arg1; return execute(stack,arg2).arg1();
@@ -156,9 +157,7 @@ public class LuaClosure extends LuaFunction {
}
public final LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) {
LuaValue[] stack = new LuaValue[p.maxstacksize];
for (int i = 3; i < p.numparams; ++i )
stack[i] = NIL;
LuaValue[] stack = getNewStack();
switch ( p.numparams ) {
default: stack[0]=arg1; stack[1]=arg2; stack[2]=arg3; return execute(stack,NONE).arg1();
case 2: stack[0]=arg1; stack[1]=arg2; return execute(stack,arg3).arg1();
@@ -172,9 +171,9 @@ public class LuaClosure extends LuaFunction {
}
public final Varargs onInvoke(Varargs varargs) {
LuaValue[] stack = new LuaValue[p.maxstacksize];
LuaValue[] stack = getNewStack();
for ( int i=0; i<p.numparams; i++ )
stack[i] = varargs.arg(i+1);
stack[i] = varargs.arg(i+1);
return execute(stack,p.is_vararg!=0? varargs.subargs(p.numparams+1): NONE);
}
@@ -302,7 +301,7 @@ public class LuaClosure extends LuaFunction {
if ( c > b+1 ) {
Buffer sb = stack[c].buffer();
while ( --c>=b )
sb = stack[c].concat(sb);
sb.concatTo(stack[c]);
stack[a] = sb.value();
} else {
stack[a] = stack[c-1].concat(stack[c]);

View File

@@ -177,7 +177,14 @@ public class LuaDouble extends LuaNumber {
* @see #dmod_d(double, double)
*/
public static LuaValue dmod(double lhs, double rhs) {
return rhs!=0? valueOf( lhs-rhs*Math.floor(lhs/rhs) ): NAN;
if (rhs == 0 || lhs == Double.POSITIVE_INFINITY || lhs == Double.NEGATIVE_INFINITY) return NAN;
if (rhs == Double.POSITIVE_INFINITY) {
return lhs < 0 ? POSINF : valueOf(lhs);
}
if (rhs == Double.NEGATIVE_INFINITY) {
return lhs > 0 ? NEGINF : valueOf(lhs);
}
return valueOf( lhs-rhs*Math.floor(lhs/rhs) );
}
/** Take modulo for double numbers according to lua math, and return a double result.
@@ -188,7 +195,14 @@ public class LuaDouble extends LuaNumber {
* @see #dmod(double, double)
*/
public static double dmod_d(double lhs, double rhs) {
return rhs!=0? lhs-rhs*Math.floor(lhs/rhs): Double.NaN;
if (rhs == 0 || lhs == Double.POSITIVE_INFINITY || lhs == Double.NEGATIVE_INFINITY) return Double.NaN;
if (rhs == Double.POSITIVE_INFINITY) {
return lhs < 0 ? Double.POSITIVE_INFINITY : lhs;
}
if (rhs == Double.NEGATIVE_INFINITY) {
return lhs > 0 ? Double.NEGATIVE_INFINITY : lhs;
}
return lhs-rhs*Math.floor(lhs/rhs);
}
// relational operators

View File

@@ -144,7 +144,7 @@ public class LuaString extends LuaValue {
/** Construct a new LuaString using a copy of the bytes array supplied */
private static LuaString valueFromCopy(byte[] bytes, int off, int len) {
final byte[] copy = new byte[len];
for (int i=0; i<len; ++i) copy[i] = bytes[off+i];
System.arraycopy(bytes, off, copy, 0, len);
return new LuaString(copy, 0, len);
}
@@ -391,23 +391,23 @@ public class LuaString extends LuaValue {
public short toshort() { return (short) toint(); }
public double optdouble(double defval) {
return checknumber().checkdouble();
return checkdouble();
}
public int optint(int defval) {
return checknumber().checkint();
return checkint();
}
public LuaInteger optinteger(LuaInteger defval) {
return checknumber().checkinteger();
return checkinteger();
}
public long optlong(long defval) {
return checknumber().checklong();
return checklong();
}
public LuaNumber optnumber(LuaNumber defval) {
return checknumber().checknumber();
return checknumber();
}
public LuaString optstring(LuaString defval) {

View File

@@ -266,8 +266,8 @@ public class LuaTable extends LuaValue implements Metatable {
/** caller must ensure key is not nil */
public void set( LuaValue key, LuaValue value ) {
if (!key.isvalidkey() && !metatag(NEWINDEX).isfunction())
typerror("table index");
if (key == null || !key.isvalidkey() && !metatag(NEWINDEX).isfunction())
throw new LuaError("value ('" + key + "') can not be used as a table index");
if ( m_metatable==null || ! rawget(key).isnil() || ! settable(this,key,value) )
rawset(key, value);
}
@@ -347,7 +347,12 @@ public class LuaTable extends LuaValue implements Metatable {
}
public int length() {
return m_metatable != null? len().toint(): rawlen();
if (m_metatable != null) {
LuaValue len = len();
if (!len.isint()) throw new LuaError("table length is not an integer: " + len);
return len.toint();
}
return rawlen();
}
public LuaValue len() {
@@ -390,7 +395,7 @@ public class LuaTable extends LuaValue implements Metatable {
}
}
if ( hash.length == 0 )
error( "invalid key to 'next'" );
error( "invalid key to 'next' 1: " + key );
i = hashSlot( key );
boolean found = false;
for ( Slot slot = hash[i]; slot != null; slot = slot.rest() ) {
@@ -404,7 +409,7 @@ public class LuaTable extends LuaValue implements Metatable {
}
}
if ( !found ) {
error( "invalid key to 'next'" );
error( "invalid key to 'next' 2: " + key );
}
i += 1+array.length;
}
@@ -780,6 +785,7 @@ public class LuaTable extends LuaValue implements Metatable {
* @param comparator {@link LuaValue} to be called to compare elements.
*/
public void sort(LuaValue comparator) {
if (len().tolong() >= (long)Integer.MAX_VALUE) throw new LuaError("array too big: " + len().tolong());
if (m_metatable != null && m_metatable.useWeakValues()) {
dropWeakArrayValues();
}
@@ -892,6 +898,11 @@ public class LuaTable extends LuaValue implements Metatable {
/** Unpack the elements from i to j inclusive */
public Varargs unpack(int i, int j) {
if (j < i) return NONE;
int count = j - i;
if (count < 0) throw new LuaError("too many results to unpack: greater " + Integer.MAX_VALUE); // integer overflow
int max = 0x00ffffff;
if (count >= max) throw new LuaError("too many results to unpack: " + count + " (max is " + max + ')');
int n = j + 1 - i;
switch (n) {
case 0: return NONE;
@@ -900,10 +911,14 @@ public class LuaTable extends LuaValue implements Metatable {
default:
if (n < 0)
return NONE;
LuaValue[] v = new LuaValue[n];
while (--n >= 0)
v[n] = get(i+n);
return varargsOf(v);
try {
LuaValue[] v = new LuaValue[n];
while (--n >= 0)
v[n] = get(i+n);
return varargsOf(v);
} catch (OutOfMemoryError e) {
throw new LuaError("too many results to unpack [out of memory]: " + n);
}
}
}
@@ -1231,13 +1246,14 @@ public class LuaTable extends LuaValue implements Metatable {
}
public Entry set(LuaValue value) {
LuaValue n = value.tonumber();
if ( !n.isnil() ) {
this.value = n.todouble();
return this;
} else {
return new NormalEntry( this.key, value );
if (value.type() == TNUMBER) {
LuaValue n = value.tonumber();
if (!n.isnil()) {
this.value = n.todouble();
return this;
}
}
return new NormalEntry( this.key, value );
}
public int keyindex( int mask ) {

View File

@@ -643,7 +643,7 @@ public class LuaValue extends Varargs {
* @see #isnumber()
* @see #TNUMBER
*/
public double optdouble(double defval) { argerror("double"); return 0; }
public double optdouble(double defval) { argerror("number"); return 0; }
/** Check that optional argument is a function and return as {@link LuaFunction}
* <p>
@@ -855,7 +855,7 @@ public class LuaValue extends Varargs {
* @see #optdouble(double)
* @see #TNUMBER
*/
public double checkdouble() { argerror("double"); return 0; }
public double checkdouble() { argerror("number"); return 0; }
/** Check that the value is a function , or throw {@link LuaError} if not
* <p>
@@ -2045,7 +2045,7 @@ public class LuaValue extends Varargs {
* @see #eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue)
* @see #EQ
*/
public LuaValue eq( LuaValue val ) { return this == val? TRUE: FALSE; }
public LuaValue eq( LuaValue val ) { return eq_b(val)? TRUE: FALSE; }
/** Equals: Perform equality comparison with another value
* including metatag processing using {@link #EQ},
@@ -3143,7 +3143,7 @@ public class LuaValue extends Varargs {
* @return {@link LuaString} corresponding to the value if a string or number
* @throws LuaError if not a string or number
*/
public LuaString strvalue() { typerror("strValue"); return null; }
public LuaString strvalue() { typerror("string or number"); return null; }
/** Return this value as a strong reference, or null if it was weak and is no longer referenced.
* @return {@link LuaValue} referred to, or null if it was weak and is no longer referenced.
@@ -3298,7 +3298,7 @@ public class LuaValue extends Varargs {
if ((!res.isnil()) || (tm = t.metatag(INDEX)).isnil())
return res;
} else if ((tm = t.metatag(INDEX)).isnil())
t.indexerror();
t.indexerror(key.tojstring());
if (tm.isfunction())
return tm.call(t, key);
t = tm;
@@ -3326,7 +3326,7 @@ public class LuaValue extends Varargs {
return true;
}
} else if ((tm = t.metatag(NEWINDEX)).isnil())
t.typerror("index");
throw new LuaError("table expected for set index ('" + key + "') value, got " + t.typename());
if (tm.isfunction()) {
tm.call(t, key, value);
return true;
@@ -3389,8 +3389,8 @@ public class LuaValue extends Varargs {
/** Throw {@link LuaError} indicating index was attempted on illegal type
* @throws LuaError when called.
*/
private void indexerror() {
error( "attempt to index ? (a "+typename()+" value)" );
private void indexerror(String key) {
error( "attempt to index ? (a "+typename()+" value) with key '" + key + "'" );
}
/** Construct a {@link Varargs} around an array of {@link LuaValue}s.

View File

@@ -128,6 +128,10 @@ public class Print extends Lua {
}
static void printValue( PrintStream ps, LuaValue v ) {
if (v == null) {
ps.print("null");
return;
}
switch ( v.type() ) {
case LuaValue.TSTRING: printString( ps, (LuaString) v ); break;
default: ps.print( v.tojstring() );
@@ -136,7 +140,7 @@ public class Print extends Lua {
}
static void printConstant(PrintStream ps, Prototype f, int i) {
printValue( ps, f.k[i] );
printValue( ps, i < f.k.length ? f.k[i] : LuaValue.valueOf("UNKNOWN_CONST_" + i) );
}
static void printUpvalue(PrintStream ps, Upvaldesc u) {
@@ -152,7 +156,7 @@ public class Print extends Lua {
int[] code = f.code;
int pc, n = code.length;
for (pc = 0; pc < n; pc++) {
printOpCode(f, pc);
pc = printOpCode(f, pc);
ps.println();
}
}
@@ -161,9 +165,10 @@ public class Print extends Lua {
* Print an opcode in a prototype
* @param f the {@link Prototype}
* @param pc the program counter to look up and print
* @return pc same as above or changed
*/
public static void printOpCode(Prototype f, int pc) {
printOpCode(ps,f,pc);
public static int printOpCode(Prototype f, int pc) {
return printOpCode(ps,f,pc);
}
/**
@@ -171,8 +176,9 @@ public class Print extends Lua {
* @param ps the {@link PrintStream} to print to
* @param f the {@link Prototype}
* @param pc the program counter to look up and print
* @return pc same as above or changed
*/
public static void printOpCode(PrintStream ps, Prototype f, int pc) {
public static int printOpCode(PrintStream ps, Prototype f, int pc) {
int[] code = f.code;
int i = code[pc];
int o = GET_OPCODE(i);
@@ -187,80 +193,67 @@ public class Print extends Lua {
ps.print("[" + line + "] ");
else
ps.print("[-] ");
ps.print(OPNAMES[o] + " ");
switch (getOpMode(o)) {
case iABC:
ps.print( a );
if (getBMode(o) != OpArgN)
ps.print(" "+(ISK(b) ? (-1 - INDEXK(b)) : b));
if (getCMode(o) != OpArgN)
ps.print(" "+(ISK(c) ? (-1 - INDEXK(c)) : c));
break;
case iABx:
if (getBMode(o) == OpArgK) {
ps.print(a + " " + (-1 - bx));
} else {
ps.print(a + " " + (bx));
if (o >= OPNAMES.length - 1) {
ps.print("UNKNOWN_OP_" + o + " ");
} else {
ps.print(OPNAMES[o] + " ");
switch (getOpMode(o)) {
case iABC:
ps.print( a );
if (getBMode(o) != OpArgN)
ps.print(" "+(ISK(b) ? (-1 - INDEXK(b)) : b));
if (getCMode(o) != OpArgN)
ps.print(" "+(ISK(c) ? (-1 - INDEXK(c)) : c));
break;
case iABx:
if (getBMode(o) == OpArgK) {
ps.print(a + " " + (-1 - bx));
} else {
ps.print(a + " " + (bx));
}
break;
case iAsBx:
if (o == OP_JMP)
ps.print( sbx );
else
ps.print(a + " " + sbx);
break;
}
break;
case iAsBx:
if (o == OP_JMP)
ps.print( sbx );
else
ps.print(a + " " + sbx);
break;
}
switch (o) {
case OP_LOADK:
ps.print(" ; ");
printConstant(ps, f, bx);
break;
case OP_GETUPVAL:
case OP_SETUPVAL:
ps.print(" ; ");
printUpvalue(ps, f.upvalues[b]);
break;
case OP_GETTABUP:
ps.print(" ; ");
printUpvalue(ps, f.upvalues[b]);
ps.print(" ");
if (ISK(c))
printConstant(ps, f, INDEXK(c));
else
ps.print("-");
break;
case OP_SETTABUP:
ps.print(" ; ");
printUpvalue(ps, f.upvalues[a]);
ps.print(" ");
if (ISK(b))
printConstant(ps, f, INDEXK(b));
else
ps.print("-");
ps.print(" ");
if (ISK(c))
printConstant(ps, f, INDEXK(c));
else
ps.print("-");
break;
case OP_GETTABLE:
case OP_SELF:
if (ISK(c)) {
switch (o) {
case OP_LOADK:
ps.print(" ; ");
printConstant(ps, f, INDEXK(c));
}
break;
case OP_SETTABLE:
case OP_ADD:
case OP_SUB:
case OP_MUL:
case OP_DIV:
case OP_POW:
case OP_EQ:
case OP_LT:
case OP_LE:
if (ISK(b) || ISK(c)) {
printConstant(ps, f, bx);
break;
case OP_GETUPVAL:
case OP_SETUPVAL:
ps.print(" ; ");
if (b < f.upvalues.length) {
printUpvalue(ps, f.upvalues[b]);
} else {
ps.print("UNKNOWN_UPVALUE_" + b);
}
break;
case OP_GETTABUP:
ps.print(" ; ");
if (b < f.upvalues.length) {
printUpvalue(ps, f.upvalues[b]);
} else {
ps.print("UNKNOWN_UPVALUE_" + b);
}
ps.print(" ");
if (ISK(c))
printConstant(ps, f, INDEXK(c));
else
ps.print("-");
break;
case OP_SETTABUP:
ps.print(" ; ");
if (a < f.upvalues.length) {
printUpvalue(ps, f.upvalues[a]);
} else {
ps.print("UNKNOWN_UPVALUE_" + a);
}
ps.print(" ");
if (ISK(b))
printConstant(ps, f, INDEXK(b));
else
@@ -270,28 +263,62 @@ public class Print extends Lua {
printConstant(ps, f, INDEXK(c));
else
ps.print("-");
break;
case OP_GETTABLE:
case OP_SELF:
if (ISK(c)) {
ps.print(" ; ");
printConstant(ps, f, INDEXK(c));
}
break;
case OP_SETTABLE:
case OP_ADD:
case OP_SUB:
case OP_MUL:
case OP_DIV:
case OP_POW:
case OP_EQ:
case OP_LT:
case OP_LE:
if (ISK(b) || ISK(c)) {
ps.print(" ; ");
if (ISK(b))
printConstant(ps, f, INDEXK(b));
else
ps.print("-");
ps.print(" ");
if (ISK(c))
printConstant(ps, f, INDEXK(c));
else
ps.print("-");
}
break;
case OP_JMP:
case OP_FORLOOP:
case OP_FORPREP:
ps.print(" ; to " + (sbx + pc + 2));
break;
case OP_CLOSURE:
if (bx < f.p.length) {
ps.print(" ; " + f.p[bx].getClass().getName());
} else {
ps.print(" ; UNKNOWN_PROTYPE_" + bx);
}
break;
case OP_SETLIST:
if (c == 0)
ps.print(" ; " + ((int) code[++pc]) + " (stored in the next OP)");
else
ps.print(" ; " + ((int) c));
break;
case OP_VARARG:
ps.print( " ; is_vararg="+ f.is_vararg );
break;
default:
break;
}
break;
case OP_JMP:
case OP_FORLOOP:
case OP_FORPREP:
ps.print(" ; to " + (sbx + pc + 2));
break;
case OP_CLOSURE:
ps.print(" ; " + f.p[bx].getClass().getName());
break;
case OP_SETLIST:
if (c == 0)
ps.print(" ; " + ((int) code[++pc]));
else
ps.print(" ; " + ((int) c));
break;
case OP_VARARG:
ps.print( " ; is_vararg="+ f.is_vararg );
break;
default:
break;
}
return pc;
}
private static int getline(Prototype f, int pc) {

View File

@@ -117,7 +117,7 @@ public class LuaC extends Constants implements Globals.Compiler, Globals.Loader
protected CompileState() {}
/** Parse the input */
private Prototype luaY_parser(InputStream z, String name) throws IOException{
Prototype luaY_parser(InputStream z, String name) throws IOException{
LexState lexstate = new LexState(this, z);
FuncState funcstate = new FuncState();
// lexstate.buff = buff;

View File

@@ -245,7 +245,7 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
public Varargs invoke(Varargs args) {
LuaValue tostring = globals.get("tostring");
for ( int i=1, n=args.narg(); i<=n; i++ ) {
if ( i>1 ) globals.STDOUT.print( '\t' );
if ( i>1 ) globals.STDOUT.print( " \t" );
LuaString s = tostring.call( args.arg(i) ).strvalue();
globals.STDOUT.print(s.tojstring());
}
@@ -299,7 +299,8 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
}
public LuaValue call(LuaValue table, LuaValue index, LuaValue value) {
LuaTable t = table.checktable();
t.rawset(index.checknotnil(), value);
if (!index.isvalidkey()) argerror(2, "value");
t.rawset(index, value);
return t;
}
}

View File

@@ -27,15 +27,15 @@ import org.luaj.vm2.Varargs;
/**
* Subclass of LibFunction that implements the Lua standard {@code bit32} library.
* <p>
* Typically, this library is included as part of a call to either
* <p>
* Typically, this library is included as part of a call to either
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
* <pre> {@code
* Globals globals = JsePlatform.standardGlobals();
* System.out.println( globals.get("bit32").get("bnot").call( LuaValue.valueOf(2) ) );
* } </pre>
* <p>
* To instantiate and use it directly,
* To instantiate and use it directly,
* link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as:
* <pre> {@code
* Globals globals = new Globals();
@@ -71,7 +71,7 @@ public class Bit32Lib extends TwoArgFunction {
"arshift", "lrotate", "lshift", "rrotate", "rshift"
});
env.set("bit32", t);
env.get("package").get("loaded").set("bit32", t);
if (!env.get("package").isnil()) env.get("package").get("loaded").set("bit32", t);
return t;
}
@@ -219,6 +219,6 @@ public class Bit32Lib extends TwoArgFunction {
}
private static LuaValue bitsToValue( int x ) {
return ( x < 0 ) ? valueOf((double) ((long) x & 0xFFFFFFFFL)) : valueOf(x);
return ( x < 0 ) ? valueOf((double) ((long) x & 0xFFFFFFFFL)) : valueOf(x);
}
}

View File

@@ -27,25 +27,25 @@ import org.luaj.vm2.LuaThread;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
/**
* Subclass of {@link LibFunction} which implements the lua standard {@code coroutine}
* library.
* <p>
/**
* Subclass of {@link LibFunction} which implements the lua standard {@code coroutine}
* library.
* <p>
* The coroutine library in luaj has the same behavior as the
* coroutine library in C, but is implemented using Java Threads to maintain
* the call state between invocations. Therefore it can be yielded from anywhere,
* coroutine library in C, but is implemented using Java Threads to maintain
* the call state between invocations. Therefore it can be yielded from anywhere,
* similar to the "Coco" yield-from-anywhere patch available for C-based lua.
* However, coroutines that are yielded but never resumed to complete their execution
* may not be collected by the garbage collector.
* <p>
* Typically, this library is included as part of a call to either
* may not be collected by the garbage collector.
* <p>
* Typically, this library is included as part of a call to either
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
* <pre> {@code
* Globals globals = JsePlatform.standardGlobals();
* System.out.println( globals.get("coroutine").get("running").call() );
* } </pre>
* <p>
* To instantiate and use it directly,
* To instantiate and use it directly,
* link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as:
* <pre> {@code
* Globals globals = new Globals();
@@ -82,7 +82,7 @@ public class CoroutineLib extends TwoArgFunction {
coroutine.set("yield", new yield());
coroutine.set("wrap", new wrap());
env.set("coroutine", coroutine);
env.get("package").get("loaded").set("coroutine", coroutine);
if (!env.get("package").isnil()) env.get("package").get("loaded").set("coroutine", coroutine);
return coroutine;
}
@@ -92,7 +92,7 @@ public class CoroutineLib extends TwoArgFunction {
}
}
final class resume extends VarArgFunction {
static final class resume extends VarArgFunction {
public Varargs invoke(Varargs args) {
final LuaThread t = args.checkthread(1);
return t.resume( args.subargs(2) );
@@ -127,7 +127,7 @@ public class CoroutineLib extends TwoArgFunction {
}
}
final class wrapper extends VarArgFunction {
static final class wrapper extends VarArgFunction {
final LuaThread luathread;
wrapper(LuaThread luathread) {
this.luathread = luathread;

View File

@@ -38,26 +38,26 @@ import org.luaj.vm2.Print;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.Varargs;
/**
* Subclass of {@link LibFunction} which implements the lua standard {@code debug}
* library.
* <p>
/**
* Subclass of {@link LibFunction} which implements the lua standard {@code debug}
* library.
* <p>
* The debug library in luaj tries to emulate the behavior of the corresponding C-based lua library.
* To do this, it must maintain a separate stack of calls to {@link LuaClosure} and {@link LibFunction}
* instances.
* To do this, it must maintain a separate stack of calls to {@link LuaClosure} and {@link LibFunction}
* instances.
* Especially when lua-to-java bytecode compiling is being used
* via a {@link org.luaj.vm2.Globals.Compiler} such as {@link org.luaj.vm2.luajc.LuaJC},
* this cannot be done in all cases.
* <p>
* Typically, this library is included as part of a call to either
* {@link org.luaj.vm2.lib.jse.JsePlatform#debugGlobals()} or
* via a {@link org.luaj.vm2.Globals.Compiler} such as {@link org.luaj.vm2.luajc.LuaJC},
* this cannot be done in all cases.
* <p>
* Typically, this library is included as part of a call to either
* {@link org.luaj.vm2.lib.jse.JsePlatform#debugGlobals()} or
* {@link org.luaj.vm2.lib.jme.JmePlatform#debugGlobals()}
* <pre> {@code
* Globals globals = JsePlatform.debugGlobals();
* System.out.println( globals.get("debug").get("traceback").call() );
* } </pre>
* <p>
* To instantiate and use it directly,
* To instantiate and use it directly,
* link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as:
* <pre> {@code
* Globals globals = new Globals();
@@ -84,27 +84,27 @@ public class DebugLib extends TwoArgFunction {
try { TRACE = (null != System.getProperty("TRACE")); } catch (Exception e) {}
}
private static final LuaString LUA = valueOf("Lua");
private static final LuaString QMARK = valueOf("?");
private static final LuaString CALL = valueOf("call");
private static final LuaString LINE = valueOf("line");
private static final LuaString COUNT = valueOf("count");
static final LuaString LUA = valueOf("Lua");
private static final LuaString QMARK = valueOf("?");
private static final LuaString CALL = valueOf("call");
private static final LuaString LINE = valueOf("line");
private static final LuaString COUNT = valueOf("count");
private static final LuaString RETURN = valueOf("return");
private static final LuaString FUNC = valueOf("func");
private static final LuaString ISTAILCALL = valueOf("istailcall");
private static final LuaString ISVARARG = valueOf("isvararg");
private static final LuaString NUPS = valueOf("nups");
private static final LuaString NPARAMS = valueOf("nparams");
private static final LuaString NAME = valueOf("name");
private static final LuaString NAMEWHAT = valueOf("namewhat");
private static final LuaString WHAT = valueOf("what");
private static final LuaString SOURCE = valueOf("source");
private static final LuaString SHORT_SRC = valueOf("short_src");
private static final LuaString LINEDEFINED = valueOf("linedefined");
private static final LuaString LASTLINEDEFINED = valueOf("lastlinedefined");
private static final LuaString CURRENTLINE = valueOf("currentline");
private static final LuaString ACTIVELINES = valueOf("activelines");
static final LuaString FUNC = valueOf("func");
static final LuaString ISTAILCALL = valueOf("istailcall");
static final LuaString ISVARARG = valueOf("isvararg");
static final LuaString NUPS = valueOf("nups");
static final LuaString NPARAMS = valueOf("nparams");
static final LuaString NAME = valueOf("name");
static final LuaString NAMEWHAT = valueOf("namewhat");
static final LuaString WHAT = valueOf("what");
static final LuaString SOURCE = valueOf("source");
static final LuaString SHORT_SRC = valueOf("short_src");
static final LuaString LINEDEFINED = valueOf("linedefined");
static final LuaString LASTLINEDEFINED = valueOf("lastlinedefined");
static final LuaString CURRENTLINE = valueOf("currentline");
static final LuaString ACTIVELINES = valueOf("activelines");
Globals globals;
@@ -135,19 +135,19 @@ public class DebugLib extends TwoArgFunction {
debug.set("upvalueid", new upvalueid());
debug.set("upvaluejoin", new upvaluejoin());
env.set("debug", debug);
env.get("package").get("loaded").set("debug", debug);
if (!env.get("package").isnil()) env.get("package").get("loaded").set("debug", debug);
return debug;
}
// debug.debug()
static final class debug extends ZeroArgFunction {
static final class debug extends ZeroArgFunction {
public LuaValue call() {
return NONE;
}
}
// debug.gethook ([thread])
final class gethook extends VarArgFunction {
final class gethook extends VarArgFunction {
public Varargs invoke(Varargs args) {
LuaThread t = args.narg() > 0 ? args.checkthread(1): globals.running;
LuaThread.State s = t.state;
@@ -159,10 +159,10 @@ public class DebugLib extends TwoArgFunction {
}
// debug.getinfo ([thread,] f [, what])
final class getinfo extends VarArgFunction {
final class getinfo extends VarArgFunction {
public Varargs invoke(Varargs args) {
int a=1;
LuaThread thread = args.isthread(a)? args.checkthread(a++): globals.running;
LuaThread thread = args.isthread(a)? args.checkthread(a++): globals.running;
LuaValue func = args.arg(a++);
String what = args.optjstring(a++, "flnStu");
DebugLib.CallStack callstack = callstack(thread);
@@ -222,10 +222,10 @@ public class DebugLib extends TwoArgFunction {
}
// debug.getlocal ([thread,] f, local)
final class getlocal extends VarArgFunction {
final class getlocal extends VarArgFunction {
public Varargs invoke(Varargs args) {
int a=1;
LuaThread thread = args.isthread(a)? args.checkthread(a++): globals.running;
LuaThread thread = args.isthread(a)? args.checkthread(a++): globals.running;
int level = args.checkint(a++);
int local = args.checkint(a++);
CallFrame f = callstack(thread).getCallFrame(level);
@@ -234,7 +234,7 @@ public class DebugLib extends TwoArgFunction {
}
// debug.getmetatable (value)
final class getmetatable extends LibFunction {
static final class getmetatable extends LibFunction {
public LuaValue call(LuaValue v) {
LuaValue mt = v.getmetatable();
return mt != null? mt: NIL;
@@ -249,7 +249,7 @@ public class DebugLib extends TwoArgFunction {
}
// debug.getupvalue (f, up)
static final class getupvalue extends VarArgFunction {
static final class getupvalue extends VarArgFunction {
public Varargs invoke(Varargs args) {
LuaValue func = args.checkfunction(1);
int up = args.checkint(2);
@@ -265,7 +265,7 @@ public class DebugLib extends TwoArgFunction {
}
// debug.getuservalue (u)
static final class getuservalue extends LibFunction {
static final class getuservalue extends LibFunction {
public LuaValue call(LuaValue u) {
return u.isuserdata()? u: NIL;
}
@@ -273,10 +273,10 @@ public class DebugLib extends TwoArgFunction {
// debug.sethook ([thread,] hook, mask [, count])
final class sethook extends VarArgFunction {
final class sethook extends VarArgFunction {
public Varargs invoke(Varargs args) {
int a=1;
LuaThread t = args.isthread(a)? args.checkthread(a++): globals.running;
LuaThread t = args.isthread(a)? args.checkthread(a++): globals.running;
LuaValue func = args.optfunction(a++, null);
String str = args.optjstring(a++,"");
int count = args.optint(a++,0);
@@ -298,20 +298,20 @@ public class DebugLib extends TwoArgFunction {
}
// debug.setlocal ([thread,] level, local, value)
final class setlocal extends VarArgFunction {
final class setlocal extends VarArgFunction {
public Varargs invoke(Varargs args) {
int a=1;
LuaThread thread = args.isthread(a)? args.checkthread(a++): globals.running;
LuaThread thread = args.isthread(a)? args.checkthread(a++): globals.running;
int level = args.checkint(a++);
int local = args.checkint(a++);
LuaValue value = args.arg(a++);
CallFrame f = callstack(thread).getCallFrame(level);
CallFrame f = callstack(thread).getCallFrame(level);
return f != null? f.setLocal(local, value): NONE;
}
}
// debug.setmetatable (value, table)
final class setmetatable extends TwoArgFunction {
static final class setmetatable extends TwoArgFunction {
public LuaValue call(LuaValue value, LuaValue table) {
LuaValue mt = table.opttable(null);
switch ( value.type() ) {
@@ -328,7 +328,7 @@ public class DebugLib extends TwoArgFunction {
}
// debug.setupvalue (f, up, value)
final class setupvalue extends VarArgFunction {
static final class setupvalue extends VarArgFunction {
public Varargs invoke(Varargs args) {
LuaValue func = args.checkfunction(1);
int up = args.checkint(2);
@@ -346,7 +346,7 @@ public class DebugLib extends TwoArgFunction {
}
// debug.setuservalue (udata, value)
final class setuservalue extends VarArgFunction {
static final class setuservalue extends VarArgFunction {
public Varargs invoke(Varargs args) {
Object o = args.checkuserdata(1);
LuaValue v = args.checkvalue(2);
@@ -358,10 +358,10 @@ public class DebugLib extends TwoArgFunction {
}
// debug.traceback ([thread,] [message [, level]])
final class traceback extends VarArgFunction {
final class traceback extends VarArgFunction {
public Varargs invoke(Varargs args) {
int a=1;
LuaThread thread = args.isthread(a)? args.checkthread(a++): globals.running;
LuaThread thread = args.isthread(a)? args.checkthread(a++): globals.running;
String message = args.optjstring(a++, null);
int level = args.optint(a++,1);
String tb = callstack(thread).traceback(level);
@@ -370,7 +370,7 @@ public class DebugLib extends TwoArgFunction {
}
// debug.upvalueid (f, n)
final class upvalueid extends VarArgFunction {
static final class upvalueid extends VarArgFunction {
public Varargs invoke(Varargs args) {
LuaValue func = args.checkfunction(1);
int up = args.checkint(2);
@@ -385,7 +385,7 @@ public class DebugLib extends TwoArgFunction {
}
// debug.upvaluejoin (f1, n1, f2, n2)
final class upvaluejoin extends VarArgFunction {
static final class upvaluejoin extends VarArgFunction {
public Varargs invoke(Varargs args) {
LuaClosure f1 = args.checkclosure(1);
int n1 = args.checkint(2);
@@ -565,7 +565,11 @@ public class DebugLib extends TwoArgFunction {
sb.append( ar.name );
sb.append( '\'' );
} else {
sb.append( "function <"+c.shortsource()+":"+c.linedefined()+">" );
sb.append( "function <" );
sb.append( c.shortsource() );
sb.append( ':' );
sb.append( c.linedefined() );
sb.append( '>' );
}
}
sb.append("\n\t[Java]: in ?");
@@ -583,7 +587,7 @@ public class DebugLib extends TwoArgFunction {
if (frame[calls-i].f == func)
return frame[i];
return null;
}
}
synchronized DebugInfo auxgetinfo(String what, LuaFunction f, CallFrame ci) {
@@ -637,7 +641,7 @@ public class DebugLib extends TwoArgFunction {
}
}
return ar;
}
}
}
@@ -673,16 +677,16 @@ public class DebugLib extends TwoArgFunction {
}
Varargs getLocal(int i) {
LuaString name = getlocalname(i);
if ( name != null )
return varargsOf( name, stack[i-1] );
if ( i >= 1 && i <= stack.length && stack[i-1] != null )
return varargsOf( name == null ? NIL : name, stack[i-1] );
else
return NIL;
}
Varargs setLocal(int i, LuaValue value) {
LuaString name = getlocalname(i);
if ( name != null ) {
if ( i >= 1 && i <= stack.length && stack[i-1] != null ) {
stack[i-1] = value;
return name;
return name == null ? NIL : name;
} else {
return NIL;
}
@@ -690,13 +694,13 @@ public class DebugLib extends TwoArgFunction {
int currentline() {
if ( !f.isclosure() ) return -1;
int[] li = f.checkclosure().p.lineinfo;
return li==null || pc<0 || pc>=li.length? -1: li[pc];
return li==null || pc<0 || pc>=li.length? -1: li[pc];
}
String sourceline() {
if ( !f.isclosure() ) return f.tojstring();
return f.checkclosure().p.shortsource() + ":" + currentline();
}
private int linedefined() {
int linedefined() {
return f.isclosure()? f.checkclosure().p.linedefined: -1;
}
LuaString getlocalname(int index) {
@@ -717,7 +721,7 @@ public class DebugLib extends TwoArgFunction {
static void lua_assert(boolean x) {
if (!x) throw new RuntimeException("lua_assert failed");
}
}
static class NameWhat {
final String name;
@@ -867,6 +871,10 @@ public class DebugLib extends TwoArgFunction {
if (reg == a) setreg = pc; /* jumped code can change 'a' */
break;
}
case Lua.OP_SETLIST: { // Lua.testAMode(Lua.OP_SETLIST) == false
if ( ((i>>14)&0x1ff) == 0 ) pc++; // if c == 0 then c stored in next op -> skip
break;
}
default:
if (Lua.testAMode(op) && reg == a) /* any instruction that set A */
setreg = pc;

View File

@@ -31,31 +31,31 @@ import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
/**
* Abstract base class extending {@link LibFunction} which implements the
* core of the lua standard {@code io} library.
* <p>
/**
* Abstract base class extending {@link LibFunction} which implements the
* core of the lua standard {@code io} library.
* <p>
* It contains the implementation of the io library support that is common to
* the JSE and JME platforms.
* In practice on of the concrete IOLib subclasses is chosen:
* {@link org.luaj.vm2.lib.jse.JseIoLib} for the JSE platform, and
* the JSE and JME platforms.
* In practice on of the concrete IOLib subclasses is chosen:
* {@link org.luaj.vm2.lib.jse.JseIoLib} for the JSE platform, and
* {@link org.luaj.vm2.lib.jme.JmeIoLib} for the JME platform.
* <p>
* The JSE implementation conforms almost completely to the C-based lua library,
* while the JME implementation follows closely except in the area of random-access files,
* which are difficult to support properly on JME.
* <p>
* Typically, this library is included as part of a call to either
* The JSE implementation conforms almost completely to the C-based lua library,
* while the JME implementation follows closely except in the area of random-access files,
* which are difficult to support properly on JME.
* <p>
* Typically, this library is included as part of a call to either
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
* <pre> {@code
* Globals globals = JsePlatform.standardGlobals();
* globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
* } </pre>
* In this example the platform-specific {@link org.luaj.vm2.lib.jse.JseIoLib} library will be loaded, which will include
* the base functionality provided by this class, whereas the {@link org.luaj.vm2.lib.jse.JsePlatform} would load the
* the base functionality provided by this class, whereas the {@link org.luaj.vm2.lib.jse.JsePlatform} would load the
* {@link org.luaj.vm2.lib.jse.JseIoLib}.
* <p>
* To instantiate and use it directly,
* To instantiate and use it directly,
* link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as:
* <pre> {@code
* Globals globals = new Globals();
@@ -73,10 +73,10 @@ import org.luaj.vm2.Varargs;
* @see org.luaj.vm2.lib.jme.JmeIoLib
* @see <a href="http://www.lua.org/manual/5.1/manual.html#5.7">http://www.lua.org/manual/5.1/manual.html#5.7</a>
*/
abstract
abstract
public class IoLib extends TwoArgFunction {
abstract
abstract
protected class File extends LuaValue{
abstract public void write( LuaString string ) throws IOException;
abstract public void flush() throws IOException;
@@ -85,12 +85,12 @@ public class IoLib extends TwoArgFunction {
abstract public boolean isclosed();
// returns new position
abstract public int seek(String option, int bytecount) throws IOException;
abstract public void setvbuf(String mode, int size);
abstract public void setvbuf(String mode, int size);
// get length remaining to read
abstract public int remaining() throws IOException;
abstract public int remaining() throws IOException;
// peek ahead one character
abstract public int peek() throws IOException, EOFException;
// return char if read, -1 if eof, throw IOException on other exception
abstract public int peek() throws IOException, EOFException;
// return char if read, -1 if eof, throw IOException on other exception
abstract public int read() throws IOException, EOFException;
// return number of bytes read if positive, false if eof, throw IOException on other exception
abstract public int read(byte[] bytes, int offset, int length) throws IOException;
@@ -123,29 +123,29 @@ public class IoLib extends TwoArgFunction {
/** Enumerated value representing a file type for a named file */
protected static final int FTYPE_NAMED = 3;
/**
* Wrap the standard input.
* @return File
/**
* Wrap the standard input.
* @return File
* @throws IOException
*/
abstract protected File wrapStdin() throws IOException;
/**
* Wrap the standard output.
* @return File
/**
* Wrap the standard output.
* @return File
* @throws IOException
*/
abstract protected File wrapStdout() throws IOException;
/**
* Wrap the standard error output.
* @return File
/**
* Wrap the standard error output.
* @return File
* @throws IOException
*/
abstract protected File wrapStderr() throws IOException;
/**
* Open a file in a particular mode.
* Open a file in a particular mode.
* @param filename
* @param readMode true if opening in read mode
* @param appendMode true if opening in append mode
@@ -157,7 +157,7 @@ public class IoLib extends TwoArgFunction {
abstract protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException;
/**
* Open a temporary file.
* Open a temporary file.
* @return File object if successful
* @throws IOException if could not be opened
*/
@@ -167,7 +167,7 @@ public class IoLib extends TwoArgFunction {
* Start a new process and return a file for input or output
* @param prog the program to execute
* @param mode "r" to read, "w" to write
* @return File to read to or write from
* @return File to read to or write from
* @throws IOException if an i/o exception occurs
*/
abstract protected File openProgram(String prog, String mode) throws IOException;
@@ -178,7 +178,7 @@ public class IoLib extends TwoArgFunction {
private static final LuaValue STDIN = valueOf("stdin");
private static final LuaValue STDOUT = valueOf("stdout");
private static final LuaValue STDERR = valueOf("stderr");
private static final LuaValue STDERR = valueOf("stderr");
private static final LuaValue FILE = valueOf("file");
private static final LuaValue CLOSED_FILE = valueOf("closed file");
@@ -256,7 +256,7 @@ public class IoLib extends TwoArgFunction {
// return the table
env.set("io", t);
env.get("package").get("loaded").set("io", t);
if (!env.get("package").isnil()) env.get("package").get("loaded").set("io", t);
return t;
}
@@ -316,7 +316,7 @@ public class IoLib extends TwoArgFunction {
return infile!=null? infile: (infile=ioopenfile(FTYPE_STDIN, "-","r"));
}
// io.flush() -> bool
// io.flush() -> bool
public Varargs _io_flush() throws IOException {
checkopen(output());
outfile.flush();
@@ -337,7 +337,7 @@ public class IoLib extends TwoArgFunction {
// io.input([file]) -> file
public Varargs _io_input(LuaValue file) {
infile = file.isnil()? input():
infile = file.isnil()? input():
file.isstring()? ioopenfile(FTYPE_NAMED, file.checkjstring(),"r"):
checkfile(file);
return infile;
@@ -345,7 +345,7 @@ public class IoLib extends TwoArgFunction {
// io.output(filename) -> file
public Varargs _io_output(LuaValue filename) {
outfile = filename.isnil()? output():
outfile = filename.isnil()? output():
filename.isstring()? ioopenfile(FTYPE_NAMED, filename.checkjstring(),"w"):
checkfile(filename);
return outfile;
@@ -420,7 +420,7 @@ public class IoLib extends TwoArgFunction {
return valueOf( checkfile(file).seek(whence,offset) );
}
// file:write(...) -> void
// file:write(...) -> void
public Varargs _file_write(LuaValue file, Varargs subargs) throws IOException {
return iowrite(checkfile(file),subargs);
}
@@ -467,8 +467,8 @@ public class IoLib extends TwoArgFunction {
return LuaValue.TRUE;
}
private static Varargs errorresult(Exception ioe) {
String s = ioe.getMessage();
static Varargs errorresult(Exception ioe) {
String s = ioe.getMessage();
return errorresult("io error: "+(s!=null? s: ioe.toString()));
}
@@ -509,8 +509,8 @@ public class IoLib extends TwoArgFunction {
case 'a': vi = freadall(f); break item;
}
}
default:
return argerror( i+1, "(invalid format)" );
default:
return argerror( i+1, "(invalid format)" );
}
if ( (v[i++] = vi).isnil() )
break;
@@ -544,7 +544,7 @@ public class IoLib extends TwoArgFunction {
}
boolean isreadmode = mode.startsWith("r");
boolean isappend = mode.startsWith("a");
boolean isupdate = mode.indexOf("+") > 0;
boolean isupdate = mode.indexOf('+') > 0;
boolean isbinary = mode.endsWith("b");
return openFile( filename, isreadmode, isappend, isupdate, isbinary );
}
@@ -564,7 +564,7 @@ public class IoLib extends TwoArgFunction {
int c;
try {
if ( lineonly ) {
loop: while ( (c = f.read()) > 0 ) {
loop: while ( (c = f.read()) > 0 ) {
switch ( c ) {
case '\r': break;
case '\n': break loop;
@@ -572,13 +572,13 @@ public class IoLib extends TwoArgFunction {
}
}
} else {
while ( (c = f.read()) > 0 )
while ( (c = f.read()) > 0 )
baos.write(c);
}
} catch ( EOFException e ) {
c = -1;
}
return ( c < 0 && baos.size() == 0 )?
return ( c < 0 && baos.size() == 0 )?
(LuaValue) NIL:
(LuaValue) LuaString.valueUsing(baos.toByteArray());
}
@@ -619,7 +619,7 @@ public class IoLib extends TwoArgFunction {
if ( baos != null )
baos.write( c );
}
}
}

View File

@@ -139,7 +139,7 @@ abstract public class LibFunction extends LuaFunction {
}
public String tojstring() {
return name != null? name: super.tojstring();
return name != null ? "function: " + name : super.tojstring();
}
/**

View File

@@ -28,13 +28,13 @@ import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
/**
* Subclass of {@link LibFunction} which implements the lua standard {@code math}
* library.
* <p>
* It contains only the math library support that is possible on JME.
* For a more complete implementation based on math functions specific to JSE
* use {@link org.luaj.vm2.lib.jse.JseMathLib}.
/**
* Subclass of {@link LibFunction} which implements the lua standard {@code math}
* library.
* <p>
* It contains only the math library support that is possible on JME.
* For a more complete implementation based on math functions specific to JSE
* use {@link org.luaj.vm2.lib.jse.JseMathLib}.
* In Particular the following math functions are <b>not</b> implemented by this library:
* <ul>
* <li>acos</li>
@@ -47,21 +47,21 @@ import org.luaj.vm2.Varargs;
* <li>atan2</li>
* </ul>
* <p>
* The implementations of {@code exp()} and {@code pow()} are constructed by
* The implementations of {@code exp()} and {@code pow()} are constructed by
* hand for JME, so will be slower and less accurate than when executed on the JSE platform.
* <p>
* Typically, this library is included as part of a call to either
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or
* <p>
* Typically, this library is included as part of a call to either
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or
* {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
* <pre> {@code
* Globals globals = JsePlatform.standardGlobals();
* System.out.println( globals.get("math").get("sqrt").call( LuaValue.valueOf(2) ) );
* } </pre>
* When using {@link org.luaj.vm2.lib.jse.JsePlatform} as in this example,
* the subclass {@link org.luaj.vm2.lib.jse.JseMathLib} will
* When using {@link org.luaj.vm2.lib.jse.JsePlatform} as in this example,
* the subclass {@link org.luaj.vm2.lib.jse.JseMathLib} will
* be included, which also includes this base functionality.
* <p>
* To instantiate and use it directly,
* To instantiate and use it directly,
* link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as:
* <pre> {@code
* Globals globals = new Globals();
@@ -70,8 +70,8 @@ import org.luaj.vm2.Varargs;
* globals.load(new MathLib());
* System.out.println( globals.get("math").get("sqrt").call( LuaValue.valueOf(2) ) );
* } </pre>
* Doing so will ensure the library is properly initialized
* and loaded into the globals table.
* Doing so will ensure the library is properly initialized
* and loaded into the globals table.
* <p>
* This has been implemented to match as closely as possible the behavior in the corresponding library in C.
* @see LibFunction
@@ -87,8 +87,8 @@ public class MathLib extends TwoArgFunction {
*/
public static MathLib MATHLIB = null;
/** Construct a MathLib, which can be initialized by calling it with a
* modname string, and a global environment table as arguments using
/** Construct a MathLib, which can be initialized by calling it with a
* modname string, and a global environment table as arguments using
* {@link #call(LuaValue, LuaValue)}. */
public MathLib() {
MATHLIB = this;
@@ -125,7 +125,7 @@ public class MathLib extends TwoArgFunction {
math.set("sqrt", new sqrt());
math.set("tan", new tan());
env.set("math", math);
env.get("package").get("loaded").set("math", math);
if (!env.get("package").isnil()) env.get("package").get("loaded").set("math", math);
return math;
}
@@ -158,15 +158,17 @@ public class MathLib extends TwoArgFunction {
exp(MathLib mathlib) {
this.mathlib = mathlib;
}
protected double call(double d) {
return mathlib.dpow_lib(Math.E,d);
}
protected double call(double d) {
return mathlib.dpow_lib(Math.E,d);
}
}
static final class fmod extends BinaryOp {
protected double call(double x, double y) {
double q = x/y;
return x - y * (q>=0? Math.floor(q): Math.ceil(q));
static final class fmod extends TwoArgFunction {
public LuaValue call(LuaValue xv, LuaValue yv) {
if (xv.islong() && yv.islong()) {
return valueOf(xv.tolong() % yv.tolong());
}
return valueOf(xv.checkdouble() % yv.checkdouble());
}
}
static final class ldexp extends BinaryOp {
@@ -194,27 +196,36 @@ public class MathLib extends TwoArgFunction {
static class max extends VarArgFunction {
public Varargs invoke(Varargs args) {
double m = args.checkdouble(1);
for ( int i=2,n=args.narg(); i<=n; ++i )
m = Math.max(m,args.checkdouble(i));
return valueOf(m);
LuaValue m = args.checkvalue(1);
for ( int i=2,n=args.narg(); i<=n; ++i ) {
LuaValue v = args.checkvalue(i);
if (m.lt_b(v)) m = v;
}
return m;
}
}
static class min extends VarArgFunction {
public Varargs invoke(Varargs args) {
double m = args.checkdouble(1);
for ( int i=2,n=args.narg(); i<=n; ++i )
m = Math.min(m,args.checkdouble(i));
return valueOf(m);
LuaValue m = args.checkvalue(1);
for ( int i=2,n=args.narg(); i<=n; ++i ) {
LuaValue v = args.checkvalue(i);
if (v.lt_b(m)) m = v;
}
return m;
}
}
static class modf extends VarArgFunction {
public Varargs invoke(Varargs args) {
double x = args.checkdouble(1);
LuaValue n = args.arg1();
/* number is its own integer part, no fractional part */
if (n.islong()) return varargsOf(n, valueOf(0.0));
double x = n.checkdouble();
/* integer part (rounds toward zero) */
double intPart = ( x > 0 ) ? Math.floor( x ) : Math.ceil( x );
double fracPart = x - intPart;
/* fractional part (test needed for inf/-inf) */
double fracPart = x == intPart ? 0.0 : x - intPart;
return varargsOf( valueOf(intPart), valueOf(fracPart) );
}
}
@@ -252,26 +263,26 @@ public class MathLib extends TwoArgFunction {
/** compute power using installed math library, or default if there is no math library installed */
public static LuaValue dpow(double a, double b) {
return LuaDouble.valueOf(
return LuaDouble.valueOf(
MATHLIB!=null?
MATHLIB.dpow_lib(a,b):
dpow_default(a,b) );
}
public static double dpow_d(double a, double b) {
return MATHLIB!=null?
MATHLIB.dpow_lib(a,b):
return MATHLIB!=null?
MATHLIB.dpow_lib(a,b):
dpow_default(a,b);
}
/**
* Hook to override default dpow behavior with faster implementation.
/**
* Hook to override default dpow behavior with faster implementation.
*/
public double dpow_lib(double a, double b) {
return dpow_default(a,b);
}
/**
* Default JME version computes using longhand heuristics.
/**
* Default JME version computes using longhand heuristics.
*/
protected static double dpow_default(double a, double b) {
if ( b < 0 )

View File

@@ -35,17 +35,17 @@ import org.luaj.vm2.Varargs;
* Subclass of {@link LibFunction} which implements the standard lua {@code os} library.
* <p>
* It is a usable base with simplified stub functions
* for library functions that cannot be implemented uniformly
* on Jse and Jme.
* for library functions that cannot be implemented uniformly
* on Jse and Jme.
* <p>
* This can be installed as-is on either platform, or extended
* This can be installed as-is on either platform, or extended
* and refined to be used in a complete Jse implementation.
* <p>
* Because the nature of the {@code os} library is to encapsulate
* os-specific features, the behavior of these functions varies considerably
* from their counterparts in the C platform.
* Because the nature of the {@code os} library is to encapsulate
* os-specific features, the behavior of these functions varies considerably
* from their counterparts in the C platform.
* <p>
* The following functions have limited implementations of features
* The following functions have limited implementations of features
* that are not supported well on Jme:
* <ul>
* <li>{@code execute()}</li>
@@ -54,7 +54,7 @@ import org.luaj.vm2.Varargs;
* <li>{@code tmpname()}</li>
* </ul>
* <p>
* Typically, this library is included as part of a call to either
* Typically, this library is included as part of a call to either
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
* <pre> {@code
* Globals globals = JsePlatform.standardGlobals();
@@ -63,7 +63,7 @@ import org.luaj.vm2.Varargs;
* In this example the platform-specific {@link org.luaj.vm2.lib.jse.JseOsLib} library will be loaded, which will include
* the base functionality provided by this class.
* <p>
* To instantiate and use it directly,
* To instantiate and use it directly,
* link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as:
* <pre> {@code
* Globals globals = new Globals();
@@ -80,8 +80,8 @@ import org.luaj.vm2.Varargs;
* @see <a href="http://www.lua.org/manual/5.1/manual.html#5.8">http://www.lua.org/manual/5.1/manual.html#5.8</a>
*/
public class OsLib extends TwoArgFunction {
public static String TMP_PREFIX = ".luaj";
public static String TMP_SUFFIX = "tmp";
public static final String TMP_PREFIX = ".luaj";
public static final String TMP_SUFFIX = "tmp";
private static final int CLOCK = 0;
private static final int DATE = 1;
@@ -114,8 +114,8 @@ public class OsLib extends TwoArgFunction {
protected Globals globals;
/**
* Create and OsLib instance.
/**
* Create and OsLib instance.
*/
public OsLib() {
}
@@ -132,7 +132,7 @@ public class OsLib extends TwoArgFunction {
for (int i = 0; i < NAMES.length; ++i)
os.set(NAMES[i], new OsLibFunc(i, NAMES[i]));
env.set("os", os);
env.get("package").get("loaded").set("os", os);
if (!env.get("package").isnil()) env.get("package").get("loaded").set("os", os);
return os;
}
@@ -200,8 +200,8 @@ public class OsLib extends TwoArgFunction {
}
/**
* @return an approximation of the amount in seconds of CPU time used by
* the program. For luaj this simple returns the elapsed time since the
* @return an approximation of the amount in seconds of CPU time used by
* the program. For luaj this simple returns the elapsed time since the
* OsLib class was loaded.
*/
protected double clock() {
@@ -209,7 +209,7 @@ public class OsLib extends TwoArgFunction {
}
/**
* Returns the number of seconds from time t1 to time t2.
* Returns the number of seconds from time t1 to time t2.
* In POSIX, Windows, and some other systems, this value is exactly t2-t1.
* @param t2
* @param t1
@@ -220,21 +220,21 @@ public class OsLib extends TwoArgFunction {
}
/**
* If the time argument is present, this is the time to be formatted
* (see the os.time function for a description of this value).
* If the time argument is present, this is the time to be formatted
* (see the os.time function for a description of this value).
* Otherwise, date formats the current time.
*
* Date returns the date as a string,
* Date returns the date as a string,
* formatted according to the same rules as ANSII strftime, but without
* support for %g, %G, or %V.
*
* When called without arguments, date returns a reasonable date and
* time representation that depends on the host system and on the
* When called without arguments, date returns a reasonable date and
* time representation that depends on the host system and on the
* current locale (that is, os.date() is equivalent to os.date("%c")).
*
* @param format
*
* @param format
* @param time time since epoch, or -1 if not supplied
* @return a LString or a LTable containing date and time,
* @return a LString or a LTable containing date and time,
* formatted according to the given string format.
*/
public String date(String format, double time) {
@@ -277,8 +277,8 @@ public class OsLib extends TwoArgFunction {
break;
case 'B':
result.append(MonthName[d.get(Calendar.MONTH)]);
break;
case 'c':
break;
case 'c':
result.append(date("%a %b %d %H:%M:%S %Y", time));
break;
case 'd':
@@ -314,7 +314,7 @@ public class OsLib extends TwoArgFunction {
case 'w':
result.append(String.valueOf((d.get(Calendar.DAY_OF_WEEK)+6)%7));
break;
case 'W':
case 'W':
result.append(String.valueOf(weekNumber(d, 1)));
break;
case 'x':
@@ -372,7 +372,7 @@ public class OsLib extends TwoArgFunction {
}
private int timeZoneOffset(Calendar d) {
int localStandarTimeMillis = (
int localStandarTimeMillis = (
d.get(Calendar.HOUR_OF_DAY) * 3600 +
d.get(Calendar.MINUTE) * 60 +
d.get(Calendar.SECOND)) * 1000;
@@ -381,28 +381,28 @@ public class OsLib extends TwoArgFunction {
d.get(Calendar.YEAR),
d.get(Calendar.MONTH),
d.get(Calendar.DAY_OF_MONTH),
d.get(Calendar.DAY_OF_WEEK),
d.get(Calendar.DAY_OF_WEEK),
localStandarTimeMillis) / 1000;
}
private boolean isDaylightSavingsTime(Calendar d) {
return timeZoneOffset(d) != d.getTimeZone().getRawOffset() / 1000;
return timeZoneOffset(d) != d.getTimeZone().getRawOffset() / 1000;
}
/**
* This function is equivalent to the C function system.
* It passes command to be executed by an operating system shell.
* It returns a status code, which is system-dependent.
* If command is absent, then it returns nonzero if a shell
/**
* This function is equivalent to the C function system.
* It passes command to be executed by an operating system shell.
* It returns a status code, which is system-dependent.
* If command is absent, then it returns nonzero if a shell
* is available and zero otherwise.
* @param command command to pass to the system
*/
*/
protected Varargs execute(String command) {
return varargsOf(NIL, valueOf("exit"), ONE);
}
/**
* Calls the C function exit, with an optional code, to terminate the host program.
* Calls the C function exit, with an optional code, to terminate the host program.
* @param code
*/
protected void exit(int code) {
@@ -415,13 +415,13 @@ public class OsLib extends TwoArgFunction {
* or null if the variable is not defined in either environment.
*
* The default implementation, which is used by the JmePlatform,
* only queryies System.getProperty().
* only queryies System.getProperty().
*
* The JsePlatform overrides this behavior and returns the
* environment variable value using System.getenv() if it exists,
* environment variable value using System.getenv() if it exists,
* or the System property value if it does not.
*
* A SecurityException may be thrown if access is not allowed
* A SecurityException may be thrown if access is not allowed
* for 'varname'.
* @param varname
* @return String value, or null if not defined
@@ -431,10 +431,10 @@ public class OsLib extends TwoArgFunction {
}
/**
* Deletes the file or directory with the given name.
* Directories must be empty to be removed.
* Deletes the file or directory with the given name.
* Directories must be empty to be removed.
* If this function fails, it throws and IOException
*
*
* @param filename
* @throws IOException if it fails
*/
@@ -443,9 +443,9 @@ public class OsLib extends TwoArgFunction {
}
/**
* Renames file or directory named oldname to newname.
* Renames file or directory named oldname to newname.
* If this function fails,it throws and IOException
*
*
* @param oldname old file name
* @param newname new file name
* @throws IOException if it fails
@@ -455,21 +455,21 @@ public class OsLib extends TwoArgFunction {
}
/**
* Sets the current locale of the program. locale is a string specifying
* a locale; category is an optional string describing which category to change:
* "all", "collate", "ctype", "monetary", "numeric", or "time"; the default category
* is "all".
* Sets the current locale of the program. locale is a string specifying
* a locale; category is an optional string describing which category to change:
* "all", "collate", "ctype", "monetary", "numeric", or "time"; the default category
* is "all".
*
* If locale is the empty string, the current locale is set to an implementation-
* defined native locale. If locale is the string "C", the current locale is set
* defined native locale. If locale is the string "C", the current locale is set
* to the standard C locale.
*
* When called with null as the first argument, this function only returns the
* When called with null as the first argument, this function only returns the
* name of the current locale for the given category.
*
*
* @param locale
* @param category
* @return the name of the new locale, or null if the request
* @return the name of the new locale, or null if the request
* cannot be honored.
*/
protected String setlocale(String locale, String category) {
@@ -477,10 +477,10 @@ public class OsLib extends TwoArgFunction {
}
/**
* Returns the current time when called without arguments,
* or a time representing the date and time specified by the given table.
* This table must have fields year, month, and day,
* and may have fields hour, min, sec, and isdst
* Returns the current time when called without arguments,
* or a time representing the date and time specified by the given table.
* This table must have fields year, month, and day,
* and may have fields hour, min, sec, and isdst
* (for a description of these fields, see the os.date function).
* @param table
* @return long value for the time
@@ -504,15 +504,15 @@ public class OsLib extends TwoArgFunction {
}
/**
* Returns a string with a file name that can be used for a temporary file.
* The file must be explicitly opened before its use and explicitly removed
* Returns a string with a file name that can be used for a temporary file.
* The file must be explicitly opened before its use and explicitly removed
* when no longer needed.
*
* On some systems (POSIX), this function also creates a file with that name,
* to avoid security risks. (Someone else might create the file with wrong
* permissions in the time between getting the name and creating the file.)
* You still have to open the file to use it and to remove it (even if you
* do not use it).
* On some systems (POSIX), this function also creates a file with that name,
* to avoid security risks. (Someone else might create the file with wrong
* permissions in the time between getting the name and creating the file.)
* You still have to open the file to use it and to remove it (even if you
* do not use it).
*
* @return String filename to use
*/

View File

@@ -81,23 +81,26 @@ public class PackageLib extends TwoArgFunction {
/** The default value to use for package.path. This can be set with the system property
* <code>"luaj.package.path"</code>, and is <code>"?.lua"</code> by default. */
public static String DEFAULT_LUA_PATH;
public static final String DEFAULT_LUA_PATH;
static {
String path = null;
try {
DEFAULT_LUA_PATH = System.getProperty("luaj.package.path");
path = System.getProperty("luaj.package.path");
} catch (Exception e) {
System.out.println(e.toString());
}
if (DEFAULT_LUA_PATH == null)
DEFAULT_LUA_PATH = "?.lua";
if (path == null) {
path = "?.lua";
}
DEFAULT_LUA_PATH = path;
}
private static final LuaString _LOADED = valueOf("loaded");
static final LuaString _LOADED = valueOf("loaded");
private static final LuaString _LOADLIB = valueOf("loadlib");
private static final LuaString _PRELOAD = valueOf("preload");
private static final LuaString _PATH = valueOf("path");
private static final LuaString _SEARCHPATH = valueOf("searchpath");
private static final LuaString _SEARCHERS = valueOf("searchers");
static final LuaString _PRELOAD = valueOf("preload");
static final LuaString _PATH = valueOf("path");
static final LuaString _SEARCHPATH = valueOf("searchpath");
static final LuaString _SEARCHERS = valueOf("searchers");
/** The globals that were used to load this library. */
Globals globals;
@@ -252,7 +255,6 @@ public class PackageLib extends TwoArgFunction {
public class lua_searcher extends VarArgFunction {
public Varargs invoke(Varargs args) {
LuaString name = args.checkstring(1);
InputStream is = null;
// get package path
LuaValue path = package_.get(_PATH);

View File

@@ -24,32 +24,32 @@ package org.luaj.vm2.lib;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.luaj.vm2.LuaClosure;
import org.luaj.vm2.Buffer;
import org.luaj.vm2.LuaClosure;
import org.luaj.vm2.LuaString;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.compiler.DumpState;
/**
* Subclass of {@link LibFunction} which implements the lua standard {@code string}
* library.
/**
* Subclass of {@link LibFunction} which implements the lua standard {@code string}
* library.
* <p>
* Typically, this library is included as part of a call to either
* Typically, this library is included as part of a call to either
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
* <pre> {@code
* Globals globals = JsePlatform.standardGlobals();
* System.out.println( globals.get("string").get("upper").call( LuaValue.valueOf("abcde") ) );
* } </pre>
* <p>
* To instantiate and use it directly,
* To instantiate and use it directly,
* link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as:
* <pre> {@code
* Globals globals = new Globals();
* globals.load(new JseBaseLib());
* globals.load(new PackageLib());
* globals.load(new StringLib());
* globals.load(new JseStringLib());
* System.out.println( globals.get("string").get("upper").call( LuaValue.valueOf("abcde") ) );
* } </pre>
* <p>
@@ -61,8 +61,8 @@ import org.luaj.vm2.compiler.DumpState;
*/
public class StringLib extends TwoArgFunction {
/** Construct a StringLib, which can be initialized by calling it with a
* modname string, and a global environment table as arguments using
/** Construct a StringLib, which can be initialized by calling it with a
* modname string, and a global environment table as arguments using
* {@link #call(LuaValue, LuaValue)}. */
public StringLib() {
}
@@ -75,8 +75,8 @@ public class StringLib extends TwoArgFunction {
* If the shared strings metatable instance is null, will set the metatable as
* the global shared metatable for strings.
* <P>
* All tables and metatables are read-write by default so if this will be used in
* a server environment, sandboxing should be used. In particular, the
* All tables and metatables are read-write by default so if this will be used in
* a server environment, sandboxing should be used. In particular, the
* {@link LuaString#s_metatable} table should probably be made read-only.
* @param modname the module name supplied if this is loaded via 'require'.
* @param env the environment to load into, typically a Globals instance.
@@ -97,17 +97,17 @@ public class StringLib extends TwoArgFunction {
string.set("reverse", new reverse());
string.set("sub", new sub());
string.set("upper", new upper());
LuaTable mt = LuaValue.tableOf(
new LuaValue[] { INDEX, string });
env.set("string", string);
env.get("package").get("loaded").set("string", string);
if (LuaString.s_metatable == null)
LuaString.s_metatable = mt;
if (!env.get("package").isnil()) env.get("package").get("loaded").set("string", string);
if (LuaString.s_metatable == null) {
LuaString.s_metatable = LuaValue.tableOf(new LuaValue[] { INDEX, string });
}
return string;
}
/**
* string.byte (s [, i [, j]])
* string.byte (s [, i [, j]])
*
* Returns the internal numerical codes of the
* characters s[i], s[i+1], ..., s[j]. The default value for i is 1; the
@@ -137,12 +137,12 @@ public class StringLib extends TwoArgFunction {
}
}
/**
/**
* string.char (...)
*
* Receives zero or more integers. Returns a string with length equal
* to the number of arguments, in which each character has the internal
* numerical code equal to its corresponding argument.
* Receives zero or more integers. Returns a string with length equal
* to the number of arguments, in which each character has the internal
* numerical code equal to its corresponding argument.
*
* Note that numerical codes are not necessarily portable across platforms.
*
@@ -154,28 +154,30 @@ public class StringLib extends TwoArgFunction {
byte[] bytes = new byte[n];
for ( int i=0, a=1; i<n; i++, a++ ) {
int c = args.checkint(a);
if (c<0 || c>=256) argerror(a, "invalid value");
if (c<0 || c>=256) argerror(a, "invalid value for string.char [0; 255]: " + c);
bytes[i] = (byte) c;
}
return LuaString.valueUsing( bytes );
}
}
/**
* string.dump (function)
/**
* string.dump (function[, stripDebug])
*
* Returns a string containing a binary representation of the given function,
* so that a later loadstring on this string returns a copy of the function.
* Returns a string containing a binary representation of the given function,
* so that a later loadstring on this string returns a copy of the function.
* function must be a Lua function without upvalues.
*
* Boolean param stripDebug - true to strip debugging info, false otherwise.
* The default value for stripDebug is true.
*
* TODO: port dumping code as optional add-on
*/
static final class dump extends OneArgFunction {
public LuaValue call(LuaValue arg) {
LuaValue f = arg.checkfunction();
static final class dump extends VarArgFunction {
public Varargs invoke(Varargs args) {
LuaValue f = args.checkfunction(1);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
DumpState.dump( ((LuaClosure)f).p, baos, true );
DumpState.dump( ((LuaClosure)f).p, baos, args.optboolean(2, true) );
return LuaString.valueUsing(baos.toByteArray());
} catch (IOException e) {
return error( e.getMessage() );
@@ -183,20 +185,20 @@ public class StringLib extends TwoArgFunction {
}
}
/**
/**
* string.find (s, pattern [, init [, plain]])
*
* Looks for the first match of pattern in the string s.
* If it finds a match, then find returns the indices of s
* where this occurrence starts and ends; otherwise, it returns nil.
* A third, optional numerical argument init specifies where to start the search;
* its default value is 1 and may be negative. A value of true as a fourth,
* optional argument plain turns off the pattern matching facilities,
* so the function does a plain "find substring" operation,
* with no characters in pattern being considered "magic".
* Looks for the first match of pattern in the string s.
* If it finds a match, then find returns the indices of s
* where this occurrence starts and ends; otherwise, it returns nil.
* A third, optional numerical argument init specifies where to start the search;
* its default value is 1 and may be negative. A value of true as a fourth,
* optional argument plain turns off the pattern matching facilities,
* so the function does a plain "find substring" operation,
* with no characters in pattern being considered "magic".
* Note that if plain is given, then init must be given as well.
*
* If the pattern has captures, then in a successful match the captured values
* If the pattern has captures, then in a successful match the captured values
* are also returned, after the two indices.
*/
static final class find extends VarArgFunction {
@@ -205,30 +207,30 @@ public class StringLib extends TwoArgFunction {
}
}
/**
/**
* string.format (formatstring, ...)
*
* Returns a formatted version of its variable number of arguments following
* the description given in its first argument (which must be a string).
* The format string follows the same rules as the printf family of standard C functions.
* The only differences are that the options/modifiers *, l, L, n, p, and h are not supported
* and that there is an extra option, q. The q option formats a string in a form suitable
* to be safely read back by the Lua interpreter: the string is written between double quotes,
* and all double quotes, newlines, embedded zeros, and backslashes in the string are correctly
* Returns a formatted version of its variable number of arguments following
* the description given in its first argument (which must be a string).
* The format string follows the same rules as the printf family of standard C functions.
* The only differences are that the options/modifiers *, l, L, n, p, and h are not supported
* and that there is an extra option, q. The q option formats a string in a form suitable
* to be safely read back by the Lua interpreter: the string is written between double quotes,
* and all double quotes, newlines, embedded zeros, and backslashes in the string are correctly
* escaped when written. For instance, the call
* string.format('%q', 'a string with "quotes" and \n new line')
*
* will produce the string:
* "a string with \"quotes\" and \
* new line"
*
* The options c, d, E, e, f, g, G, i, o, u, X, and x all expect a number as argument,
* whereas q and s expect a string.
*
* This function does not accept string values containing embedded zeros,
* except as arguments to the q option.
* The options c, d, E, e, f, g, G, i, o, u, X, and x all expect a number as argument,
* whereas q and s expect a string.
*
* This function does not accept string values containing embedded zeros,
* except as arguments to the q option.
*/
static final class format extends VarArgFunction {
final class format extends VarArgFunction {
public Varargs invoke(Varargs args) {
LuaString fmt = args.checkstring( 1 );
final int n = fmt.length();
@@ -259,7 +261,7 @@ public class StringLib extends TwoArgFunction {
break;
case 'i':
case 'd':
fdsc.format( result, args.checkint( arg ) );
fdsc.format( result, args.checklong( arg ) );
break;
case 'o':
case 'u':
@@ -298,7 +300,7 @@ public class StringLib extends TwoArgFunction {
}
}
private static void addquoted(Buffer buf, LuaString s) {
static void addquoted(Buffer buf, LuaString s) {
int c;
buf.append( (byte) '"' );
for ( int i = 0, n = s.length(); i < n; i++ ) {
@@ -328,7 +330,7 @@ public class StringLib extends TwoArgFunction {
private static final String FLAGS = "-+ #0";
static class FormatDesc {
class FormatDesc {
private boolean leftAdjust;
private boolean zeroPad;
@@ -338,11 +340,13 @@ public class StringLib extends TwoArgFunction {
private static final int MAX_FLAGS = 5;
private int width;
private int precision;
int precision;
public final int conversion;
public final int length;
public final String src;
public FormatDesc(Varargs args, LuaString strfrmt, final int start) {
int p = start, n = strfrmt.length();
int c = 0;
@@ -390,6 +394,7 @@ public class StringLib extends TwoArgFunction {
zeroPad &= !leftAdjust; // '-' overrides '0'
conversion = c;
length = p - start;
src = strfrmt.substring(start - 1, p).tojstring();
}
public void format(Buffer buf, byte c) {
@@ -465,8 +470,7 @@ public class StringLib extends TwoArgFunction {
}
public void format(Buffer buf, double x) {
// TODO
buf.append( String.valueOf( x ) );
buf.append( StringLib.this.format(src, x) );
}
public void format(Buffer buf, LuaString s) {
@@ -476,27 +480,31 @@ public class StringLib extends TwoArgFunction {
buf.append(s);
}
public static final void pad(Buffer buf, char c, int n) {
public final void pad(Buffer buf, char c, int n) {
byte b = (byte)c;
while ( n-- > 0 )
buf.append(b);
}
}
/**
protected String format(String src, double x) {
return String.valueOf(x);
}
/**
* string.gmatch (s, pattern)
*
* Returns an iterator function that, each time it is called, returns the next captures
* from pattern over string s. If pattern specifies no captures, then the
* whole match is produced in each call.
* Returns an iterator function that, each time it is called, returns the next captures
* from pattern over string s. If pattern specifies no captures, then the
* whole match is produced in each call.
*
* As an example, the following loop
* s = "hello world from Lua"
* for w in string.gmatch(s, "%a+") do
* print(w)
* end
*
* will iterate over all the words from string s, printing one per line.
*
* will iterate over all the words from string s, printing one per line.
* The next example collects all pairs key=value from the given string into a table:
* t = {}
* s = "from=world, to=Lua"
@@ -504,7 +512,7 @@ public class StringLib extends TwoArgFunction {
* t[k] = v
* end
*
* For this function, a '^' at the start of a pattern does not work as an anchor,
* For this function, a '^' at the start of a pattern does not work as an anchor,
* as this would prevent the iteration.
*/
static final class gmatch extends VarArgFunction {
@@ -525,12 +533,13 @@ public class StringLib extends TwoArgFunction {
this.soffset = 0;
}
public Varargs invoke(Varargs args) {
for ( ; soffset<srclen; soffset++ ) {
for ( ; soffset<=srclen; soffset++ ) {
ms.reset();
int res = ms.match(soffset, 0);
if ( res >=0 ) {
int soff = soffset;
soffset = res;
if (soff == res) soffset++; /* empty match? go at least one position */
return ms.push_captures( true, soff, res );
}
}
@@ -539,28 +548,28 @@ public class StringLib extends TwoArgFunction {
}
/**
/**
* string.gsub (s, pattern, repl [, n])
* Returns a copy of s in which all (or the first n, if given) occurrences of the
* pattern have been replaced by a replacement string specified by repl, which
* may be a string, a table, or a function. gsub also returns, as its second value,
* Returns a copy of s in which all (or the first n, if given) occurrences of the
* pattern have been replaced by a replacement string specified by repl, which
* may be a string, a table, or a function. gsub also returns, as its second value,
* the total number of matches that occurred.
*
* If repl is a string, then its value is used for replacement.
* The character % works as an escape character: any sequence in repl of the form %n,
* with n between 1 and 9, stands for the value of the n-th captured substring (see below).
* The sequence %0 stands for the whole match. The sequence %% stands for a single %.
*
* If repl is a table, then the table is queried for every match, using the first capture
* as the key; if the pattern specifies no captures, then the whole match is used as the key.
* If repl is a string, then its value is used for replacement.
* The character % works as an escape character: any sequence in repl of the form %n,
* with n between 1 and 9, stands for the value of the n-th captured substring (see below).
* The sequence %0 stands for the whole match. The sequence %% stands for a single %.
*
* If repl is a function, then this function is called every time a match occurs,
* with all captured substrings passed as arguments, in order; if the pattern specifies
* no captures, then the whole match is passed as a sole argument.
* If repl is a table, then the table is queried for every match, using the first capture
* as the key; if the pattern specifies no captures, then the whole match is used as the key.
*
* If the value returned by the table query or by the function call is a string or a number,
* then it is used as the replacement string; otherwise, if it is false or nil,
* then there is no replacement (that is, the original match is kept in the string).
* If repl is a function, then this function is called every time a match occurs,
* with all captured substrings passed as arguments, in order; if the pattern specifies
* no captures, then the whole match is passed as a sole argument.
*
* If the value returned by the table query or by the function call is a string or a number,
* then it is used as the replacement string; otherwise, if it is false or nil,
* then there is no replacement (that is, the original match is kept in the string).
*
* Here are some examples:
* x = string.gsub("hello world", "(%w+)", "%1 %1")
@@ -619,11 +628,11 @@ public class StringLib extends TwoArgFunction {
}
}
/**
/**
* string.len (s)
*
* Receives a string and returns its length. The empty string "" has length 0.
* Embedded zeros are counted, so "a\000bc\000" has length 5.
* Receives a string and returns its length. The empty string "" has length 0.
* Embedded zeros are counted, so "a\000bc\000" has length 5.
*/
static final class len extends OneArgFunction {
public LuaValue call(LuaValue arg) {
@@ -631,11 +640,11 @@ public class StringLib extends TwoArgFunction {
}
}
/**
/**
* string.lower (s)
*
* Receives a string and returns a copy of this string with all uppercase letters
* changed to lowercase. All other characters are left unchanged.
* Receives a string and returns a copy of this string with all uppercase letters
* changed to lowercase. All other characters are left unchanged.
* The definition of what an uppercase letter is depends on the current locale.
*/
static final class lower extends OneArgFunction {
@@ -662,7 +671,7 @@ public class StringLib extends TwoArgFunction {
/**
* string.rep (s, n)
*
* Returns a string that is the concatenation of n copies of the string s.
* Returns a string that is the concatenation of n copies of the string s.
*/
static final class rep extends VarArgFunction {
public Varargs invoke(Varargs args) {
@@ -677,10 +686,10 @@ public class StringLib extends TwoArgFunction {
}
}
/**
/**
* string.reverse (s)
*
* Returns a string that is the string s reversed.
* Returns a string that is the string s reversed.
*/
static final class reverse extends OneArgFunction {
public LuaValue call(LuaValue arg) {
@@ -693,15 +702,15 @@ public class StringLib extends TwoArgFunction {
}
}
/**
/**
* string.sub (s, i [, j])
*
* Returns the substring of s that starts at i and continues until j;
* i and j may be negative. If j is absent, then it is assumed to be equal to -1
* (which is the same as the string length). In particular, the call
* string.sub(s,1,j)
* returns a prefix of s with length j, and
* string.sub(s, -i)
* Returns the substring of s that starts at i and continues until j;
* i and j may be negative. If j is absent, then it is assumed to be equal to -1
* (which is the same as the string length). In particular, the call
* string.sub(s,1,j)
* returns a prefix of s with length j, and
* string.sub(s, -i)
* returns a suffix of s with length i.
*/
static final class sub extends VarArgFunction {
@@ -725,12 +734,12 @@ public class StringLib extends TwoArgFunction {
}
}
/**
/**
* string.upper (s)
*
* Receives a string and returns a copy of this string with all lowercase letters
* changed to uppercase. All other characters are left unchanged.
* The definition of what a lowercase letter is depends on the current locale.
* Receives a string and returns a copy of this string with all lowercase letters
* changed to uppercase. All other characters are left unchanged.
* The definition of what a lowercase letter is depends on the current locale.
*/
static final class upper extends OneArgFunction {
public LuaValue call(LuaValue arg) {
@@ -764,7 +773,7 @@ public class StringLib extends TwoArgFunction {
boolean anchor = false;
int poff = 0;
if ( pat.luaByte( 0 ) == '^' ) {
if ( pat.length() > 0 && pat.luaByte( 0 ) == '^' ) {
anchor = true;
poff = 1;
}
@@ -785,7 +794,7 @@ public class StringLib extends TwoArgFunction {
return NIL;
}
private static int posrelat( int pos, int len ) {
static int posrelat( int pos, int len ) {
return ( pos >= 0 ) ? pos : len + pos + 1;
}
@@ -807,7 +816,7 @@ public class StringLib extends TwoArgFunction {
private static final byte MASK_CONTROL = 0x40;
private static final byte MASK_HEXDIGIT = (byte)0x80;
private static final byte[] CHAR_TABLE;
static final byte[] CHAR_TABLE;
static {
CHAR_TABLE = new byte[256];
@@ -866,8 +875,14 @@ public class StringLib extends TwoArgFunction {
lbuf.append( (byte) b );
} else {
++i; // skip ESC
b = (byte) news.luaByte( i );
b = (byte)(i < l ? news.luaByte( i ) : 0);
if ( !Character.isDigit( (char) b ) ) {
if (b != L_ESC) error( "invalid use of '" + (char)L_ESC +
"' in replacement string: after '" + (char)L_ESC +
"' must be '0'-'9' or '" + (char)L_ESC +
"', but found " + (i < l ? "symbol '" + (char)b + "' with code " + b +
" at pos " + (i + 1) :
"end of string"));
lbuf.append( b );
} else if ( b == '0' ) {
lbuf.append( s.substring( soff, e ) );
@@ -961,19 +976,19 @@ public class StringLib extends TwoArgFunction {
switch ( p.luaByte( poffset++ ) ) {
case L_ESC:
if ( poffset == p.length() ) {
error( "malformed pattern (ends with %)" );
error( "malformed pattern (ends with '%')" );
}
return poffset + 1;
case '[':
if ( p.luaByte( poffset ) == '^' ) poffset++;
if ( poffset != p.length() && p.luaByte( poffset ) == '^' ) poffset++;
do {
if ( poffset == p.length() ) {
error( "malformed pattern (missing ])" );
error( "malformed pattern (missing ']')" );
}
if ( p.luaByte( poffset++ ) == L_ESC && poffset != p.length() )
poffset++;
} while ( p.luaByte( poffset ) != ']' );
if ( p.luaByte( poffset++ ) == L_ESC && poffset < p.length() )
poffset++; /* skip escapes (e.g. '%]') */
} while ( poffset == p.length() || p.luaByte( poffset ) != ']' );
return poffset + 1;
default:
return poffset;
@@ -1038,7 +1053,7 @@ public class StringLib extends TwoArgFunction {
*/
int match( int soffset, int poffset ) {
while ( true ) {
// Check if we are at the end of the pattern -
// Check if we are at the end of the pattern -
// equivalent to the '\0' case in the C version, but our pattern
// string is not NUL-terminated.
if ( poffset == p.length() )
@@ -1062,13 +1077,14 @@ public class StringLib extends TwoArgFunction {
continue;
case 'f': {
poffset += 2;
if ( p.luaByte( poffset ) != '[' ) {
error("Missing [ after %f in pattern");
if ( poffset == p.length() || p.luaByte( poffset ) != '[' ) {
error("Missing '[' after '%f' in pattern");
}
int ep = classend( poffset );
int previous = ( soffset == 0 ) ? -1 : s.luaByte( soffset - 1 );
int previous = ( soffset == 0 ) ? '\0' : s.luaByte( soffset - 1 );
int next = ( soffset == s.length() ) ? '\0' : s.luaByte( soffset );
if ( matchbracketclass( previous, poffset, ep - 1 ) ||
matchbracketclass( s.luaByte( soffset ), poffset, ep - 1 ) )
!matchbracketclass( next, poffset, ep - 1 ) )
return -1;
poffset = ep;
continue;

View File

@@ -25,19 +25,19 @@ import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
/**
* Subclass of {@link LibFunction} which implements the lua standard {@code table}
* library.
/**
* Subclass of {@link LibFunction} which implements the lua standard {@code table}
* library.
*
* <p>
* Typically, this library is included as part of a call to either
* Typically, this library is included as part of a call to either
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
* <pre> {@code
* Globals globals = JsePlatform.standardGlobals();
* System.out.println( globals.get("table").get("length").call( LuaValue.tableOf() ) );
* } </pre>
* <p>
* To instantiate and use it directly,
* To instantiate and use it directly,
* link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as:
* <pre> {@code
* Globals globals = new Globals();
@@ -70,7 +70,7 @@ public class TableLib extends TwoArgFunction {
table.set("sort", new sort());
table.set("unpack", new unpack());
env.set("table", table);
env.get("package").get("loaded").set("table", table);
if (!env.get("package").isnil()) env.get("package").get("loaded").set("table", table);
return NIL;
}

View File

@@ -101,7 +101,7 @@ abstract public class Visitor {
visitExps(args.exps);
}
public void visit(TableField field) {
if ( field.name != null );
if ( field.name != null )
visit( field.name );
if ( field.index != null )
field.index.accept(this);

View File

@@ -21,6 +21,7 @@
******************************************************************************/
package org.luaj.vm2.lib.jse;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -133,7 +134,7 @@ public class CoerceJavaToLua {
}
static final Map COERCIONS = new HashMap();
static final Map COERCIONS = Collections.synchronizedMap(new HashMap());
static {
Coercion boolCoercion = new BoolCoercion() ;

View File

@@ -21,6 +21,7 @@
******************************************************************************/
package org.luaj.vm2.lib.jse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@@ -106,9 +107,10 @@ public class JseBaseLib extends org.luaj.vm2.lib.BaseLib {
if ( ! f.exists() )
return super.findResource(filename);
try {
return new FileInputStream(f);
return new BufferedInputStream(new FileInputStream(f));
} catch ( IOException ioe ) {
return null;
}
}
}

View File

@@ -24,6 +24,7 @@ package org.luaj.vm2.lib.jse;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.LibFunction;
import org.luaj.vm2.lib.TwoArgFunction;
/**
* Subclass of {@link LibFunction} which implements the lua standard {@code math}
@@ -76,8 +77,9 @@ public class JseMathLib extends org.luaj.vm2.lib.MathLib {
LuaValue math = env.get("math");
math.set("acos", new acos());
math.set("asin", new asin());
math.set("atan", new atan());
math.set("atan2", new atan2());
LuaValue atan = new atan2();
math.set("atan", atan);
math.set("atan2", atan);
math.set("cosh", new cosh());
math.set("exp", new exp());
math.set("log", new log());
@@ -89,11 +91,21 @@ public class JseMathLib extends org.luaj.vm2.lib.MathLib {
static final class acos extends UnaryOp { protected double call(double d) { return Math.acos(d); } }
static final class asin extends UnaryOp { protected double call(double d) { return Math.asin(d); } }
static final class atan extends UnaryOp { protected double call(double d) { return Math.atan(d); } }
static final class atan2 extends BinaryOp { protected double call(double y, double x) { return Math.atan2(y, x); } }
static final class atan2 extends TwoArgFunction {
public LuaValue call(LuaValue x, LuaValue y) {
return valueOf(Math.atan2(x.checkdouble(), y.optdouble(1)));
}
}
static final class cosh extends UnaryOp { protected double call(double d) { return Math.cosh(d); } }
static final class exp extends UnaryOp { protected double call(double d) { return Math.exp(d); } }
static final class log extends UnaryOp { protected double call(double d) { return Math.log(d); } }
static final class log extends TwoArgFunction {
public LuaValue call(LuaValue x, LuaValue base) {
double nat = Math.log(x.checkdouble());
double b = base.optdouble(Math.E);
if (b != Math.E) nat /= Math.log(b);
return valueOf(nat);
}
}
static final class pow extends BinaryOp { protected double call(double x, double y) { return Math.pow(x, y); } }
static final class sinh extends UnaryOp { protected double call(double d) { return Math.sinh(d); } }
static final class tanh extends UnaryOp { protected double call(double d) { return Math.tanh(d); } }
@@ -105,3 +117,4 @@ public class JseMathLib extends org.luaj.vm2.lib.MathLib {
}

View File

@@ -74,13 +74,13 @@ import org.luaj.vm2.lib.OsLib;
public class JseOsLib extends org.luaj.vm2.lib.OsLib {
/** return code indicating the execute() threw an I/O exception */
public static int EXEC_IOEXCEPTION = 1;
public static final int EXEC_IOEXCEPTION = 1;
/** return code indicating the execute() was interrupted */
public static int EXEC_INTERRUPTED = -2;
public static final int EXEC_INTERRUPTED = -2;
/** return code indicating the execute() threw an unknown exception */
public static int EXEC_ERROR = -3;
public static final int EXEC_ERROR = -3;
/** public constructor */
public JseOsLib() {
@@ -120,7 +120,7 @@ public class JseOsLib extends org.luaj.vm2.lib.OsLib {
if ( ! f.exists() )
throw new IOException("No such file or directory");
if ( ! f.renameTo(new File(newname)) )
throw new IOException("Failed to delete");
throw new IOException("Failed to rename");
}
protected String tmpname() {

View File

@@ -23,8 +23,8 @@ package org.luaj.vm2.lib.jse;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LoadState;
import org.luaj.vm2.LuaThread;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.lib.Bit32Lib;
import org.luaj.vm2.lib.CoroutineLib;
@@ -34,10 +34,10 @@ import org.luaj.vm2.lib.ResourceFinder;
import org.luaj.vm2.lib.StringLib;
import org.luaj.vm2.lib.TableLib;
/** The {@link org.luaj.vm2.lib.jse.JsePlatform} class is a convenience class to standardize
* how globals tables are initialized for the JSE platform.
/** The {@link org.luaj.vm2.lib.jse.JsePlatform} class is a convenience class to standardize
* how globals tables are initialized for the JSE platform.
* <p>
* It is used to allocate either a set of standard globals using
* It is used to allocate either a set of standard globals using
* {@link #standardGlobals()} or debug globals using {@link #debugGlobals()}
* <p>
* A simple example of initializing globals and using them from Java is:
@@ -51,7 +51,7 @@ import org.luaj.vm2.lib.TableLib;
* globals.load( new FileInputStream("main.lua"), "main.lua" ).call();
* } </pre>
* <p>
* although {@code require} could also be used:
* although {@code require} could also be used:
* <pre> {@code
* globals.get("require").call(LuaValue.valueOf("main"));
* } </pre>
@@ -72,8 +72,8 @@ import org.luaj.vm2.lib.TableLib;
* <li>{@link org.luaj.vm2.lib.jse.JseOsLib}</li>
* <li>{@link org.luaj.vm2.lib.jse.LuajavaLib}</li>
* </ul>
* In addition, the {@link LuaC} compiler is installed so lua files may be loaded in their source form.
* <p>
* In addition, the {@link LuaC} compiler is installed so lua files may be loaded in their source form.
* <p>
* The debug globals are simply the standard globals plus the {@code debug} library {@link DebugLib}.
* <p>
* The class ensures that initialization is done in the correct order.
@@ -97,7 +97,7 @@ public class JsePlatform {
globals.load(new PackageLib());
globals.load(new Bit32Lib());
globals.load(new TableLib());
globals.load(new StringLib());
globals.load(new JseStringLib());
globals.load(new CoroutineLib());
globals.load(new JseMathLib());
globals.load(new JseIoLib());
@@ -105,7 +105,7 @@ public class JsePlatform {
globals.load(new LuajavaLib());
LoadState.install(globals);
LuaC.install(globals);
return globals;
return globals;
}
/** Create standard globals including the {@link DebugLib} library.
@@ -123,11 +123,12 @@ public class JsePlatform {
}
/** Simple wrapper for invoking a lua function with command line arguments.
* The supplied function is first given a new Globals object,
/** Simple wrapper for invoking a lua function with command line arguments.
* The supplied function is first given a new Globals object as its environment
* then the program is run with arguments.
* @return {@link Varargs} containing any values returned by mainChunk.
*/
public static void luaMain(LuaValue mainChunk, String[] args) {
public static Varargs luaMain(LuaValue mainChunk, String[] args) {
Globals g = standardGlobals();
int n = args.length;
LuaValue[] vargs = new LuaValue[args.length];
@@ -137,6 +138,6 @@ public class JsePlatform {
arg.set("n", n);
g.set("arg", arg);
mainChunk.initupvalue1(g);
mainChunk.invoke(LuaValue.varargsOf(vargs));
return mainChunk.invoke(LuaValue.varargsOf(vargs));
}
}

View File

@@ -37,38 +37,38 @@ import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.lib.LibFunction;
import org.luaj.vm2.lib.VarArgFunction;
/**
* Subclass of {@link LibFunction} which implements the features of the luajava package.
* <p>
* Luajava is an approach to mixing lua and java using simple functions that bind
* java classes and methods to lua dynamically. The API is documented on the
/**
* Subclass of {@link LibFunction} which implements the features of the luajava package.
* <p>
* Luajava is an approach to mixing lua and java using simple functions that bind
* java classes and methods to lua dynamically. The API is documented on the
* <a href="http://www.keplerproject.org/luajava/">luajava</a> documentation pages.
*
* <p>
* Typically, this library is included as part of a call to
* Typically, this library is included as part of a call to
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
* <pre> {@code
* Globals globals = JsePlatform.standardGlobals();
* System.out.println( globals.get("luajava").get("bindClass").call( LuaValue.valueOf("java.lang.System") ).invokeMethod("currentTimeMillis") );
* } </pre>
* <p>
* To instantiate and use it directly,
* To instantiate and use it directly,
* link it into your globals table via {@link Globals#load} using code such as:
* <pre> {@code
* Globals globals = new Globals();
* globals.load(new JseBaseLib());
* globals.load(new PackageLib());
* globals.load(new LuajavaLib());
* globals.load(
* globals.load(
* "sys = luajava.bindClass('java.lang.System')\n"+
* "print ( sys:currentTimeMillis() )\n", "main.lua" ).call();
* "print ( sys:currentTimeMillis() )\n", "main.lua" ).call();
* } </pre>
* <p>
*
* The {@code luajava} library is available
* The {@code luajava} library is available
* on all JSE platforms via the call to {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
* and the luajava api's are simply invoked from lua.
* Because it makes extensive use of Java's reflection API, it is not available
* and the luajava api's are simply invoked from lua.
* Because it makes extensive use of Java's reflection API, it is not available
* on JME, but can be used in Android applications.
* <p>
* This has been implemented to match as closely as possible the behavior in the corresponding library in C.
@@ -91,10 +91,10 @@ public class LuajavaLib extends VarArgFunction {
static final int LOADLIB = 5;
static final String[] NAMES = {
"bindClass",
"newInstance",
"new",
"createProxy",
"bindClass",
"newInstance",
"new",
"createProxy",
"loadLib",
};
@@ -112,7 +112,7 @@ public class LuajavaLib extends VarArgFunction {
LuaTable t = new LuaTable();
bind( t, this.getClass(), NAMES, BINDCLASS );
env.set("luajava", t);
env.get("package").get("loaded").set("luajava", t);
if (!env.get("package").isnil()) env.get("package").get("loaded").set("luajava", t);
return t;
}
case BINDCLASS: {
@@ -122,13 +122,13 @@ public class LuajavaLib extends VarArgFunction {
case NEWINSTANCE:
case NEW: {
// get constructor
final LuaValue c = args.checkvalue(1);
final LuaValue c = args.checkvalue(1);
final Class clazz = (opcode==NEWINSTANCE? classForName(c.tojstring()): (Class) c.checkuserdata(Class.class));
final Varargs consargs = args.subargs(2);
return JavaClass.forClass(clazz).getConstructor().invoke(consargs);
}
case CREATEPROXY: {
case CREATEPROXY: {
final int niface = args.narg()-1;
if ( niface <= 0 )
throw new LuaError("no interfaces");
@@ -136,7 +136,7 @@ public class LuajavaLib extends VarArgFunction {
// get the interfaces
final Class[] ifaces = new Class[niface];
for ( int i=0; i<niface; i++ )
for ( int i=0; i<niface; i++ )
ifaces[i] = classForName(args.checkjstring(i+1));
// create the invocation handler
@@ -191,16 +191,16 @@ public class LuajavaLib extends VarArgFunction {
if ( func.isnil() )
return null;
boolean isvarargs = ((method.getModifiers() & METHOD_MODIFIERS_VARARGS) != 0);
int n = args!=null? args.length: 0;
int n = args!=null? args.length: 0;
LuaValue[] v;
if ( isvarargs ) {
if ( isvarargs ) {
Object o = args[--n];
int m = Array.getLength( o );
v = new LuaValue[n+m];
for ( int i=0; i<n; i++ )
v[i] = CoerceJavaToLua.coerce(args[i]);
for ( int i=0; i<m; i++ )
v[i+n] = CoerceJavaToLua.coerce(Array.get(o,i));
v[i+n] = CoerceJavaToLua.coerce(Array.get(o,i));
} else {
v = new LuaValue[n];
for ( int i=0; i<n; i++ )

View File

@@ -32,6 +32,7 @@ import org.luaj.vm2.compiler.DumpLoadEndianIntTest;
import org.luaj.vm2.compiler.LuaParserTests;
import org.luaj.vm2.compiler.RegressionTests;
import org.luaj.vm2.compiler.SimpleTests;
import org.luaj.vm2.lib.jse.JsePlatformTest;
import org.luaj.vm2.lib.jse.LuaJavaCoercionTest;
import org.luaj.vm2.lib.jse.LuajavaAccessibleMembersTest;
import org.luaj.vm2.lib.jse.LuajavaClassMembersTest;
@@ -85,6 +86,7 @@ public class AllTests {
// library tests
TestSuite lib = new TestSuite("Library Tests");
lib.addTestSuite(JsePlatformTest.class);
lib.addTestSuite(LuajavaAccessibleMembersTest.class);
lib.addTestSuite(LuajavaClassMembersTest.class);
lib.addTestSuite(LuaJavaCoercionTest.class);

View File

@@ -0,0 +1,21 @@
package org.luaj.vm2.lib.jse;
import junit.framework.TestCase;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
public class JsePlatformTest extends TestCase {
public void testLuaMainPassesArguments() {
Globals globals = JsePlatform.standardGlobals();
LuaValue chunk = globals.load("return #arg, arg.n, arg[2], arg[1]");
Varargs results = JsePlatform.luaMain(chunk, new String[] { "aaa", "bbb" });
assertEquals(results.narg(), 4);
assertEquals(results.arg(1), LuaValue.valueOf(2));
assertEquals(results.arg(2), LuaValue.valueOf(2));
assertEquals(results.arg(3), LuaValue.valueOf("bbb"));
assertEquals(results.arg(4), LuaValue.valueOf("aaa"));
}
}

View File

@@ -1 +1 @@
version: 3.0.1
version: 3.0.2