From 696f630b83f07afde34b02c37ca0454391bb483e Mon Sep 17 00:00:00 2001 From: leon Date: Wed, 17 Aug 2016 11:21:59 +0800 Subject: [PATCH 1/2] change to android studio project --- .classpath | 8 - .gitignore | 7 + .project | 33 - AndroidManifest.xml | 18 - app/.gitignore | 1 + app/build.gradle | 19 + proguard.cfg => app/proguard.cfg | 0 app/src/main/AndroidManifest.xml | 26 + {assets => app/src/main/assets}/greet.lua | 0 {assets => app/src/main/assets}/import.lua | 268 +- .../java}/org/keplerproject/luajava/CPtr.java | 142 +- .../org/keplerproject/luajava/Console.java | 198 +- .../keplerproject/luajava/JavaFunction.java | 172 +- .../keplerproject/luajava/LuaException.java | 106 +- .../luajava/LuaInvocationHandler.java | 168 +- .../org/keplerproject/luajava/LuaJavaAPI.java | 1188 +-- .../org/keplerproject/luajava/LuaObject.java | 1086 +-- .../org/keplerproject/luajava/LuaState.java | 2368 +++--- .../luajava/LuaStateFactory.java | 244 +- .../main/java}/sk/kottman/androlua/Main.java | 0 {jni => app/src/main/jni}/Android.mk | 0 {jni => app/src/main/jni}/lua/Android.mk | 0 {jni => app/src/main/jni}/lua/lapi.c | 0 {jni => app/src/main/jni}/lua/lapi.h | 0 {jni => app/src/main/jni}/lua/lauxlib.c | 0 {jni => app/src/main/jni}/lua/lauxlib.h | 0 {jni => app/src/main/jni}/lua/lbaselib.c | 0 {jni => app/src/main/jni}/lua/lcode.c | 0 {jni => app/src/main/jni}/lua/lcode.h | 0 {jni => app/src/main/jni}/lua/ldblib.c | 0 {jni => app/src/main/jni}/lua/ldebug.c | 0 {jni => app/src/main/jni}/lua/ldebug.h | 0 {jni => app/src/main/jni}/lua/ldo.c | 0 {jni => app/src/main/jni}/lua/ldo.h | 0 {jni => app/src/main/jni}/lua/ldump.c | 0 {jni => app/src/main/jni}/lua/lfunc.c | 0 {jni => app/src/main/jni}/lua/lfunc.h | 0 {jni => app/src/main/jni}/lua/lgc.c | 0 {jni => app/src/main/jni}/lua/lgc.h | 0 {jni => app/src/main/jni}/lua/linit.c | 0 {jni => app/src/main/jni}/lua/liolib.c | 0 {jni => app/src/main/jni}/lua/llex.c | 0 {jni => app/src/main/jni}/lua/llex.h | 0 {jni => app/src/main/jni}/lua/llimits.h | 0 {jni => app/src/main/jni}/lua/lmathlib.c | 0 {jni => app/src/main/jni}/lua/lmem.c | 0 {jni => app/src/main/jni}/lua/lmem.h | 0 {jni => app/src/main/jni}/lua/loadlib.c | 0 {jni => app/src/main/jni}/lua/lobject.c | 0 {jni => app/src/main/jni}/lua/lobject.h | 0 {jni => app/src/main/jni}/lua/lopcodes.c | 0 {jni => app/src/main/jni}/lua/lopcodes.h | 0 {jni => app/src/main/jni}/lua/loslib.c | 0 {jni => app/src/main/jni}/lua/lparser.c | 0 {jni => app/src/main/jni}/lua/lparser.h | 0 {jni => app/src/main/jni}/lua/lstate.c | 0 {jni => app/src/main/jni}/lua/lstate.h | 0 {jni => app/src/main/jni}/lua/lstring.c | 0 {jni => app/src/main/jni}/lua/lstring.h | 0 {jni => app/src/main/jni}/lua/lstrlib.c | 0 {jni => app/src/main/jni}/lua/ltable.c | 0 {jni => app/src/main/jni}/lua/ltable.h | 0 {jni => app/src/main/jni}/lua/ltablib.c | 0 {jni => app/src/main/jni}/lua/ltm.c | 0 {jni => app/src/main/jni}/lua/ltm.h | 0 {jni => app/src/main/jni}/lua/lua.h | 0 {jni => app/src/main/jni}/lua/luaconf.h | 0 {jni => app/src/main/jni}/lua/lualib.h | 0 {jni => app/src/main/jni}/lua/lundump.c | 0 {jni => app/src/main/jni}/lua/lundump.h | 0 {jni => app/src/main/jni}/lua/lvm.c | 0 {jni => app/src/main/jni}/lua/lvm.h | 0 {jni => app/src/main/jni}/lua/lzio.c | 0 {jni => app/src/main/jni}/lua/lzio.h | 0 {jni => app/src/main/jni}/luajava/Android.mk | 0 {jni => app/src/main/jni}/luajava/luajava.c | 6810 ++++++++--------- .../src/main/res}/drawable-hdpi/icon.png | Bin .../src/main/res}/drawable-ldpi/icon.png | Bin .../src/main/res}/drawable-mdpi/icon.png | Bin {res => app/src/main/res}/layout/main.xml | 0 {res => app/src/main/res}/values/strings.xml | 0 build.gradle | 15 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 53636 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 160 + gradlew.bat | 90 + libs/armeabi/libluajava.so | Bin 124136 -> 0 bytes project.properties | 11 - settings.gradle | 1 + src/org/keplerproject/luajava/package.html | 58 - 90 files changed, 6700 insertions(+), 6503 deletions(-) delete mode 100644 .classpath create mode 100644 .gitignore delete mode 100644 .project delete mode 100644 AndroidManifest.xml create mode 100644 app/.gitignore create mode 100644 app/build.gradle rename proguard.cfg => app/proguard.cfg (100%) create mode 100644 app/src/main/AndroidManifest.xml rename {assets => app/src/main/assets}/greet.lua (100%) rename {assets => app/src/main/assets}/import.lua (95%) rename {src => app/src/main/java}/org/keplerproject/luajava/CPtr.java (97%) mode change 100755 => 100644 rename {src => app/src/main/java}/org/keplerproject/luajava/Console.java (96%) mode change 100755 => 100644 rename {src => app/src/main/java}/org/keplerproject/luajava/JavaFunction.java (97%) mode change 100755 => 100644 rename {src => app/src/main/java}/org/keplerproject/luajava/LuaException.java (96%) mode change 100755 => 100644 rename {src => app/src/main/java}/org/keplerproject/luajava/LuaInvocationHandler.java (96%) mode change 100755 => 100644 rename {src => app/src/main/java}/org/keplerproject/luajava/LuaJavaAPI.java (95%) mode change 100755 => 100644 rename {src => app/src/main/java}/org/keplerproject/luajava/LuaObject.java (95%) mode change 100755 => 100644 rename {src => app/src/main/java}/org/keplerproject/luajava/LuaState.java (96%) mode change 100755 => 100644 rename {src => app/src/main/java}/org/keplerproject/luajava/LuaStateFactory.java (96%) mode change 100755 => 100644 rename {src => app/src/main/java}/sk/kottman/androlua/Main.java (100%) rename {jni => app/src/main/jni}/Android.mk (100%) rename {jni => app/src/main/jni}/lua/Android.mk (100%) rename {jni => app/src/main/jni}/lua/lapi.c (100%) rename {jni => app/src/main/jni}/lua/lapi.h (100%) rename {jni => app/src/main/jni}/lua/lauxlib.c (100%) rename {jni => app/src/main/jni}/lua/lauxlib.h (100%) rename {jni => app/src/main/jni}/lua/lbaselib.c (100%) rename {jni => app/src/main/jni}/lua/lcode.c (100%) rename {jni => app/src/main/jni}/lua/lcode.h (100%) rename {jni => app/src/main/jni}/lua/ldblib.c (100%) rename {jni => app/src/main/jni}/lua/ldebug.c (100%) rename {jni => app/src/main/jni}/lua/ldebug.h (100%) rename {jni => app/src/main/jni}/lua/ldo.c (100%) rename {jni => app/src/main/jni}/lua/ldo.h (100%) rename {jni => app/src/main/jni}/lua/ldump.c (100%) rename {jni => app/src/main/jni}/lua/lfunc.c (100%) rename {jni => app/src/main/jni}/lua/lfunc.h (100%) rename {jni => app/src/main/jni}/lua/lgc.c (100%) rename {jni => app/src/main/jni}/lua/lgc.h (100%) rename {jni => app/src/main/jni}/lua/linit.c (100%) rename {jni => app/src/main/jni}/lua/liolib.c (100%) rename {jni => app/src/main/jni}/lua/llex.c (100%) rename {jni => app/src/main/jni}/lua/llex.h (100%) rename {jni => app/src/main/jni}/lua/llimits.h (100%) rename {jni => app/src/main/jni}/lua/lmathlib.c (100%) rename {jni => app/src/main/jni}/lua/lmem.c (100%) rename {jni => app/src/main/jni}/lua/lmem.h (100%) rename {jni => app/src/main/jni}/lua/loadlib.c (100%) rename {jni => app/src/main/jni}/lua/lobject.c (100%) rename {jni => app/src/main/jni}/lua/lobject.h (100%) rename {jni => app/src/main/jni}/lua/lopcodes.c (100%) rename {jni => app/src/main/jni}/lua/lopcodes.h (100%) rename {jni => app/src/main/jni}/lua/loslib.c (100%) rename {jni => app/src/main/jni}/lua/lparser.c (100%) rename {jni => app/src/main/jni}/lua/lparser.h (100%) rename {jni => app/src/main/jni}/lua/lstate.c (100%) rename {jni => app/src/main/jni}/lua/lstate.h (100%) rename {jni => app/src/main/jni}/lua/lstring.c (100%) rename {jni => app/src/main/jni}/lua/lstring.h (100%) rename {jni => app/src/main/jni}/lua/lstrlib.c (100%) rename {jni => app/src/main/jni}/lua/ltable.c (100%) rename {jni => app/src/main/jni}/lua/ltable.h (100%) rename {jni => app/src/main/jni}/lua/ltablib.c (100%) rename {jni => app/src/main/jni}/lua/ltm.c (100%) rename {jni => app/src/main/jni}/lua/ltm.h (100%) rename {jni => app/src/main/jni}/lua/lua.h (100%) rename {jni => app/src/main/jni}/lua/luaconf.h (100%) rename {jni => app/src/main/jni}/lua/lualib.h (100%) rename {jni => app/src/main/jni}/lua/lundump.c (100%) rename {jni => app/src/main/jni}/lua/lundump.h (100%) rename {jni => app/src/main/jni}/lua/lvm.c (100%) rename {jni => app/src/main/jni}/lua/lvm.h (100%) rename {jni => app/src/main/jni}/lua/lzio.c (100%) rename {jni => app/src/main/jni}/lua/lzio.h (100%) rename {jni => app/src/main/jni}/luajava/Android.mk (100%) rename {jni => app/src/main/jni}/luajava/luajava.c (96%) mode change 100755 => 100644 rename {res => app/src/main/res}/drawable-hdpi/icon.png (100%) rename {res => app/src/main/res}/drawable-ldpi/icon.png (100%) rename {res => app/src/main/res}/drawable-mdpi/icon.png (100%) rename {res => app/src/main/res}/layout/main.xml (100%) rename {res => app/src/main/res}/values/strings.xml (100%) create mode 100644 build.gradle create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat delete mode 100755 libs/armeabi/libluajava.so delete mode 100644 project.properties create mode 100644 settings.gradle delete mode 100755 src/org/keplerproject/luajava/package.html diff --git a/.classpath b/.classpath deleted file mode 100644 index a4763d1..0000000 --- a/.classpath +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5f94008 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*.iml +.gradle +/local.properties +/.idea +.DS_Store +/build +/captures diff --git a/.project b/.project deleted file mode 100644 index c481973..0000000 --- a/.project +++ /dev/null @@ -1,33 +0,0 @@ - - - AndroLua - - - - - - com.android.ide.eclipse.adt.ResourceManagerBuilder - - - - - com.android.ide.eclipse.adt.PreCompilerBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - com.android.ide.eclipse.adt.ApkBuilder - - - - - - com.android.ide.eclipse.adt.AndroidNature - org.eclipse.jdt.core.javanature - - diff --git a/AndroidManifest.xml b/AndroidManifest.xml deleted file mode 100644 index b4f8849..0000000 --- a/AndroidManifest.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..016360b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,19 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 24 + buildToolsVersion "24.0.1" + + defaultConfig { + applicationId "sk.kottman.androlua" + minSdkVersion 15 + targetSdkVersion 24 + } + + buildTypes { + release { + minifyEnabled false + proguardFiles 'proguard.cfg' + } + } +} diff --git a/proguard.cfg b/app/proguard.cfg similarity index 100% rename from proguard.cfg rename to app/proguard.cfg diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..4a53aa8 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/greet.lua b/app/src/main/assets/greet.lua similarity index 100% rename from assets/greet.lua rename to app/src/main/assets/greet.lua diff --git a/assets/import.lua b/app/src/main/assets/import.lua similarity index 95% rename from assets/import.lua rename to app/src/main/assets/import.lua index 7598f6a..3dbacc4 100644 --- a/assets/import.lua +++ b/app/src/main/assets/import.lua @@ -1,134 +1,134 @@ -local packages = {} -local append = table.insert -local new = luajava.new - --- SciTE requires this, if you want to see stdout immediately... - -io.stdout:setvbuf 'no' -io.stderr:setvbuf 'no' - -local function new_tostring (o) - return o:toString() -end - -local function call (t,...) - local obj,stat - if select('#',...) == 1 and type(select(1,...))=='table' then - obj = make_array(t,select(1,...)) - else - stat,obj = pcall(new,t,...) - if not stat then - print(debug.traceback()) - os.exit(1) - end - end - getmetatable(obj).__tostring = new_tostring - return obj -end - -local function import_class (classname,packagename) - local res,class = pcall(luajava.bindClass,packagename) - if res then - _G[classname] = class - local mt = getmetatable(class) - mt.__call = call - return class - end -end - -local function massage_classname (classname) - if classname:find('_') then - classname = classname:gsub('_','$') - end - return classname -end - -local globalMT = { - __index = function(T,classname) - classname = massage_classname(classname) - for i,p in ipairs(packages) do - local class = import_class(classname,p..classname) - if class then return class end - end - error("import cannot find "..classname) - end -} -setmetatable(_G, globalMT) - -function import (package) - local i = package:find('%.%*$') - if i then -- a wildcard; put into the package list, including the final '.' - append(packages,package:sub(1,i)) - else - local classname = package:match('([%w_]+)$') - if not import_class(classname,package) then - error("cannot find "..package) - end - end -end - -append(packages,'') - -function proxy (classname,obj) - classname = massage_classname(classname) - -- if the classname contains dots it's assumed to be fully qualified - if classname:find('.',1,true) then - return luajava.createProxy(classname,obj) - end - -- otherwise, it must lie on the package path! - for i,p in ipairs(packages) do - local ok,res = pcall(luajava.createProxy,p..classname, obj) - if ok then return res end - end - error ("cannot find "..classname) -end - - -function enum(e) - --local e = o:GetEnumerator() - return function() - if e:hasMoreElements() then - return e:nextElement() - end - end -end - -function dump (t) - for k,v in pairs(t) do - print(k,v) - end -end - -function p (o) - if type(o) == 'userdata' then - local mt = getmetatable(o) - if not mt.__tostring then - return print('java:'..o:toString()) - end - end - print(type(o)..':'..tostring(o)) -end - -import 'java.lang.reflect.Array' - -function make_array (Type,list) - local len - local init = type(list)=='table' - if init then - len = #list - else - len = list - end - local arr = Array:newInstance(Type,len) - if init then - for i,v in ipairs(list) do - Array:set(arr,i-1,v) - end - end - return arr -end - - -import 'java.lang.*' -import 'java.util.*' - +local packages = {} +local append = table.insert +local new = luajava.new + +-- SciTE requires this, if you want to see stdout immediately... + +io.stdout:setvbuf 'no' +io.stderr:setvbuf 'no' + +local function new_tostring (o) + return o:toString() +end + +local function call (t,...) + local obj,stat + if select('#',...) == 1 and type(select(1,...))=='table' then + obj = make_array(t,select(1,...)) + else + stat,obj = pcall(new,t,...) + if not stat then + print(debug.traceback()) + os.exit(1) + end + end + getmetatable(obj).__tostring = new_tostring + return obj +end + +local function import_class (classname,packagename) + local res,class = pcall(luajava.bindClass,packagename) + if res then + _G[classname] = class + local mt = getmetatable(class) + mt.__call = call + return class + end +end + +local function massage_classname (classname) + if classname:find('_') then + classname = classname:gsub('_','$') + end + return classname +end + +local globalMT = { + __index = function(T,classname) + classname = massage_classname(classname) + for i,p in ipairs(packages) do + local class = import_class(classname,p..classname) + if class then return class end + end + error("import cannot find "..classname) + end +} +setmetatable(_G, globalMT) + +function import (package) + local i = package:find('%.%*$') + if i then -- a wildcard; put into the package list, including the final '.' + append(packages,package:sub(1,i)) + else + local classname = package:match('([%w_]+)$') + if not import_class(classname,package) then + error("cannot find "..package) + end + end +end + +append(packages,'') + +function proxy (classname,obj) + classname = massage_classname(classname) + -- if the classname contains dots it's assumed to be fully qualified + if classname:find('.',1,true) then + return luajava.createProxy(classname,obj) + end + -- otherwise, it must lie on the package path! + for i,p in ipairs(packages) do + local ok,res = pcall(luajava.createProxy,p..classname, obj) + if ok then return res end + end + error ("cannot find "..classname) +end + + +function enum(e) + --local e = o:GetEnumerator() + return function() + if e:hasMoreElements() then + return e:nextElement() + end + end +end + +function dump (t) + for k,v in pairs(t) do + print(k,v) + end +end + +function p (o) + if type(o) == 'userdata' then + local mt = getmetatable(o) + if not mt.__tostring then + return print('java:'..o:toString()) + end + end + print(type(o)..':'..tostring(o)) +end + +import 'java.lang.reflect.Array' + +function make_array (Type,list) + local len + local init = type(list)=='table' + if init then + len = #list + else + len = list + end + local arr = Array:newInstance(Type,len) + if init then + for i,v in ipairs(list) do + Array:set(arr,i-1,v) + end + end + return arr +end + + +import 'java.lang.*' +import 'java.util.*' + diff --git a/src/org/keplerproject/luajava/CPtr.java b/app/src/main/java/org/keplerproject/luajava/CPtr.java old mode 100755 new mode 100644 similarity index 97% rename from src/org/keplerproject/luajava/CPtr.java rename to app/src/main/java/org/keplerproject/luajava/CPtr.java index 69bdeb4..08956e9 --- a/src/org/keplerproject/luajava/CPtr.java +++ b/app/src/main/java/org/keplerproject/luajava/CPtr.java @@ -1,71 +1,71 @@ -/* - * $Id: CPtr.java,v 1.4 2006/12/22 14:06:40 thiago Exp $ - * Copyright (C) 2003-2007 Kepler Project. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -package org.keplerproject.luajava; - -/** - * An abstraction for a C pointer data type. A CPtr instance represents, on - * the Java side, a C pointer. The C pointer could be any type of C - * pointer. - */ -public class CPtr -{ - - /** - * Compares this CPtr to the specified object. - * - * @param other a CPtr - * @return true if the class of this CPtr object and the - * class of other are exactly equal, and the C - * pointers being pointed to by these objects are also - * equal. Returns false otherwise. - */ - public boolean equals(Object other) - { - if (other == null) - return false; - if (other == this) - return true; - if (CPtr.class != other.getClass()) - return false; - return peer == ((CPtr)other).peer; - } - - - /* Pointer value of the real C pointer. Use long to be 64-bit safe. */ - private long peer; - - /** - * Gets the value of the C pointer abstraction - * @return long - */ - protected long getPeer() - { - return peer; - } - - /* No-args constructor. */ - CPtr() {} - -} +/* + * $Id: CPtr.java,v 1.4 2006/12/22 14:06:40 thiago Exp $ + * Copyright (C) 2003-2007 Kepler Project. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package org.keplerproject.luajava; + +/** + * An abstraction for a C pointer data type. A CPtr instance represents, on + * the Java side, a C pointer. The C pointer could be any type of C + * pointer. + */ +public class CPtr +{ + + /** + * Compares this CPtr to the specified object. + * + * @param other a CPtr + * @return true if the class of this CPtr object and the + * class of other are exactly equal, and the C + * pointers being pointed to by these objects are also + * equal. Returns false otherwise. + */ + public boolean equals(Object other) + { + if (other == null) + return false; + if (other == this) + return true; + if (CPtr.class != other.getClass()) + return false; + return peer == ((CPtr)other).peer; + } + + + /* Pointer value of the real C pointer. Use long to be 64-bit safe. */ + private long peer; + + /** + * Gets the value of the C pointer abstraction + * @return long + */ + protected long getPeer() + { + return peer; + } + + /* No-args constructor. */ + CPtr() {} + +} diff --git a/src/org/keplerproject/luajava/Console.java b/app/src/main/java/org/keplerproject/luajava/Console.java old mode 100755 new mode 100644 similarity index 96% rename from src/org/keplerproject/luajava/Console.java rename to app/src/main/java/org/keplerproject/luajava/Console.java index f31e846..ee90ca6 --- a/src/org/keplerproject/luajava/Console.java +++ b/app/src/main/java/org/keplerproject/luajava/Console.java @@ -1,100 +1,100 @@ -/* - * $Id: Console.java,v 1.7 2006/12/22 14:06:40 thiago Exp $ - * Copyright (C) 2003-2007 Kepler Project. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -package org.keplerproject.luajava; - -import java.io.BufferedReader; -import java.io.InputStreamReader; - -/** - * Simple LuaJava console. - * This is also an example on how to use the Java side of LuaJava and how to startup - * a LuaJava application. - * - * @author Thiago Ponte - */ -public class Console -{ - - /** - * Creates a console for user interaction. - * - * @param args names of the lua files to be executed - */ - public static void main(String[] args) - { - try - { - LuaState L = LuaStateFactory.newLuaState(); - L.openLibs(); - - if (args.length > 0) - { - for (int i = 0; i < args.length; i++) - { - int res = L.LloadFile(args[i]); - if (res == 0) - { - res = L.pcall(0, 0, 0); - } - if (res != 0) - { - throw new LuaException("Error on file: " + args[i] + ". " + L.toString(-1)); - } - } - - return; - } - - System.out.println("API Lua Java - console mode."); - - BufferedReader inp = new BufferedReader(new InputStreamReader(System.in)); - - String line; - - System.out.print("> "); - while ((line = inp.readLine()) != null && !line.equals("exit")) - { - int ret = L.LloadBuffer(line.getBytes(), "from console"); - if (ret == 0) - { - ret = L.pcall(0, 0, 0); - } - if (ret != 0) - { - System.err.println("Error on line: " + line); - System.err.println(L.toString(-1)); - } - System.out.print("> "); - } - - L.close(); - } - catch (Exception e) - { - e.printStackTrace(); - } - - } +/* + * $Id: Console.java,v 1.7 2006/12/22 14:06:40 thiago Exp $ + * Copyright (C) 2003-2007 Kepler Project. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package org.keplerproject.luajava; + +import java.io.BufferedReader; +import java.io.InputStreamReader; + +/** + * Simple LuaJava console. + * This is also an example on how to use the Java side of LuaJava and how to startup + * a LuaJava application. + * + * @author Thiago Ponte + */ +public class Console +{ + + /** + * Creates a console for user interaction. + * + * @param args names of the lua files to be executed + */ + public static void main(String[] args) + { + try + { + LuaState L = LuaStateFactory.newLuaState(); + L.openLibs(); + + if (args.length > 0) + { + for (int i = 0; i < args.length; i++) + { + int res = L.LloadFile(args[i]); + if (res == 0) + { + res = L.pcall(0, 0, 0); + } + if (res != 0) + { + throw new LuaException("Error on file: " + args[i] + ". " + L.toString(-1)); + } + } + + return; + } + + System.out.println("API Lua Java - console mode."); + + BufferedReader inp = new BufferedReader(new InputStreamReader(System.in)); + + String line; + + System.out.print("> "); + while ((line = inp.readLine()) != null && !line.equals("exit")) + { + int ret = L.LloadBuffer(line.getBytes(), "from console"); + if (ret == 0) + { + ret = L.pcall(0, 0, 0); + } + if (ret != 0) + { + System.err.println("Error on line: " + line); + System.err.println(L.toString(-1)); + } + System.out.print("> "); + } + + L.close(); + } + catch (Exception e) + { + e.printStackTrace(); + } + + } } \ No newline at end of file diff --git a/src/org/keplerproject/luajava/JavaFunction.java b/app/src/main/java/org/keplerproject/luajava/JavaFunction.java old mode 100755 new mode 100644 similarity index 97% rename from src/org/keplerproject/luajava/JavaFunction.java rename to app/src/main/java/org/keplerproject/luajava/JavaFunction.java index 065dad9..edabfa1 --- a/src/org/keplerproject/luajava/JavaFunction.java +++ b/app/src/main/java/org/keplerproject/luajava/JavaFunction.java @@ -1,86 +1,86 @@ -/* - * $Id: JavaFunction.java,v 1.6 2006/12/22 14:06:40 thiago Exp $ - * Copyright (C) 2003-2007 Kepler Project. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -package org.keplerproject.luajava; - -/** - * JavaFunction is a class that can be used to implement a Lua function in Java. - * JavaFunction is an abstract class, so in order to use it you must extend this - * class and implement the execute method. This execute - * method is the method that will be called when you call the function from Lua. - * To register the JavaFunction in Lua use the method register(String name). - */ -public abstract class JavaFunction -{ - - /** - * This is the state in which this function will exist. - */ - protected LuaState L; - - /** - * This method is called from Lua. Any parameters can be taken with - * getParam. A reference to the JavaFunctionWrapper itself is - * always the first parameter received. Values passed back as results - * of the function must be pushed onto the stack. - * @return The number of values pushed onto the stack. - */ - public abstract int execute() throws LuaException; - - /** - * Constructor that receives a LuaState. - * @param L LuaState object associated with this JavaFunction object - */ - public JavaFunction(LuaState L) - { - this.L = L; - } - - /** - * Returns a parameter received from Lua. Parameters are numbered from 1. - * A reference to the JavaFunction itself is always the first parameter - * received (the same as this). - * @param idx Index of the parameter. - * @return Reference to parameter. - * @see LuaObject - */ - public LuaObject getParam(int idx) - { - return L.getLuaObject(idx); - } - - /** - * Register a JavaFunction with a given name. This method registers in a - * global variable the JavaFunction specified. - * @param name name of the function. - */ - public void register(String name) throws LuaException - { - synchronized (L) - { - L.pushJavaFunction(this); - L.setGlobal(name); - } - } -} +/* + * $Id: JavaFunction.java,v 1.6 2006/12/22 14:06:40 thiago Exp $ + * Copyright (C) 2003-2007 Kepler Project. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package org.keplerproject.luajava; + +/** + * JavaFunction is a class that can be used to implement a Lua function in Java. + * JavaFunction is an abstract class, so in order to use it you must extend this + * class and implement the execute method. This execute + * method is the method that will be called when you call the function from Lua. + * To register the JavaFunction in Lua use the method register(String name). + */ +public abstract class JavaFunction +{ + + /** + * This is the state in which this function will exist. + */ + protected LuaState L; + + /** + * This method is called from Lua. Any parameters can be taken with + * getParam. A reference to the JavaFunctionWrapper itself is + * always the first parameter received. Values passed back as results + * of the function must be pushed onto the stack. + * @return The number of values pushed onto the stack. + */ + public abstract int execute() throws LuaException; + + /** + * Constructor that receives a LuaState. + * @param L LuaState object associated with this JavaFunction object + */ + public JavaFunction(LuaState L) + { + this.L = L; + } + + /** + * Returns a parameter received from Lua. Parameters are numbered from 1. + * A reference to the JavaFunction itself is always the first parameter + * received (the same as this). + * @param idx Index of the parameter. + * @return Reference to parameter. + * @see LuaObject + */ + public LuaObject getParam(int idx) + { + return L.getLuaObject(idx); + } + + /** + * Register a JavaFunction with a given name. This method registers in a + * global variable the JavaFunction specified. + * @param name name of the function. + */ + public void register(String name) throws LuaException + { + synchronized (L) + { + L.pushJavaFunction(this); + L.setGlobal(name); + } + } +} diff --git a/src/org/keplerproject/luajava/LuaException.java b/app/src/main/java/org/keplerproject/luajava/LuaException.java old mode 100755 new mode 100644 similarity index 96% rename from src/org/keplerproject/luajava/LuaException.java rename to app/src/main/java/org/keplerproject/luajava/LuaException.java index 7f8232f..8b36920 --- a/src/org/keplerproject/luajava/LuaException.java +++ b/app/src/main/java/org/keplerproject/luajava/LuaException.java @@ -1,54 +1,54 @@ -/* - * $Id: LuaException.java,v 1.6 2006/12/22 14:06:40 thiago Exp $ - * Copyright (C) 2003-2007 Kepler Project. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -package org.keplerproject.luajava; - -/** - * LuaJava exception - * - * @author Thiago Ponte - * - */ -public class LuaException extends Exception -{ - /** - * - */ - private static final long serialVersionUID = 1L; - - public LuaException(String str) - { - super(str); - } - - /** - * Will work only on Java 1.4 or later. - * To work with Java 1.3, comment the first line and uncomment the second one. - */ - public LuaException(Exception e) - { - super((e.getCause() != null) ? e.getCause() : e); - //super(e.getMessage()); - } +/* + * $Id: LuaException.java,v 1.6 2006/12/22 14:06:40 thiago Exp $ + * Copyright (C) 2003-2007 Kepler Project. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package org.keplerproject.luajava; + +/** + * LuaJava exception + * + * @author Thiago Ponte + * + */ +public class LuaException extends Exception +{ + /** + * + */ + private static final long serialVersionUID = 1L; + + public LuaException(String str) + { + super(str); + } + + /** + * Will work only on Java 1.4 or later. + * To work with Java 1.3, comment the first line and uncomment the second one. + */ + public LuaException(Exception e) + { + super((e.getCause() != null) ? e.getCause() : e); + //super(e.getMessage()); + } } \ No newline at end of file diff --git a/src/org/keplerproject/luajava/LuaInvocationHandler.java b/app/src/main/java/org/keplerproject/luajava/LuaInvocationHandler.java old mode 100755 new mode 100644 similarity index 96% rename from src/org/keplerproject/luajava/LuaInvocationHandler.java rename to app/src/main/java/org/keplerproject/luajava/LuaInvocationHandler.java index 67362cf..1b90edb --- a/src/org/keplerproject/luajava/LuaInvocationHandler.java +++ b/app/src/main/java/org/keplerproject/luajava/LuaInvocationHandler.java @@ -1,84 +1,84 @@ -/* - * $Id: LuaInvocationHandler.java,v 1.4 2006/12/22 14:06:40 thiago Exp $ - * Copyright (C) 2003-2007 Kepler Project. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -package org.keplerproject.luajava; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; - -/** - * Class that implements the InvocationHandler interface. - * This class is used in the LuaJava's proxy system. - * When a proxy object is accessed, the method invoked is - * called from Lua - * @author Rizzato - * @author Thiago Ponte - */ -public class LuaInvocationHandler implements InvocationHandler -{ - private LuaObject obj; - - - public LuaInvocationHandler(LuaObject obj) - { - this.obj = obj; - } - - /** - * Function called when a proxy object function is invoked. - */ - public Object invoke(Object proxy, Method method, Object[] args) throws LuaException - { - synchronized(obj.L) - { - String methodName = method.getName(); - LuaObject func = obj.getField(methodName); - - if ( func.isNil() ) - { - return null; - } - - Class retType = method.getReturnType(); - Object ret; - - // Checks if returned type is void. if it is returns null. - if ( retType.equals( Void.class ) || retType.equals( void.class ) ) - { - func.call( args , 0 ); - ret = null; - } - else - { - ret = func.call(args, 1)[0]; - if( ret != null && ret instanceof Double ) - { - ret = LuaState.convertLuaNumber((Double) ret, retType); - } - } - - return ret; - } - } -} +/* + * $Id: LuaInvocationHandler.java,v 1.4 2006/12/22 14:06:40 thiago Exp $ + * Copyright (C) 2003-2007 Kepler Project. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package org.keplerproject.luajava; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +/** + * Class that implements the InvocationHandler interface. + * This class is used in the LuaJava's proxy system. + * When a proxy object is accessed, the method invoked is + * called from Lua + * @author Rizzato + * @author Thiago Ponte + */ +public class LuaInvocationHandler implements InvocationHandler +{ + private LuaObject obj; + + + public LuaInvocationHandler(LuaObject obj) + { + this.obj = obj; + } + + /** + * Function called when a proxy object function is invoked. + */ + public Object invoke(Object proxy, Method method, Object[] args) throws LuaException + { + synchronized(obj.L) + { + String methodName = method.getName(); + LuaObject func = obj.getField(methodName); + + if ( func.isNil() ) + { + return null; + } + + Class retType = method.getReturnType(); + Object ret; + + // Checks if returned type is void. if it is returns null. + if ( retType.equals( Void.class ) || retType.equals( void.class ) ) + { + func.call( args , 0 ); + ret = null; + } + else + { + ret = func.call(args, 1)[0]; + if( ret != null && ret instanceof Double ) + { + ret = LuaState.convertLuaNumber((Double) ret, retType); + } + } + + return ret; + } + } +} diff --git a/src/org/keplerproject/luajava/LuaJavaAPI.java b/app/src/main/java/org/keplerproject/luajava/LuaJavaAPI.java old mode 100755 new mode 100644 similarity index 95% rename from src/org/keplerproject/luajava/LuaJavaAPI.java rename to app/src/main/java/org/keplerproject/luajava/LuaJavaAPI.java index 8777990..a60c123 --- a/src/org/keplerproject/luajava/LuaJavaAPI.java +++ b/app/src/main/java/org/keplerproject/luajava/LuaJavaAPI.java @@ -1,595 +1,595 @@ -/* - * $Id: LuaJavaAPI.java,v 1.4 2006/12/22 14:06:40 thiago Exp $ - * Copyright (C) 2003-2007 Kepler Project. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -package org.keplerproject.luajava; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; - -/** - * Class that contains functions accessed by lua. - * - * @author Thiago Ponte - */ -public final class LuaJavaAPI -{ - - private LuaJavaAPI() - { - } - - /** - * Java implementation of the metamethod __index - * - * @param luaState int that indicates the state used - * @param obj Object to be indexed - * @param methodName the name of the method - * @return number of returned objects - */ - public static int objectIndex(int luaState, Object obj, String methodName) - throws LuaException - { - LuaState L = LuaStateFactory.getExistingState(luaState); - - synchronized (L) - { - int top = L.getTop(); - - Object[] objs = new Object[top - 1]; - - Class clazz; - - if (obj instanceof Class) - { - clazz = (Class) obj; - } - else - { - clazz = obj.getClass(); - } - - Method[] methods = clazz.getMethods(); - Method method = null; - - // gets method and arguments - for (int i = 0; i < methods.length; i++) - { - if (!methods[i].getName().equals(methodName)) - - continue; - - Class[] parameters = methods[i].getParameterTypes(); - if (parameters.length != top - 1) - continue; - - boolean okMethod = true; - - for (int j = 0; j < parameters.length; j++) - { - try - { - objs[j] = compareTypes(L, parameters[j], j + 2); - } - catch (Exception e) - { - okMethod = false; - break; - } - } - - if (okMethod) - { - method = methods[i]; - break; - } - - } - - // If method is null means there isn't one receiving the given arguments - if (method == null) - { - throw new LuaException("Invalid method call. No such method."); - } - - Object ret; - try - { - if(Modifier.isPublic(method.getModifiers())) - { - method.setAccessible(true); - } - - if (obj instanceof Class) - { - ret = method.invoke(null, objs); - } - else - { - ret = method.invoke(obj, objs); - } - } - catch (Exception e) - { - throw new LuaException(e); - } - - // Void function returns null - if (ret == null) - { - return 0; - } - - // push result - L.pushObjectValue(ret); - - return 1; - } - } - - /** - * Java function to be called when a java Class metamethod __index is called. - * This function returns 1 if there is a field with searchName and 2 if there - * is a method if the searchName - * - * @param luaState int that represents the state to be used - * @param clazz class to be indexed - * @param searchName name of the field or method to be accessed - * @return number of returned objects - * @throws LuaException - */ - public static int classIndex(int luaState, Class clazz, String searchName) - throws LuaException - { - synchronized (LuaStateFactory.getExistingState(luaState)) - { - int res; - - res = checkField(luaState, clazz, searchName); - - if (res != 0) - { - return 1; - } - - res = checkMethod(luaState, clazz, searchName); - - if (res != 0) - { - return 2; - } - - return 0; - } - } - - /** - * Pushes a new instance of a java Object of the type className - * - * @param luaState int that represents the state to be used - * @param className name of the class - * @return number of returned objects - * @throws LuaException - */ - public static int javaNewInstance(int luaState, String className) - throws LuaException - { - LuaState L = LuaStateFactory.getExistingState(luaState); - - synchronized (L) - { - Class clazz; - try - { - clazz = Class.forName(className); - } - catch (ClassNotFoundException e) - { - throw new LuaException(e); - } - Object ret = getObjInstance(L, clazz); - - L.pushJavaObject(ret); - - return 1; - } - } - - /** - * javaNew returns a new instance of a given clazz - * - * @param luaState int that represents the state to be used - * @param clazz class to be instanciated - * @return number of returned objects - * @throws LuaException - */ - public static int javaNew(int luaState, Class clazz) throws LuaException - { - LuaState L = LuaStateFactory.getExistingState(luaState); - - synchronized (L) - { - Object ret = getObjInstance(L, clazz); - - L.pushJavaObject(ret); - - return 1; - } - } - - /** - * Calls the static method methodName in class className - * that receives a LuaState as first parameter. - * @param luaState int that represents the state to be used - * @param className name of the class that has the open library method - * @param methodName method to open library - * @return number of returned objects - * @throws LuaException - */ - public static int javaLoadLib(int luaState, String className, String methodName) - throws LuaException - { - LuaState L = LuaStateFactory.getExistingState(luaState); - - synchronized (L) - { - Class clazz; - try - { - clazz = Class.forName(className); - } - catch (ClassNotFoundException e) - { - throw new LuaException(e); - } - - try - { - Method mt = clazz.getMethod(methodName, new Class[] {LuaState.class}); - Object obj = mt.invoke(null, new Object[] {L}); - - if (obj != null && obj instanceof Integer) - { - return ((Integer) obj).intValue(); - } - else - return 0; - } - catch (Exception e) - { - throw new LuaException("Error on calling method. Library could not be loaded. " + e.getMessage()); - } - } - } - - private static Object getObjInstance(LuaState L, Class clazz) - throws LuaException - { - synchronized (L) - { - int top = L.getTop(); - - Object[] objs = new Object[top - 1]; - - Constructor[] constructors = clazz.getConstructors(); - Constructor constructor = null; - - // gets method and arguments - for (int i = 0; i < constructors.length; i++) - { - Class[] parameters = constructors[i].getParameterTypes(); - if (parameters.length != top - 1) - continue; - - boolean okConstruc = true; - - for (int j = 0; j < parameters.length; j++) - { - try - { - objs[j] = compareTypes(L, parameters[j], j + 2); - } - catch (Exception e) - { - okConstruc = false; - break; - } - } - - if (okConstruc) - { - constructor = constructors[i]; - break; - } - - } - - // If method is null means there isn't one receiving the given arguments - if (constructor == null) - { - throw new LuaException("Invalid method call. No such method."); - } - - Object ret; - try - { - ret = constructor.newInstance(objs); - } - catch (Exception e) - { - throw new LuaException(e); - } - - if (ret == null) - { - throw new LuaException("Couldn't instantiate java Object"); - } - - return ret; - } - } - - /** - * Checks if there is a field on the obj with the given name - * - * @param luaState int that represents the state to be used - * @param obj object to be inspected - * @param fieldName name of the field to be inpected - * @return number of returned objects - */ - public static int checkField(int luaState, Object obj, String fieldName) - throws LuaException - { - LuaState L = LuaStateFactory.getExistingState(luaState); - - synchronized (L) - { - Field field = null; - Class objClass; - - if (obj instanceof Class) - { - objClass = (Class) obj; - } - else - { - objClass = obj.getClass(); - } - - try - { - field = objClass.getField(fieldName); - } - catch (Exception e) - { - return 0; - } - - if (field == null) - { - return 0; - } - - Object ret = null; - try - { - ret = field.get(obj); - } - catch (Exception e1) - { - return 0; - } - - if (obj == null) - { - return 0; - } - - L.pushObjectValue(ret); - - return 1; - } - } - - /** - * Checks to see if there is a method with the given name. - * - * @param luaState int that represents the state to be used - * @param obj object to be inspected - * @param methodName name of the field to be inpected - * @return number of returned objects - */ - public static int checkMethod(int luaState, Object obj, String methodName) - { - LuaState L = LuaStateFactory.getExistingState(luaState); - - synchronized (L) - { - Class clazz; - - if (obj instanceof Class) - { - clazz = (Class) obj; - } - else - { - clazz = obj.getClass(); - } - - Method[] methods = clazz.getMethods(); - - for (int i = 0; i < methods.length; i++) - { - if (methods[i].getName().equals(methodName)) - return 1; - } - - return 0; - } - } - - /** - * Function that creates an object proxy and pushes it into the stack - * - * @param luaState int that represents the state to be used - * @param implem interfaces implemented separated by comma (,) - * @return number of returned objects - * @throws LuaException - */ - public static int createProxyObject(int luaState, String implem) - throws LuaException - { - LuaState L = LuaStateFactory.getExistingState(luaState); - - synchronized (L) - { - try - { - if (!(L.isTable(2))) - throw new LuaException( - "Parameter is not a table. Can't create proxy."); - - LuaObject luaObj = L.getLuaObject(2); - - Object proxy = luaObj.createProxy(implem); - L.pushJavaObject(proxy); - } - catch (Exception e) - { - throw new LuaException(e); - } - - return 1; - } - } - - private static Object compareTypes(LuaState L, Class parameter, int idx) - throws LuaException - { - boolean okType = true; - Object obj = null; - - if (L.isBoolean(idx)) - { - if (parameter.isPrimitive()) - { - if (parameter != Boolean.TYPE) - { - okType = false; - } - } - else if (!parameter.isAssignableFrom(Boolean.class)) - { - okType = false; - } - obj = new Boolean(L.toBoolean(idx)); - } - else if (L.type(idx) == LuaState.LUA_TSTRING.intValue()) - { - if (!parameter.isAssignableFrom(String.class)) - { - okType = false; - } - else - { - obj = L.toString(idx); - } - } - else if (L.isFunction(idx)) - { - if (!parameter.isAssignableFrom(LuaObject.class)) - { - okType = false; - } - else - { - obj = L.getLuaObject(idx); - } - } - else if (L.isTable(idx)) - { - if (!parameter.isAssignableFrom(LuaObject.class)) - { - okType = false; - } - else - { - obj = L.getLuaObject(idx); - } - } - else if (L.type(idx) == LuaState.LUA_TNUMBER.intValue()) - { - Double db = new Double(L.toNumber(idx)); - - obj = LuaState.convertLuaNumber(db, parameter); - if (obj == null) - { - okType = false; - } - } - else if (L.isUserdata(idx)) - { - if (L.isObject(idx)) - { - Object userObj = L.getObjectFromUserdata(idx); - if (!parameter.isAssignableFrom(userObj.getClass())) - { - okType = false; - } - else - { - obj = userObj; - } - } - else - { - if (!parameter.isAssignableFrom(LuaObject.class)) - { - okType = false; - } - else - { - obj = L.getLuaObject(idx); - } - } - } - else if (L.isNil(idx)) - { - obj = null; - } - else - { - throw new LuaException("Invalid Parameters."); - } - - if (!okType) - { - throw new LuaException("Invalid Parameter."); - } - - return obj; - } - +/* + * $Id: LuaJavaAPI.java,v 1.4 2006/12/22 14:06:40 thiago Exp $ + * Copyright (C) 2003-2007 Kepler Project. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package org.keplerproject.luajava; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +/** + * Class that contains functions accessed by lua. + * + * @author Thiago Ponte + */ +public final class LuaJavaAPI +{ + + private LuaJavaAPI() + { + } + + /** + * Java implementation of the metamethod __index + * + * @param luaState int that indicates the state used + * @param obj Object to be indexed + * @param methodName the name of the method + * @return number of returned objects + */ + public static int objectIndex(int luaState, Object obj, String methodName) + throws LuaException + { + LuaState L = LuaStateFactory.getExistingState(luaState); + + synchronized (L) + { + int top = L.getTop(); + + Object[] objs = new Object[top - 1]; + + Class clazz; + + if (obj instanceof Class) + { + clazz = (Class) obj; + } + else + { + clazz = obj.getClass(); + } + + Method[] methods = clazz.getMethods(); + Method method = null; + + // gets method and arguments + for (int i = 0; i < methods.length; i++) + { + if (!methods[i].getName().equals(methodName)) + + continue; + + Class[] parameters = methods[i].getParameterTypes(); + if (parameters.length != top - 1) + continue; + + boolean okMethod = true; + + for (int j = 0; j < parameters.length; j++) + { + try + { + objs[j] = compareTypes(L, parameters[j], j + 2); + } + catch (Exception e) + { + okMethod = false; + break; + } + } + + if (okMethod) + { + method = methods[i]; + break; + } + + } + + // If method is null means there isn't one receiving the given arguments + if (method == null) + { + throw new LuaException("Invalid method call. No such method."); + } + + Object ret; + try + { + if(Modifier.isPublic(method.getModifiers())) + { + method.setAccessible(true); + } + + if (obj instanceof Class) + { + ret = method.invoke(null, objs); + } + else + { + ret = method.invoke(obj, objs); + } + } + catch (Exception e) + { + throw new LuaException(e); + } + + // Void function returns null + if (ret == null) + { + return 0; + } + + // push result + L.pushObjectValue(ret); + + return 1; + } + } + + /** + * Java function to be called when a java Class metamethod __index is called. + * This function returns 1 if there is a field with searchName and 2 if there + * is a method if the searchName + * + * @param luaState int that represents the state to be used + * @param clazz class to be indexed + * @param searchName name of the field or method to be accessed + * @return number of returned objects + * @throws LuaException + */ + public static int classIndex(int luaState, Class clazz, String searchName) + throws LuaException + { + synchronized (LuaStateFactory.getExistingState(luaState)) + { + int res; + + res = checkField(luaState, clazz, searchName); + + if (res != 0) + { + return 1; + } + + res = checkMethod(luaState, clazz, searchName); + + if (res != 0) + { + return 2; + } + + return 0; + } + } + + /** + * Pushes a new instance of a java Object of the type className + * + * @param luaState int that represents the state to be used + * @param className name of the class + * @return number of returned objects + * @throws LuaException + */ + public static int javaNewInstance(int luaState, String className) + throws LuaException + { + LuaState L = LuaStateFactory.getExistingState(luaState); + + synchronized (L) + { + Class clazz; + try + { + clazz = Class.forName(className); + } + catch (ClassNotFoundException e) + { + throw new LuaException(e); + } + Object ret = getObjInstance(L, clazz); + + L.pushJavaObject(ret); + + return 1; + } + } + + /** + * javaNew returns a new instance of a given clazz + * + * @param luaState int that represents the state to be used + * @param clazz class to be instanciated + * @return number of returned objects + * @throws LuaException + */ + public static int javaNew(int luaState, Class clazz) throws LuaException + { + LuaState L = LuaStateFactory.getExistingState(luaState); + + synchronized (L) + { + Object ret = getObjInstance(L, clazz); + + L.pushJavaObject(ret); + + return 1; + } + } + + /** + * Calls the static method methodName in class className + * that receives a LuaState as first parameter. + * @param luaState int that represents the state to be used + * @param className name of the class that has the open library method + * @param methodName method to open library + * @return number of returned objects + * @throws LuaException + */ + public static int javaLoadLib(int luaState, String className, String methodName) + throws LuaException + { + LuaState L = LuaStateFactory.getExistingState(luaState); + + synchronized (L) + { + Class clazz; + try + { + clazz = Class.forName(className); + } + catch (ClassNotFoundException e) + { + throw new LuaException(e); + } + + try + { + Method mt = clazz.getMethod(methodName, new Class[] {LuaState.class}); + Object obj = mt.invoke(null, new Object[] {L}); + + if (obj != null && obj instanceof Integer) + { + return ((Integer) obj).intValue(); + } + else + return 0; + } + catch (Exception e) + { + throw new LuaException("Error on calling method. Library could not be loaded. " + e.getMessage()); + } + } + } + + private static Object getObjInstance(LuaState L, Class clazz) + throws LuaException + { + synchronized (L) + { + int top = L.getTop(); + + Object[] objs = new Object[top - 1]; + + Constructor[] constructors = clazz.getConstructors(); + Constructor constructor = null; + + // gets method and arguments + for (int i = 0; i < constructors.length; i++) + { + Class[] parameters = constructors[i].getParameterTypes(); + if (parameters.length != top - 1) + continue; + + boolean okConstruc = true; + + for (int j = 0; j < parameters.length; j++) + { + try + { + objs[j] = compareTypes(L, parameters[j], j + 2); + } + catch (Exception e) + { + okConstruc = false; + break; + } + } + + if (okConstruc) + { + constructor = constructors[i]; + break; + } + + } + + // If method is null means there isn't one receiving the given arguments + if (constructor == null) + { + throw new LuaException("Invalid method call. No such method."); + } + + Object ret; + try + { + ret = constructor.newInstance(objs); + } + catch (Exception e) + { + throw new LuaException(e); + } + + if (ret == null) + { + throw new LuaException("Couldn't instantiate java Object"); + } + + return ret; + } + } + + /** + * Checks if there is a field on the obj with the given name + * + * @param luaState int that represents the state to be used + * @param obj object to be inspected + * @param fieldName name of the field to be inpected + * @return number of returned objects + */ + public static int checkField(int luaState, Object obj, String fieldName) + throws LuaException + { + LuaState L = LuaStateFactory.getExistingState(luaState); + + synchronized (L) + { + Field field = null; + Class objClass; + + if (obj instanceof Class) + { + objClass = (Class) obj; + } + else + { + objClass = obj.getClass(); + } + + try + { + field = objClass.getField(fieldName); + } + catch (Exception e) + { + return 0; + } + + if (field == null) + { + return 0; + } + + Object ret = null; + try + { + ret = field.get(obj); + } + catch (Exception e1) + { + return 0; + } + + if (obj == null) + { + return 0; + } + + L.pushObjectValue(ret); + + return 1; + } + } + + /** + * Checks to see if there is a method with the given name. + * + * @param luaState int that represents the state to be used + * @param obj object to be inspected + * @param methodName name of the field to be inpected + * @return number of returned objects + */ + public static int checkMethod(int luaState, Object obj, String methodName) + { + LuaState L = LuaStateFactory.getExistingState(luaState); + + synchronized (L) + { + Class clazz; + + if (obj instanceof Class) + { + clazz = (Class) obj; + } + else + { + clazz = obj.getClass(); + } + + Method[] methods = clazz.getMethods(); + + for (int i = 0; i < methods.length; i++) + { + if (methods[i].getName().equals(methodName)) + return 1; + } + + return 0; + } + } + + /** + * Function that creates an object proxy and pushes it into the stack + * + * @param luaState int that represents the state to be used + * @param implem interfaces implemented separated by comma (,) + * @return number of returned objects + * @throws LuaException + */ + public static int createProxyObject(int luaState, String implem) + throws LuaException + { + LuaState L = LuaStateFactory.getExistingState(luaState); + + synchronized (L) + { + try + { + if (!(L.isTable(2))) + throw new LuaException( + "Parameter is not a table. Can't create proxy."); + + LuaObject luaObj = L.getLuaObject(2); + + Object proxy = luaObj.createProxy(implem); + L.pushJavaObject(proxy); + } + catch (Exception e) + { + throw new LuaException(e); + } + + return 1; + } + } + + private static Object compareTypes(LuaState L, Class parameter, int idx) + throws LuaException + { + boolean okType = true; + Object obj = null; + + if (L.isBoolean(idx)) + { + if (parameter.isPrimitive()) + { + if (parameter != Boolean.TYPE) + { + okType = false; + } + } + else if (!parameter.isAssignableFrom(Boolean.class)) + { + okType = false; + } + obj = new Boolean(L.toBoolean(idx)); + } + else if (L.type(idx) == LuaState.LUA_TSTRING.intValue()) + { + if (!parameter.isAssignableFrom(String.class)) + { + okType = false; + } + else + { + obj = L.toString(idx); + } + } + else if (L.isFunction(idx)) + { + if (!parameter.isAssignableFrom(LuaObject.class)) + { + okType = false; + } + else + { + obj = L.getLuaObject(idx); + } + } + else if (L.isTable(idx)) + { + if (!parameter.isAssignableFrom(LuaObject.class)) + { + okType = false; + } + else + { + obj = L.getLuaObject(idx); + } + } + else if (L.type(idx) == LuaState.LUA_TNUMBER.intValue()) + { + Double db = new Double(L.toNumber(idx)); + + obj = LuaState.convertLuaNumber(db, parameter); + if (obj == null) + { + okType = false; + } + } + else if (L.isUserdata(idx)) + { + if (L.isObject(idx)) + { + Object userObj = L.getObjectFromUserdata(idx); + if (!parameter.isAssignableFrom(userObj.getClass())) + { + okType = false; + } + else + { + obj = userObj; + } + } + else + { + if (!parameter.isAssignableFrom(LuaObject.class)) + { + okType = false; + } + else + { + obj = L.getLuaObject(idx); + } + } + } + else if (L.isNil(idx)) + { + obj = null; + } + else + { + throw new LuaException("Invalid Parameters."); + } + + if (!okType) + { + throw new LuaException("Invalid Parameter."); + } + + return obj; + } + } \ No newline at end of file diff --git a/src/org/keplerproject/luajava/LuaObject.java b/app/src/main/java/org/keplerproject/luajava/LuaObject.java old mode 100755 new mode 100644 similarity index 95% rename from src/org/keplerproject/luajava/LuaObject.java rename to app/src/main/java/org/keplerproject/luajava/LuaObject.java index 64cf908..e2fe116 --- a/src/org/keplerproject/luajava/LuaObject.java +++ b/app/src/main/java/org/keplerproject/luajava/LuaObject.java @@ -1,543 +1,543 @@ -/* - * $Id: LuaObject.java,v 1.6 2006/12/22 14:06:40 thiago Exp $ - * Copyright (C) 2003-2007 Kepler Project. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -package org.keplerproject.luajava; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Proxy; -import java.util.StringTokenizer; - -/** - * This class represents a Lua object of any type. A LuaObject is constructed by a {@link LuaState} object using one of - * the four methods: - * - * The LuaObject will represent only the object itself, not a variable or a stack index, so when you change a string, - * remember that strings are immutable objects in Lua, and the LuaObject you have will represent the old one. - * - *

Proxies

- * - * LuaJava allows you to implement a class in Lua, like said before. If you want to create this proxy from Java, you - * should have a LuaObject representing the table that has the functions that implement the interface. From this - * LuaObject you can call the createProxy(String implements). This method receives the string with the - * name of the interfaces implemented by the object separated by comma. - * - * @author Rizzato - * @author Thiago Ponte - */ -public class LuaObject -{ - protected Integer ref; - - protected LuaState L; - - /** - * Creates a reference to an object in the variable globalName - * - * @param L - * @param globalName - */ - protected LuaObject(LuaState L, String globalName) - { - synchronized (L) - { - this.L = L; - L.getGlobal(globalName); - registerValue(-1); - L.pop(1); - } - } - - /** - * Creates a reference to an object inside another object - * - * @param parent - * The Lua Table or Userdata that contains the Field. - * @param name - * The name that index the field - */ - protected LuaObject(LuaObject parent, String name) throws LuaException - { - synchronized (parent.getLuaState()) - { - this.L = parent.getLuaState(); - - if (!parent.isTable() && !parent.isUserdata()) - { - throw new LuaException("Object parent should be a table or userdata ."); - } - - parent.push(); - L.pushString(name); - L.getTable(-2); - L.remove(-2); - registerValue(-1); - L.pop(1); - } - } - - /** - * This constructor creates a LuaObject from a table that is indexed by a number. - * - * @param parent - * The Lua Table or Userdata that contains the Field. - * @param name - * The name (number) that index the field - * @throws LuaException - * When the parent object isn't a Table or Userdata - */ - protected LuaObject(LuaObject parent, Number name) throws LuaException - { - synchronized (parent.getLuaState()) - { - this.L = parent.getLuaState(); - if (!parent.isTable() && !parent.isUserdata()) - throw new LuaException("Object parent should be a table or userdata ."); - - parent.push(); - L.pushNumber(name.doubleValue()); - L.getTable(-2); - L.remove(-2); - registerValue(-1); - L.pop(1); - } - } - - /** - * This constructor creates a LuaObject from a table that is indexed by a LuaObject. - * - * @param parent - * The Lua Table or Userdata that contains the Field. - * @param name - * The name (LuaObject) that index the field - * @throws LuaException - * When the parent object isn't a Table or Userdata - */ - protected LuaObject(LuaObject parent, LuaObject name) throws LuaException - { - if (parent.getLuaState() != name.getLuaState()) - throw new LuaException("LuaStates must be the same!"); - synchronized (parent.getLuaState()) - { - if (!parent.isTable() && !parent.isUserdata()) - throw new LuaException("Object parent should be a table or userdata ."); - - this.L = parent.getLuaState(); - - parent.push(); - name.push(); - L.getTable(-2); - L.remove(-2); - registerValue(-1); - L.pop(1); - } - } - - /** - * Creates a reference to an object in the given index of the stack - * - * @param L - * @param index - * of the object on the lua stack - */ - protected LuaObject(LuaState L, int index) - { - synchronized (L) - { - this.L = L; - - registerValue(index); - } - } - - /** - * Gets the Object's State - */ - public LuaState getLuaState() - { - return L; - } - - /** - * Creates the reference to the object in the registry table - * - * @param index - * of the object on the lua stack - */ - private void registerValue(int index) - { - synchronized (L) - { - L.pushValue(index); - int key = L.Lref(LuaState.LUA_REGISTRYINDEX.intValue()); - ref = new Integer(key); - } - } - - protected void finalize() - { - try - { - synchronized (L) - { - if (L.getCPtrPeer() != 0) - L.LunRef(LuaState.LUA_REGISTRYINDEX.intValue(), ref.intValue()); - } - } - catch (Exception e) - { - System.err.println("Unable to release object " + ref); - } - } - - /** - * Pushes the object represented by this into L's stack - */ - public void push() - { - L.rawGetI(LuaState.LUA_REGISTRYINDEX.intValue(), ref.intValue()); - } - - public boolean isNil() - { - synchronized (L) - { - push(); - boolean bool = L.isNil(-1); - L.pop(1); - return bool; - } - } - - public boolean isBoolean() - { - synchronized (L) - { - push(); - boolean bool = L.isBoolean(-1); - L.pop(1); - return bool; - } - } - - public boolean isNumber() - { - synchronized (L) - { - push(); - boolean bool = L.isNumber(-1); - L.pop(1); - return bool; - } - } - - public boolean isString() - { - synchronized (L) - { - push(); - boolean bool = L.isString(-1); - L.pop(1); - return bool; - } - } - - public boolean isFunction() - { - synchronized (L) - { - push(); - boolean bool = L.isFunction(-1); - L.pop(1); - return bool; - } - } - - public boolean isJavaObject() - { - synchronized (L) - { - push(); - boolean bool = L.isObject(-1); - L.pop(1); - return bool; - } - } - - public boolean isJavaFunction() - { - synchronized (L) - { - push(); - boolean bool = L.isJavaFunction(-1); - L.pop(1); - return bool; - } - } - - public boolean isTable() - { - synchronized (L) - { - push(); - boolean bool = L.isTable(-1); - L.pop(1); - return bool; - } - } - - public boolean isUserdata() - { - synchronized (L) - { - push(); - boolean bool = L.isUserdata(-1); - L.pop(1); - return bool; - } - } - - public int type() - { - synchronized (L) - { - push(); - int type = L.type(-1); - L.pop(1); - return type; - } - } - - public boolean getBoolean() - { - synchronized (L) - { - push(); - boolean bool = L.toBoolean(-1); - L.pop(1); - return bool; - } - } - - public double getNumber() - { - synchronized (L) - { - push(); - double db = L.toNumber(-1); - L.pop(1); - return db; - } - } - - public String getString() - { - synchronized (L) - { - push(); - String str = L.toString(-1); - L.pop(1); - return str; - } - } - - public Object getObject() throws LuaException - { - synchronized (L) - { - push(); - Object obj = L.getObjectFromUserdata(-1); - L.pop(1); - return obj; - } - } - - /** - * If this is a table or userdata tries to set - * a field value. - */ - public LuaObject getField(String field) throws LuaException - { - return L.getLuaObject(this, field); - } - - /** - * Calls the object represented by this using Lua function pcall. - * - * @param args - - * Call arguments - * @param nres - - * Number of objects returned - * @return Object[] - Returned Objects - * @throws LuaException - */ - public Object[] call(Object[] args, int nres) throws LuaException - { - synchronized (L) - { - if (!isFunction() && !isTable() && !isUserdata()) - throw new LuaException("Invalid object. Not a function, table or userdata ."); - - int top = L.getTop(); - push(); - int nargs; - if (args != null) - { - nargs = args.length; - for (int i = 0; i < nargs; i++) - { - Object obj = args[i]; - L.pushObjectValue(obj); - } - } - else - nargs = 0; - - int err = L.pcall(nargs, nres, 0); - - if (err != 0) - { - String str; - if (L.isString(-1)) - { - str = L.toString(-1); - L.pop(1); - } - else - str = ""; - - if (err == LuaState.LUA_ERRRUN.intValue()) - { - str = "Runtime error. " + str; - } - else if (err == LuaState.LUA_ERRMEM.intValue()) - { - str = "Memory allocation error. " + str; - } - else if (err == LuaState.LUA_ERRERR.intValue()) - { - str = "Error while running the error handler function. " + str; - } - else - { - str = "Lua Error code " + err + ". " + str; - } - - throw new LuaException(str); - } - - if (nres == LuaState.LUA_MULTRET.intValue()) - nres = L.getTop() - top; - if (L.getTop() - top < nres) - { - throw new LuaException("Invalid Number of Results ."); - } - - Object[] res = new Object[nres]; - - for (int i = nres; i > 0; i--) - { - res[i - 1] = L.toJavaObject(-1); - L.pop(1); - } - return res; - } - } - - /** - * Calls the object represented by this using Lua function pcall. Returns 1 object - * - * @param args - - * Call arguments - * @return Object - Returned Object - * @throws LuaException - */ - public Object call(Object[] args) throws LuaException - { - return call(args, 1)[0]; - } - - public String toString() - { - synchronized (L) - { - try - { - if (isNil()) - return "nil"; - else if (isBoolean()) - return String.valueOf(getBoolean()); - else if (isNumber()) - return String.valueOf(getNumber()); - else if (isString()) - return getString(); - else if (isFunction()) - return "Lua Function"; - else if (isJavaObject()) - return getObject().toString(); - else if (isUserdata()) - return "Userdata"; - else if (isTable()) - return "Lua Table"; - else if (isJavaFunction()) - return "Java Function"; - else - return null; - } - catch (LuaException e) - { - return null; - } - } - } - - /** - * Function that creates a java proxy to the object represented by this - * - * @param implem - * Interfaces that are implemented, separated by , - */ - public Object createProxy(String implem) throws ClassNotFoundException, LuaException - { - synchronized (L) - { - if (!isTable()) - throw new LuaException("Invalid Object. Must be Table."); - - StringTokenizer st = new StringTokenizer(implem, ","); - Class[] interfaces = new Class[st.countTokens()]; - for (int i = 0; st.hasMoreTokens(); i++) - interfaces[i] = Class.forName(st.nextToken()); - - InvocationHandler handler = new LuaInvocationHandler(this); - - return Proxy.newProxyInstance(this.getClass().getClassLoader(), interfaces, handler); - } - } -} +/* + * $Id: LuaObject.java,v 1.6 2006/12/22 14:06:40 thiago Exp $ + * Copyright (C) 2003-2007 Kepler Project. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package org.keplerproject.luajava; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; +import java.util.StringTokenizer; + +/** + * This class represents a Lua object of any type. A LuaObject is constructed by a {@link LuaState} object using one of + * the four methods: + *
    + *
  • {@link LuaState#getLuaObject(String globalName)}
  • + *
  • {@link LuaState#getLuaObject(LuaObject parent, String name)}
  • + *
  • {@link LuaState#getLuaObject(LuaObject parent, Number name)}
  • + *
  • {@link LuaState#getLuaObject(LuaObject parent, LuaObject name)}
  • + *
  • {@link LuaState#getLuaObject(int index)}
  • + *
+ * The LuaObject will represent only the object itself, not a variable or a stack index, so when you change a string, + * remember that strings are immutable objects in Lua, and the LuaObject you have will represent the old one. + * + *

Proxies

+ * + * LuaJava allows you to implement a class in Lua, like said before. If you want to create this proxy from Java, you + * should have a LuaObject representing the table that has the functions that implement the interface. From this + * LuaObject you can call the createProxy(String implements). This method receives the string with the + * name of the interfaces implemented by the object separated by comma. + * + * @author Rizzato + * @author Thiago Ponte + */ +public class LuaObject +{ + protected Integer ref; + + protected LuaState L; + + /** + * Creates a reference to an object in the variable globalName + * + * @param L + * @param globalName + */ + protected LuaObject(LuaState L, String globalName) + { + synchronized (L) + { + this.L = L; + L.getGlobal(globalName); + registerValue(-1); + L.pop(1); + } + } + + /** + * Creates a reference to an object inside another object + * + * @param parent + * The Lua Table or Userdata that contains the Field. + * @param name + * The name that index the field + */ + protected LuaObject(LuaObject parent, String name) throws LuaException + { + synchronized (parent.getLuaState()) + { + this.L = parent.getLuaState(); + + if (!parent.isTable() && !parent.isUserdata()) + { + throw new LuaException("Object parent should be a table or userdata ."); + } + + parent.push(); + L.pushString(name); + L.getTable(-2); + L.remove(-2); + registerValue(-1); + L.pop(1); + } + } + + /** + * This constructor creates a LuaObject from a table that is indexed by a number. + * + * @param parent + * The Lua Table or Userdata that contains the Field. + * @param name + * The name (number) that index the field + * @throws LuaException + * When the parent object isn't a Table or Userdata + */ + protected LuaObject(LuaObject parent, Number name) throws LuaException + { + synchronized (parent.getLuaState()) + { + this.L = parent.getLuaState(); + if (!parent.isTable() && !parent.isUserdata()) + throw new LuaException("Object parent should be a table or userdata ."); + + parent.push(); + L.pushNumber(name.doubleValue()); + L.getTable(-2); + L.remove(-2); + registerValue(-1); + L.pop(1); + } + } + + /** + * This constructor creates a LuaObject from a table that is indexed by a LuaObject. + * + * @param parent + * The Lua Table or Userdata that contains the Field. + * @param name + * The name (LuaObject) that index the field + * @throws LuaException + * When the parent object isn't a Table or Userdata + */ + protected LuaObject(LuaObject parent, LuaObject name) throws LuaException + { + if (parent.getLuaState() != name.getLuaState()) + throw new LuaException("LuaStates must be the same!"); + synchronized (parent.getLuaState()) + { + if (!parent.isTable() && !parent.isUserdata()) + throw new LuaException("Object parent should be a table or userdata ."); + + this.L = parent.getLuaState(); + + parent.push(); + name.push(); + L.getTable(-2); + L.remove(-2); + registerValue(-1); + L.pop(1); + } + } + + /** + * Creates a reference to an object in the given index of the stack + * + * @param L + * @param index + * of the object on the lua stack + */ + protected LuaObject(LuaState L, int index) + { + synchronized (L) + { + this.L = L; + + registerValue(index); + } + } + + /** + * Gets the Object's State + */ + public LuaState getLuaState() + { + return L; + } + + /** + * Creates the reference to the object in the registry table + * + * @param index + * of the object on the lua stack + */ + private void registerValue(int index) + { + synchronized (L) + { + L.pushValue(index); + int key = L.Lref(LuaState.LUA_REGISTRYINDEX.intValue()); + ref = new Integer(key); + } + } + + protected void finalize() + { + try + { + synchronized (L) + { + if (L.getCPtrPeer() != 0) + L.LunRef(LuaState.LUA_REGISTRYINDEX.intValue(), ref.intValue()); + } + } + catch (Exception e) + { + System.err.println("Unable to release object " + ref); + } + } + + /** + * Pushes the object represented by this into L's stack + */ + public void push() + { + L.rawGetI(LuaState.LUA_REGISTRYINDEX.intValue(), ref.intValue()); + } + + public boolean isNil() + { + synchronized (L) + { + push(); + boolean bool = L.isNil(-1); + L.pop(1); + return bool; + } + } + + public boolean isBoolean() + { + synchronized (L) + { + push(); + boolean bool = L.isBoolean(-1); + L.pop(1); + return bool; + } + } + + public boolean isNumber() + { + synchronized (L) + { + push(); + boolean bool = L.isNumber(-1); + L.pop(1); + return bool; + } + } + + public boolean isString() + { + synchronized (L) + { + push(); + boolean bool = L.isString(-1); + L.pop(1); + return bool; + } + } + + public boolean isFunction() + { + synchronized (L) + { + push(); + boolean bool = L.isFunction(-1); + L.pop(1); + return bool; + } + } + + public boolean isJavaObject() + { + synchronized (L) + { + push(); + boolean bool = L.isObject(-1); + L.pop(1); + return bool; + } + } + + public boolean isJavaFunction() + { + synchronized (L) + { + push(); + boolean bool = L.isJavaFunction(-1); + L.pop(1); + return bool; + } + } + + public boolean isTable() + { + synchronized (L) + { + push(); + boolean bool = L.isTable(-1); + L.pop(1); + return bool; + } + } + + public boolean isUserdata() + { + synchronized (L) + { + push(); + boolean bool = L.isUserdata(-1); + L.pop(1); + return bool; + } + } + + public int type() + { + synchronized (L) + { + push(); + int type = L.type(-1); + L.pop(1); + return type; + } + } + + public boolean getBoolean() + { + synchronized (L) + { + push(); + boolean bool = L.toBoolean(-1); + L.pop(1); + return bool; + } + } + + public double getNumber() + { + synchronized (L) + { + push(); + double db = L.toNumber(-1); + L.pop(1); + return db; + } + } + + public String getString() + { + synchronized (L) + { + push(); + String str = L.toString(-1); + L.pop(1); + return str; + } + } + + public Object getObject() throws LuaException + { + synchronized (L) + { + push(); + Object obj = L.getObjectFromUserdata(-1); + L.pop(1); + return obj; + } + } + + /** + * If this is a table or userdata tries to set + * a field value. + */ + public LuaObject getField(String field) throws LuaException + { + return L.getLuaObject(this, field); + } + + /** + * Calls the object represented by this using Lua function pcall. + * + * @param args - + * Call arguments + * @param nres - + * Number of objects returned + * @return Object[] - Returned Objects + * @throws LuaException + */ + public Object[] call(Object[] args, int nres) throws LuaException + { + synchronized (L) + { + if (!isFunction() && !isTable() && !isUserdata()) + throw new LuaException("Invalid object. Not a function, table or userdata ."); + + int top = L.getTop(); + push(); + int nargs; + if (args != null) + { + nargs = args.length; + for (int i = 0; i < nargs; i++) + { + Object obj = args[i]; + L.pushObjectValue(obj); + } + } + else + nargs = 0; + + int err = L.pcall(nargs, nres, 0); + + if (err != 0) + { + String str; + if (L.isString(-1)) + { + str = L.toString(-1); + L.pop(1); + } + else + str = ""; + + if (err == LuaState.LUA_ERRRUN.intValue()) + { + str = "Runtime error. " + str; + } + else if (err == LuaState.LUA_ERRMEM.intValue()) + { + str = "Memory allocation error. " + str; + } + else if (err == LuaState.LUA_ERRERR.intValue()) + { + str = "Error while running the error handler function. " + str; + } + else + { + str = "Lua Error code " + err + ". " + str; + } + + throw new LuaException(str); + } + + if (nres == LuaState.LUA_MULTRET.intValue()) + nres = L.getTop() - top; + if (L.getTop() - top < nres) + { + throw new LuaException("Invalid Number of Results ."); + } + + Object[] res = new Object[nres]; + + for (int i = nres; i > 0; i--) + { + res[i - 1] = L.toJavaObject(-1); + L.pop(1); + } + return res; + } + } + + /** + * Calls the object represented by this using Lua function pcall. Returns 1 object + * + * @param args - + * Call arguments + * @return Object - Returned Object + * @throws LuaException + */ + public Object call(Object[] args) throws LuaException + { + return call(args, 1)[0]; + } + + public String toString() + { + synchronized (L) + { + try + { + if (isNil()) + return "nil"; + else if (isBoolean()) + return String.valueOf(getBoolean()); + else if (isNumber()) + return String.valueOf(getNumber()); + else if (isString()) + return getString(); + else if (isFunction()) + return "Lua Function"; + else if (isJavaObject()) + return getObject().toString(); + else if (isUserdata()) + return "Userdata"; + else if (isTable()) + return "Lua Table"; + else if (isJavaFunction()) + return "Java Function"; + else + return null; + } + catch (LuaException e) + { + return null; + } + } + } + + /** + * Function that creates a java proxy to the object represented by this + * + * @param implem + * Interfaces that are implemented, separated by , + */ + public Object createProxy(String implem) throws ClassNotFoundException, LuaException + { + synchronized (L) + { + if (!isTable()) + throw new LuaException("Invalid Object. Must be Table."); + + StringTokenizer st = new StringTokenizer(implem, ","); + Class[] interfaces = new Class[st.countTokens()]; + for (int i = 0; st.hasMoreTokens(); i++) + interfaces[i] = Class.forName(st.nextToken()); + + InvocationHandler handler = new LuaInvocationHandler(this); + + return Proxy.newProxyInstance(this.getClass().getClassLoader(), interfaces, handler); + } + } +} diff --git a/src/org/keplerproject/luajava/LuaState.java b/app/src/main/java/org/keplerproject/luajava/LuaState.java old mode 100755 new mode 100644 similarity index 96% rename from src/org/keplerproject/luajava/LuaState.java rename to app/src/main/java/org/keplerproject/luajava/LuaState.java index c081cb5..2868953 --- a/src/org/keplerproject/luajava/LuaState.java +++ b/app/src/main/java/org/keplerproject/luajava/LuaState.java @@ -1,1184 +1,1184 @@ -/* - * $Id: LuaState.java,v 1.9 2006/12/22 14:06:40 thiago Exp $ - * Copyright (C) 2003-2007 Kepler Project. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -package org.keplerproject.luajava; - -/** - * LuaState if the main class of LuaJava for the Java developer. - * LuaState is a mapping of most of Lua's C API functions. - * LuaState also provides many other functions that will be used to manipulate - * objects between Lua and Java. - * @author Thiago Ponte - */ -public class LuaState -{ - private final static String LUAJAVA_LIB = "luajava"; - - final public static Integer LUA_GLOBALSINDEX = new Integer(-10002); - final public static Integer LUA_REGISTRYINDEX = new Integer(-10000); - - final public static Integer LUA_TNONE = new Integer(-1); - final public static Integer LUA_TNIL = new Integer(0); - final public static Integer LUA_TBOOLEAN = new Integer(1); - final public static Integer LUA_TLIGHTUSERDATA = new Integer(2); - final public static Integer LUA_TNUMBER = new Integer(3); - final public static Integer LUA_TSTRING = new Integer(4); - final public static Integer LUA_TTABLE = new Integer(5); - final public static Integer LUA_TFUNCTION = new Integer(6); - final public static Integer LUA_TUSERDATA = new Integer(7); - final public static Integer LUA_TTHREAD = new Integer(8); - - /** - * Specifies that an unspecified (multiple) number of return arguments - * will be returned by a call. - */ - final public static Integer LUA_MULTRET = new Integer(-1); - - /* - * error codes for `lua_load' and `lua_pcall' - */ - /** - * a runtime error. - */ - final public static Integer LUA_ERRRUN = new Integer(1); - - /** - * - */ - final public static Integer LUA_YIELD = new Integer(2); - - /** - * syntax error during pre-compilation. - */ - final public static Integer LUA_ERRSYNTAX = new Integer(3); - - /** - * memory allocation error. For such errors, Lua does not call - * the error handler function. - */ - final public static Integer LUA_ERRMEM = new Integer(4); - - /** - * error while running the error handler function. - */ - final public static Integer LUA_ERRERR = new Integer(5); - - /** - * Opens the library containing the luajava API - */ - static - { - System.loadLibrary(LUAJAVA_LIB); - } - - private CPtr luaState; - - private int stateId; - - /** - * Constructor to instance a new LuaState and initialize it with LuaJava's functions - * @param stateId - */ - protected LuaState(int stateId) - { - luaState = _open(); - luajava_open(luaState, stateId); - this.stateId = stateId; - } - - /** - * Receives a existing state and initializes it - * @param luaState - */ - protected LuaState(CPtr luaState) - { - this.luaState = luaState; - this.stateId = LuaStateFactory.insertLuaState(this); - luajava_open(luaState, stateId); - } - - /** - * Closes state and removes the object from the LuaStateFactory - */ - public synchronized void close() - { - LuaStateFactory.removeLuaState(stateId); - _close(luaState); - this.luaState = null; - } - - /** - * Returns true if state is closed. - */ - public synchronized boolean isClosed() - { - return luaState == null; - } - - /** - * Return the long representing the LuaState pointer - * @return long - */ - public long getCPtrPeer() - { - return (luaState != null)? luaState.getPeer() : 0; - } - - - /********************* Lua Native Interface *************************/ - - private synchronized native CPtr _open(); - private synchronized native void _close(CPtr ptr); - private synchronized native CPtr _newthread(CPtr ptr); - - // Stack manipulation - private synchronized native int _getTop(CPtr ptr); - private synchronized native void _setTop(CPtr ptr, int idx); - private synchronized native void _pushValue(CPtr ptr, int idx); - private synchronized native void _remove(CPtr ptr, int idx); - private synchronized native void _insert(CPtr ptr, int idx); - private synchronized native void _replace(CPtr ptr, int idx); - private synchronized native int _checkStack(CPtr ptr, int sz); - - private synchronized native void _xmove(CPtr from, CPtr to, int n); - - // Access functions - private synchronized native int _isNumber(CPtr ptr, int idx); - private synchronized native int _isString(CPtr ptr, int idx); - private synchronized native int _isCFunction(CPtr ptr, int idx); - private synchronized native int _isUserdata(CPtr ptr, int idx); - private synchronized native int _type(CPtr ptr, int idx); - private synchronized native String _typeName(CPtr ptr, int tp); - - private synchronized native int _equal(CPtr ptr, int idx1, int idx2); - private synchronized native int _rawequal(CPtr ptr, int idx1, int idx2); - private synchronized native int _lessthan(CPtr ptr, int idx1, int idx2); - - private synchronized native double _toNumber(CPtr ptr, int idx); - private synchronized native int _toInteger(CPtr ptr, int idx); - private synchronized native int _toBoolean(CPtr ptr, int idx); - private synchronized native String _toString(CPtr ptr, int idx); - private synchronized native int _objlen(CPtr ptr, int idx); - private synchronized native CPtr _toThread(CPtr ptr, int idx); - - // Push functions - private synchronized native void _pushNil(CPtr ptr); - private synchronized native void _pushNumber(CPtr ptr, double number); - private synchronized native void _pushInteger(CPtr ptr, int integer); - private synchronized native void _pushString(CPtr ptr, String str); - private synchronized native void _pushString(CPtr ptr, byte[] bytes, int n); - private synchronized native void _pushBoolean(CPtr ptr, int bool); - - // Get functions - private synchronized native void _getTable(CPtr ptr, int idx); - private synchronized native void _getField(CPtr ptr, int idx, String k); - private synchronized native void _rawGet(CPtr ptr, int idx); - private synchronized native void _rawGetI(CPtr ptr, int idx, int n); - private synchronized native void _createTable(CPtr ptr, int narr, int nrec); - private synchronized native int _getMetaTable(CPtr ptr, int idx); - private synchronized native void _getFEnv(CPtr ptr, int idx); - - // Set functions - private synchronized native void _setTable(CPtr ptr, int idx); - private synchronized native void _setField(CPtr ptr, int idx, String k); - private synchronized native void _rawSet(CPtr ptr, int idx); - private synchronized native void _rawSetI(CPtr ptr, int idx, int n); - private synchronized native int _setMetaTable(CPtr ptr, int idx); - private synchronized native int _setFEnv(CPtr ptr, int idx); - - private synchronized native void _call(CPtr ptr, int nArgs, int nResults); - private synchronized native int _pcall(CPtr ptr, int nArgs, int Results, int errFunc); - - // Coroutine Functions - private synchronized native int _yield(CPtr ptr, int nResults); - private synchronized native int _resume(CPtr ptr, int nargs); - private synchronized native int _status(CPtr ptr); - - // Gargabe Collection Functions - final public static Integer LUA_GCSTOP = new Integer(0); - final public static Integer LUA_GCRESTART = new Integer(1); - final public static Integer LUA_GCCOLLECT = new Integer(2); - final public static Integer LUA_GCCOUNT = new Integer(3); - final public static Integer LUA_GCCOUNTB = new Integer(4); - final public static Integer LUA_GCSTEP = new Integer(5); - final public static Integer LUA_GCSETPAUSE = new Integer(6); - final public static Integer LUA_GCSETSTEPMUL = new Integer(7); - private synchronized native int _gc(CPtr ptr, int what, int data); - - // Miscellaneous Functions - private synchronized native int _error(CPtr ptr); - private synchronized native int _next(CPtr ptr, int idx); - private synchronized native void _concat(CPtr ptr, int n); - - // Some macros - private synchronized native void _pop(CPtr ptr, int n); - private synchronized native void _newTable(CPtr ptr); - private synchronized native int _strlen(CPtr ptr, int idx); - private synchronized native int _isFunction(CPtr ptr, int idx); - private synchronized native int _isTable(CPtr ptr, int idx); - private synchronized native int _isNil(CPtr ptr, int idx); - private synchronized native int _isBoolean(CPtr ptr, int idx); - private synchronized native int _isThread(CPtr ptr, int idx); - private synchronized native int _isNone(CPtr ptr, int idx); - private synchronized native int _isNoneOrNil(CPtr ptr, int idx); - - private synchronized native void _setGlobal(CPtr ptr, String name); - private synchronized native void _getGlobal(CPtr ptr, String name); - - private synchronized native int _getGcCount(CPtr ptr); - - - // LuaLibAux - private synchronized native int _LdoFile(CPtr ptr, String fileName); - private synchronized native int _LdoString(CPtr ptr, String string); - //private synchronized native int _doBuffer(CPtr ptr, byte[] buff, long sz, String n); - - private synchronized native int _LgetMetaField(CPtr ptr, int obj, String e); - private synchronized native int _LcallMeta(CPtr ptr, int obj, String e); - private synchronized native int _Ltyperror(CPtr ptr, int nArg, String tName); - private synchronized native int _LargError(CPtr ptr, int numArg, String extraMsg); - private synchronized native String _LcheckString(CPtr ptr, int numArg); - private synchronized native String _LoptString(CPtr ptr, int numArg, String def); - private synchronized native double _LcheckNumber(CPtr ptr, int numArg); - private synchronized native double _LoptNumber(CPtr ptr, int numArg, double def); - - private synchronized native int _LcheckInteger(CPtr ptr, int numArg); - private synchronized native int _LoptInteger(CPtr ptr, int numArg, int def); - - private synchronized native void _LcheckStack(CPtr ptr, int sz, String msg); - private synchronized native void _LcheckType(CPtr ptr, int nArg, int t); - private synchronized native void _LcheckAny(CPtr ptr, int nArg); - - private synchronized native int _LnewMetatable(CPtr ptr, String tName); - private synchronized native void _LgetMetatable(CPtr ptr, String tName); - - private synchronized native void _Lwhere(CPtr ptr, int lvl); - - private synchronized native int _Lref(CPtr ptr, int t); - private synchronized native void _LunRef(CPtr ptr, int t, int ref); - - private synchronized native int _LgetN(CPtr ptr, int t); - private synchronized native void _LsetN(CPtr ptr, int t, int n); - - private synchronized native int _LloadFile(CPtr ptr, String fileName); - private synchronized native int _LloadBuffer(CPtr ptr, byte[] buff, long sz, String name); - private synchronized native int _LloadString(CPtr ptr, String s); - - private synchronized native String _Lgsub(CPtr ptr, String s, String p, String r); - private synchronized native String _LfindTable(CPtr ptr, int idx, String fname, int szhint); - - - private synchronized native void _openBase(CPtr ptr); - private synchronized native void _openTable(CPtr ptr); - private synchronized native void _openIo(CPtr ptr); - private synchronized native void _openOs(CPtr ptr); - private synchronized native void _openString(CPtr ptr); - private synchronized native void _openMath(CPtr ptr); - private synchronized native void _openDebug(CPtr ptr); - private synchronized native void _openPackage(CPtr ptr); - private synchronized native void _openLibs(CPtr ptr); - - // Java Interface ----------------------------------------------------- - - public LuaState newThread() - { - LuaState l = new LuaState(_newthread(luaState)); - LuaStateFactory.insertLuaState(l); - return l; - } - - // STACK MANIPULATION - - public int getTop() - { - return _getTop(luaState); - } - - public void setTop(int idx) - { - _setTop(luaState, idx); - } - - public void pushValue(int idx) - { - _pushValue(luaState, idx); - } - - public void remove(int idx) - { - _remove(luaState, idx); - } - - public void insert(int idx) - { - _insert(luaState, idx); - } - - public void replace(int idx) - { - _replace(luaState, idx); - } - - public int checkStack(int sz) - { - return _checkStack(luaState, sz); - } - - public void xmove(LuaState to, int n) - { - _xmove(luaState, to.luaState, n); - } - - // ACCESS FUNCTION - - public boolean isNumber(int idx) - { - return (_isNumber(luaState, idx)!=0); - } - - public boolean isString(int idx) - { - return (_isString(luaState, idx)!=0); - } - - public boolean isFunction(int idx) - { - return (_isFunction(luaState, idx)!=0); - } - - public boolean isCFunction(int idx) - { - return (_isCFunction(luaState, idx)!=0); - } - - public boolean isUserdata(int idx) - { - return (_isUserdata(luaState, idx)!=0); - } - - public boolean isTable(int idx) - { - return (_isTable(luaState, idx)!=0); - } - - public boolean isBoolean(int idx) - { - return (_isBoolean(luaState, idx)!=0); - } - - public boolean isNil(int idx) - { - return (_isNil(luaState, idx)!=0); - } - - public boolean isThread(int idx) - { - return (_isThread(luaState, idx)!=0); - } - - public boolean isNone(int idx) - { - return (_isNone(luaState, idx)!=0); - } - - public boolean isNoneOrNil(int idx) - { - return (_isNoneOrNil(luaState, idx)!=0); - } - - public int type(int idx) - { - return _type(luaState, idx); - } - - public String typeName(int tp) - { - return _typeName(luaState, tp); - } - - public int equal(int idx1, int idx2) - { - return _equal(luaState, idx1, idx2); - } - - public int rawequal(int idx1, int idx2) - { - return _rawequal(luaState, idx1, idx2); - } - - public int lessthan(int idx1, int idx2) - { - return _lessthan(luaState, idx1, idx2); - } - - public double toNumber(int idx) - { - return _toNumber(luaState, idx); - } - - public int toInteger(int idx) - { - return _toInteger(luaState, idx); - } - - public boolean toBoolean(int idx) - { - return (_toBoolean(luaState, idx)!=0); - } - - public String toString(int idx) - { - return _toString(luaState, idx); - } - - public int strLen(int idx) - { - return _strlen(luaState, idx); - } - - public int objLen(int idx) - { - return _objlen(luaState, idx); - } - - public LuaState toThread(int idx) - { - return new LuaState(_toThread(luaState, idx)); - } - - //PUSH FUNCTIONS - - public void pushNil() - { - _pushNil(luaState); - } - - public void pushNumber(double db) - { - _pushNumber(luaState, db); - } - - public void pushInteger(int integer) - { - _pushInteger(luaState, integer); - } - - public void pushString(String str) - { - if (str == null) - _pushNil(luaState); - else - _pushString(luaState, str); - } - - public void pushString(byte[] bytes) - { - if (bytes == null) - _pushNil(luaState); - else - _pushString(luaState, bytes, bytes.length); - } - - public void pushBoolean(boolean bool) - { - _pushBoolean(luaState, bool ? 1 : 0); - } - - // GET FUNCTIONS - - public void getTable(int idx) - { - _getTable(luaState, idx); - } - - public void getField(int idx, String k) - { - _getField(luaState, idx, k); - } - - public void rawGet(int idx) - { - _rawGet(luaState, idx); - } - - public void rawGetI(int idx, int n) - { - _rawGetI(luaState, idx, n); - } - - public void createTable(int narr, int nrec) - { - _createTable(luaState, narr, nrec); - } - - public void newTable() - { - _newTable(luaState); - } - - // if returns 0, there is no metatable - public int getMetaTable(int idx) - { - return _getMetaTable(luaState, idx); - } - - public void getFEnv(int idx) - { - _getFEnv(luaState, idx); - } - - // SET FUNCTIONS - - public void setTable(int idx) - { - _setTable(luaState, idx); - } - - public void setField(int idx, String k) - { - _setField(luaState, idx, k); - } - - public void rawSet(int idx) - { - _rawSet(luaState, idx); - } - - public void rawSetI(int idx, int n) - { - _rawSetI(luaState, idx, n); - } - - // if returns 0, cannot set the metatable to the given object - public int setMetaTable(int idx) - { - return _setMetaTable(luaState, idx); - } - - // if object is not a function returns 0 - public int setFEnv(int idx) - { - return _setFEnv(luaState, idx); - } - - public void call(int nArgs, int nResults) - { - _call(luaState, nArgs, nResults); - } - - // returns 0 if ok of one of the error codes defined - public int pcall(int nArgs, int nResults, int errFunc) - { - return _pcall(luaState, nArgs, nResults, errFunc); - } - - public int yield(int nResults) - { - return _yield(luaState, nResults); - } - - public int resume(int nArgs) - { - return _resume(luaState, nArgs); - } - - public int status() - { - return _status(luaState); - } - - public int gc(int what, int data) - { - return _gc(luaState, what, data); - } - - public int getGcCount() - { - return _getGcCount(luaState); - } - - public int next(int idx) - { - return _next(luaState, idx); - } - - public int error() - { - return _error(luaState); - } - - public void concat(int n) - { - _concat(luaState, n); - } - - - // FUNCTION FROM lauxlib - // returns 0 if ok - public int LdoFile(String fileName) - { - return _LdoFile(luaState, fileName); - } - - // returns 0 if ok - public int LdoString(String str) - { - return _LdoString(luaState, str); - } - - public int LgetMetaField(int obj, String e) - { - return _LgetMetaField(luaState, obj, e); - } - - public int LcallMeta(int obj, String e) - { - return _LcallMeta(luaState, obj, e); - } - - public int Ltyperror(int nArg, String tName) - { - return _Ltyperror(luaState, nArg, tName); - } - - public int LargError(int numArg, String extraMsg) - { - return _LargError(luaState, numArg, extraMsg); - } - - public String LcheckString(int numArg) - { - return _LcheckString(luaState, numArg); - } - - public String LoptString(int numArg, String def) - { - return _LoptString(luaState, numArg, def); - } - - public double LcheckNumber(int numArg) - { - return _LcheckNumber(luaState, numArg); - } - - public double LoptNumber(int numArg, double def) - { - return _LoptNumber(luaState, numArg, def); - } - - public int LcheckInteger(int numArg) - { - return _LcheckInteger(luaState, numArg); - } - - public int LoptInteger(int numArg, int def) - { - return _LoptInteger(luaState, numArg, def); - } - - public void LcheckStack(int sz, String msg) - { - _LcheckStack(luaState, sz, msg); - } - - public void LcheckType(int nArg, int t) - { - _LcheckType(luaState, nArg, t); - } - - public void LcheckAny(int nArg) - { - _LcheckAny(luaState, nArg); - } - - public int LnewMetatable(String tName) - { - return _LnewMetatable(luaState, tName); - } - - public void LgetMetatable(String tName) - { - _LgetMetatable(luaState, tName); - } - - public void Lwhere(int lvl) - { - _Lwhere(luaState, lvl); - } - - public int Lref(int t) - { - return _Lref(luaState, t); - } - - public void LunRef(int t, int ref) - { - _LunRef(luaState, t, ref); - } - - public int LgetN(int t) - { - return _LgetN(luaState, t); - } - - public void LsetN(int t, int n) - { - _LsetN(luaState, t, n); - } - - public int LloadFile(String fileName) - { - return _LloadFile(luaState, fileName); - } - - public int LloadString(String s) - { - return _LloadString(luaState, s); - } - - public int LloadBuffer(byte[] buff, String name) - { - return _LloadBuffer(luaState, buff, buff.length, name); - } - - public String Lgsub(String s, String p, String r) - { - return _Lgsub(luaState, s, p, r); - } - - public String LfindTable(int idx, String fname, int szhint) - { - return _LfindTable(luaState, idx, fname, szhint); - } - - //IMPLEMENTED C MACROS - - public void pop(int n) - { - //setTop(- (n) - 1); - _pop(luaState, n); - } - - public synchronized void getGlobal(String global) - { -// pushString(global); -// getTable(LUA_GLOBALSINDEX.intValue()); - _getGlobal(luaState, global); - } - - public synchronized void setGlobal(String name) - { - //pushString(name); - //insert(-2); - //setTable(LUA_GLOBALSINDEX.intValue()); - _setGlobal(luaState, name); - } - - // Functions to open lua libraries - public void openBase() - { - _openBase(luaState); - } - public void openTable() - { - _openTable(luaState); - } - public void openIo() - { - _openIo(luaState); - } - public void openOs() - { - _openOs(luaState); - } - public void openString() - { - _openString(luaState); - } - public void openMath() - { - _openMath(luaState); - } - public void openDebug() - { - _openDebug(luaState); - } - public void openPackage() - { - _openPackage(luaState); - } - public void openLibs() - { - _openLibs(luaState); - } - - - /********************** Luajava API Library **********************/ - - /** - * Initializes lua State to be used by luajava - * @param cptr - * @param stateId - */ - private synchronized native void luajava_open(CPtr cptr, int stateId); - /** - * Gets a Object from a userdata - * @param L - * @param idx index of the lua stack - * @return Object - */ - private synchronized native Object _getObjectFromUserdata(CPtr L, int idx) throws LuaException; - - /** - * Returns whether a userdata contains a Java Object - * @param L - * @param idx index of the lua stack - * @return boolean - */ - private synchronized native boolean _isObject(CPtr L, int idx); - - /** - * Pushes a Java Object into the state stack - * @param L - * @param obj - */ - private synchronized native void _pushJavaObject(CPtr L, Object obj); - - /** - * Pushes a JavaFunction into the state stack - * @param L - * @param func - */ - private synchronized native void _pushJavaFunction(CPtr L, JavaFunction func) throws LuaException; - - /** - * Returns whether a userdata contains a Java Function - * @param L - * @param idx index of the lua stack - * @return boolean - */ - private synchronized native boolean _isJavaFunction(CPtr L, int idx); - - /** - * Gets a Object from Lua - * @param idx index of the lua stack - * @return Object - * @throws LuaException if the lua object does not represent a java object. - */ - public Object getObjectFromUserdata(int idx) throws LuaException - { - return _getObjectFromUserdata(luaState, idx); - } - - /** - * Tells whether a lua index contains a java Object - * @param idx index of the lua stack - * @return boolean - */ - public boolean isObject(int idx) - { - return _isObject(luaState, idx); - } - - /** - * Pushes a Java Object into the lua stack.
- * This function does not check if the object is from a class that could - * be represented by a lua type. Eg: java.lang.String could be a lua string. - * @param obj Object to be pushed into lua - */ - public void pushJavaObject(Object obj) - { - _pushJavaObject(luaState, obj); - } - - /** - * Pushes a JavaFunction into the state stack - * @param func - */ - public void pushJavaFunction(JavaFunction func) throws LuaException - { - _pushJavaFunction(luaState, func); - } - - /** - * Returns whether a userdata contains a Java Function - * @param idx index of the lua stack - * @return boolean - */ - public boolean isJavaFunction(int idx) - { - return _isJavaFunction(luaState, idx); - } - - /** - * Pushes into the stack any object value.
- * This function checks if the object could be pushed as a lua type, if not - * pushes the java object. - * @param obj - */ - public void pushObjectValue(Object obj) throws LuaException - { - if (obj == null) - { - pushNil(); - } - else if (obj instanceof Boolean) - { - Boolean bool = (Boolean) obj; - pushBoolean(bool.booleanValue()); - } - else if (obj instanceof Number) - { - pushNumber(((Number) obj).doubleValue()); - } - else if (obj instanceof String) - { - pushString((String) obj); - } - else if (obj instanceof JavaFunction) - { - JavaFunction func = (JavaFunction) obj; - pushJavaFunction(func); - } - else if (obj instanceof LuaObject) - { - LuaObject ref = (LuaObject) obj; - ref.push(); - } - else if (obj instanceof byte[]) - { - pushString((byte[]) obj); - } - else - { - pushJavaObject(obj); - } - } - - /** - * Function that returns a Java Object equivalent to the one in the given - * position of the Lua Stack. - * @param idx Index in the Lua Stack - * @return Java object equivalent to the Lua one - */ - public synchronized Object toJavaObject( int idx ) throws LuaException - { - Object obj = null; - - if (isBoolean(idx)) - { - obj = new Boolean(toBoolean(idx)); - } - else if (type(idx) == LuaState.LUA_TSTRING.intValue()) - { - obj = toString(idx); - } - else if (isFunction(idx)) - { - obj = getLuaObject(idx); - } - else if (isTable(idx)) - { - obj = getLuaObject(idx); - } - else if (type(idx) == LuaState.LUA_TNUMBER.intValue()) - { - obj = new Double(toNumber(idx)); - } - else if (isUserdata(idx)) - { - if (isObject(idx)) - { - obj = getObjectFromUserdata(idx); - } - else - { - obj = getLuaObject(idx); - } - } - else if (isNil(idx)) - { - obj = null; - } - - return obj; - } - - /** - * Creates a reference to an object in the variable globalName - * @param globalName - * @return LuaObject - */ - public LuaObject getLuaObject(String globalName) - { - return new LuaObject(this, globalName); - } - - /** - * Creates a reference to an object inside another object - * @param parent The Lua Table or Userdata that contains the Field. - * @param name The name that index the field - * @return LuaObject - * @throws LuaException if parent is not a table or userdata - */ - public LuaObject getLuaObject(LuaObject parent, String name) - throws LuaException - { - if (parent.L.getCPtrPeer() != luaState.getPeer()) - throw new LuaException("Object must have the same LuaState as the parent!"); - - return new LuaObject(parent, name); - } - - /** - * This constructor creates a LuaObject from a table that is indexed by a number. - * @param parent The Lua Table or Userdata that contains the Field. - * @param name The name (number) that index the field - * @return LuaObject - * @throws LuaException When the parent object isn't a Table or Userdata - */ - public LuaObject getLuaObject(LuaObject parent, Number name) - throws LuaException - { - if (parent.L.getCPtrPeer() != luaState.getPeer()) - throw new LuaException("Object must have the same LuaState as the parent!"); - - return new LuaObject(parent, name); - } - - /** - * This constructor creates a LuaObject from a table that is indexed by any LuaObject. - * @param parent The Lua Table or Userdata that contains the Field. - * @param name The name (LuaObject) that index the field - * @return LuaObject - * @throws LuaException When the parent object isn't a Table or Userdata - */ - public LuaObject getLuaObject(LuaObject parent, LuaObject name) - throws LuaException - { - if (parent.getLuaState().getCPtrPeer() != luaState.getPeer() || - parent.getLuaState().getCPtrPeer() != name.getLuaState().getCPtrPeer()) - throw new LuaException("Object must have the same LuaState as the parent!"); - - return new LuaObject(parent, name); - } - - /** - * Creates a reference to an object in the index position - * of the stack - * @param index position on the stack - * @return LuaObject - */ - public LuaObject getLuaObject(int index) - { - return new LuaObject(this, index); - } - - /** - * When you call a function in lua, it may return a number, and the - * number will be interpreted as a Double.
- * This function converts the number into a type specified by - * retType - * @param db lua number to be converted - * @param retType type to convert to - * @return The converted number - */ - public static Number convertLuaNumber(Double db, Class retType) - { - // checks if retType is a primitive type - if (retType.isPrimitive()) - { - if (retType == Integer.TYPE) - { - return new Integer(db.intValue()); - } - else if (retType == Long.TYPE) - { - return new Long(db.longValue()); - } - else if (retType == Float.TYPE) - { - return new Float(db.floatValue()); - } - else if (retType == Double.TYPE) - { - return db; - } - else if (retType == Byte.TYPE) - { - return new Byte(db.byteValue()); - } - else if (retType == Short.TYPE) - { - return new Short(db.shortValue()); - } - } - else if (retType.isAssignableFrom(Number.class)) - { - // Checks all possibilities of number types - if (retType.isAssignableFrom(Integer.class)) - { - return new Integer(db.intValue()); - } - else if (retType.isAssignableFrom(Long.class)) - { - return new Long(db.longValue()); - } - else if (retType.isAssignableFrom(Float.class)) - { - return new Float(db.floatValue()); - } - else if (retType.isAssignableFrom(Double.class)) - { - return db; - } - else if (retType.isAssignableFrom(Byte.class)) - { - return new Byte(db.byteValue()); - } - else if (retType.isAssignableFrom(Short.class)) - { - return new Short(db.shortValue()); - } - } - - // if all checks fail, return null - return null; - } - - public String dumpStack() { - int n = getTop(); - StringBuilder sb = new StringBuilder(); - for (int i = 1; i <= n; i++) { - int t = type(i); - sb.append(i).append(": ").append(typeName(t)); - if (t == LUA_TNUMBER) - sb.append(" = ").append(toNumber(i)); - else if (t == LUA_TSTRING) - sb.append(" = '").append(toString(i)).append("'"); - sb.append("\n"); - } - return sb.toString(); - } -} +/* + * $Id: LuaState.java,v 1.9 2006/12/22 14:06:40 thiago Exp $ + * Copyright (C) 2003-2007 Kepler Project. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package org.keplerproject.luajava; + +/** + * LuaState if the main class of LuaJava for the Java developer. + * LuaState is a mapping of most of Lua's C API functions. + * LuaState also provides many other functions that will be used to manipulate + * objects between Lua and Java. + * @author Thiago Ponte + */ +public class LuaState +{ + private final static String LUAJAVA_LIB = "luajava"; + + final public static Integer LUA_GLOBALSINDEX = new Integer(-10002); + final public static Integer LUA_REGISTRYINDEX = new Integer(-10000); + + final public static Integer LUA_TNONE = new Integer(-1); + final public static Integer LUA_TNIL = new Integer(0); + final public static Integer LUA_TBOOLEAN = new Integer(1); + final public static Integer LUA_TLIGHTUSERDATA = new Integer(2); + final public static Integer LUA_TNUMBER = new Integer(3); + final public static Integer LUA_TSTRING = new Integer(4); + final public static Integer LUA_TTABLE = new Integer(5); + final public static Integer LUA_TFUNCTION = new Integer(6); + final public static Integer LUA_TUSERDATA = new Integer(7); + final public static Integer LUA_TTHREAD = new Integer(8); + + /** + * Specifies that an unspecified (multiple) number of return arguments + * will be returned by a call. + */ + final public static Integer LUA_MULTRET = new Integer(-1); + + /* + * error codes for `lua_load' and `lua_pcall' + */ + /** + * a runtime error. + */ + final public static Integer LUA_ERRRUN = new Integer(1); + + /** + * + */ + final public static Integer LUA_YIELD = new Integer(2); + + /** + * syntax error during pre-compilation. + */ + final public static Integer LUA_ERRSYNTAX = new Integer(3); + + /** + * memory allocation error. For such errors, Lua does not call + * the error handler function. + */ + final public static Integer LUA_ERRMEM = new Integer(4); + + /** + * error while running the error handler function. + */ + final public static Integer LUA_ERRERR = new Integer(5); + + /** + * Opens the library containing the luajava API + */ + static + { + System.loadLibrary(LUAJAVA_LIB); + } + + private CPtr luaState; + + private int stateId; + + /** + * Constructor to instance a new LuaState and initialize it with LuaJava's functions + * @param stateId + */ + protected LuaState(int stateId) + { + luaState = _open(); + luajava_open(luaState, stateId); + this.stateId = stateId; + } + + /** + * Receives a existing state and initializes it + * @param luaState + */ + protected LuaState(CPtr luaState) + { + this.luaState = luaState; + this.stateId = LuaStateFactory.insertLuaState(this); + luajava_open(luaState, stateId); + } + + /** + * Closes state and removes the object from the LuaStateFactory + */ + public synchronized void close() + { + LuaStateFactory.removeLuaState(stateId); + _close(luaState); + this.luaState = null; + } + + /** + * Returns true if state is closed. + */ + public synchronized boolean isClosed() + { + return luaState == null; + } + + /** + * Return the long representing the LuaState pointer + * @return long + */ + public long getCPtrPeer() + { + return (luaState != null)? luaState.getPeer() : 0; + } + + + /********************* Lua Native Interface *************************/ + + private synchronized native CPtr _open(); + private synchronized native void _close(CPtr ptr); + private synchronized native CPtr _newthread(CPtr ptr); + + // Stack manipulation + private synchronized native int _getTop(CPtr ptr); + private synchronized native void _setTop(CPtr ptr, int idx); + private synchronized native void _pushValue(CPtr ptr, int idx); + private synchronized native void _remove(CPtr ptr, int idx); + private synchronized native void _insert(CPtr ptr, int idx); + private synchronized native void _replace(CPtr ptr, int idx); + private synchronized native int _checkStack(CPtr ptr, int sz); + + private synchronized native void _xmove(CPtr from, CPtr to, int n); + + // Access functions + private synchronized native int _isNumber(CPtr ptr, int idx); + private synchronized native int _isString(CPtr ptr, int idx); + private synchronized native int _isCFunction(CPtr ptr, int idx); + private synchronized native int _isUserdata(CPtr ptr, int idx); + private synchronized native int _type(CPtr ptr, int idx); + private synchronized native String _typeName(CPtr ptr, int tp); + + private synchronized native int _equal(CPtr ptr, int idx1, int idx2); + private synchronized native int _rawequal(CPtr ptr, int idx1, int idx2); + private synchronized native int _lessthan(CPtr ptr, int idx1, int idx2); + + private synchronized native double _toNumber(CPtr ptr, int idx); + private synchronized native int _toInteger(CPtr ptr, int idx); + private synchronized native int _toBoolean(CPtr ptr, int idx); + private synchronized native String _toString(CPtr ptr, int idx); + private synchronized native int _objlen(CPtr ptr, int idx); + private synchronized native CPtr _toThread(CPtr ptr, int idx); + + // Push functions + private synchronized native void _pushNil(CPtr ptr); + private synchronized native void _pushNumber(CPtr ptr, double number); + private synchronized native void _pushInteger(CPtr ptr, int integer); + private synchronized native void _pushString(CPtr ptr, String str); + private synchronized native void _pushString(CPtr ptr, byte[] bytes, int n); + private synchronized native void _pushBoolean(CPtr ptr, int bool); + + // Get functions + private synchronized native void _getTable(CPtr ptr, int idx); + private synchronized native void _getField(CPtr ptr, int idx, String k); + private synchronized native void _rawGet(CPtr ptr, int idx); + private synchronized native void _rawGetI(CPtr ptr, int idx, int n); + private synchronized native void _createTable(CPtr ptr, int narr, int nrec); + private synchronized native int _getMetaTable(CPtr ptr, int idx); + private synchronized native void _getFEnv(CPtr ptr, int idx); + + // Set functions + private synchronized native void _setTable(CPtr ptr, int idx); + private synchronized native void _setField(CPtr ptr, int idx, String k); + private synchronized native void _rawSet(CPtr ptr, int idx); + private synchronized native void _rawSetI(CPtr ptr, int idx, int n); + private synchronized native int _setMetaTable(CPtr ptr, int idx); + private synchronized native int _setFEnv(CPtr ptr, int idx); + + private synchronized native void _call(CPtr ptr, int nArgs, int nResults); + private synchronized native int _pcall(CPtr ptr, int nArgs, int Results, int errFunc); + + // Coroutine Functions + private synchronized native int _yield(CPtr ptr, int nResults); + private synchronized native int _resume(CPtr ptr, int nargs); + private synchronized native int _status(CPtr ptr); + + // Gargabe Collection Functions + final public static Integer LUA_GCSTOP = new Integer(0); + final public static Integer LUA_GCRESTART = new Integer(1); + final public static Integer LUA_GCCOLLECT = new Integer(2); + final public static Integer LUA_GCCOUNT = new Integer(3); + final public static Integer LUA_GCCOUNTB = new Integer(4); + final public static Integer LUA_GCSTEP = new Integer(5); + final public static Integer LUA_GCSETPAUSE = new Integer(6); + final public static Integer LUA_GCSETSTEPMUL = new Integer(7); + private synchronized native int _gc(CPtr ptr, int what, int data); + + // Miscellaneous Functions + private synchronized native int _error(CPtr ptr); + private synchronized native int _next(CPtr ptr, int idx); + private synchronized native void _concat(CPtr ptr, int n); + + // Some macros + private synchronized native void _pop(CPtr ptr, int n); + private synchronized native void _newTable(CPtr ptr); + private synchronized native int _strlen(CPtr ptr, int idx); + private synchronized native int _isFunction(CPtr ptr, int idx); + private synchronized native int _isTable(CPtr ptr, int idx); + private synchronized native int _isNil(CPtr ptr, int idx); + private synchronized native int _isBoolean(CPtr ptr, int idx); + private synchronized native int _isThread(CPtr ptr, int idx); + private synchronized native int _isNone(CPtr ptr, int idx); + private synchronized native int _isNoneOrNil(CPtr ptr, int idx); + + private synchronized native void _setGlobal(CPtr ptr, String name); + private synchronized native void _getGlobal(CPtr ptr, String name); + + private synchronized native int _getGcCount(CPtr ptr); + + + // LuaLibAux + private synchronized native int _LdoFile(CPtr ptr, String fileName); + private synchronized native int _LdoString(CPtr ptr, String string); + //private synchronized native int _doBuffer(CPtr ptr, byte[] buff, long sz, String n); + + private synchronized native int _LgetMetaField(CPtr ptr, int obj, String e); + private synchronized native int _LcallMeta(CPtr ptr, int obj, String e); + private synchronized native int _Ltyperror(CPtr ptr, int nArg, String tName); + private synchronized native int _LargError(CPtr ptr, int numArg, String extraMsg); + private synchronized native String _LcheckString(CPtr ptr, int numArg); + private synchronized native String _LoptString(CPtr ptr, int numArg, String def); + private synchronized native double _LcheckNumber(CPtr ptr, int numArg); + private synchronized native double _LoptNumber(CPtr ptr, int numArg, double def); + + private synchronized native int _LcheckInteger(CPtr ptr, int numArg); + private synchronized native int _LoptInteger(CPtr ptr, int numArg, int def); + + private synchronized native void _LcheckStack(CPtr ptr, int sz, String msg); + private synchronized native void _LcheckType(CPtr ptr, int nArg, int t); + private synchronized native void _LcheckAny(CPtr ptr, int nArg); + + private synchronized native int _LnewMetatable(CPtr ptr, String tName); + private synchronized native void _LgetMetatable(CPtr ptr, String tName); + + private synchronized native void _Lwhere(CPtr ptr, int lvl); + + private synchronized native int _Lref(CPtr ptr, int t); + private synchronized native void _LunRef(CPtr ptr, int t, int ref); + + private synchronized native int _LgetN(CPtr ptr, int t); + private synchronized native void _LsetN(CPtr ptr, int t, int n); + + private synchronized native int _LloadFile(CPtr ptr, String fileName); + private synchronized native int _LloadBuffer(CPtr ptr, byte[] buff, long sz, String name); + private synchronized native int _LloadString(CPtr ptr, String s); + + private synchronized native String _Lgsub(CPtr ptr, String s, String p, String r); + private synchronized native String _LfindTable(CPtr ptr, int idx, String fname, int szhint); + + + private synchronized native void _openBase(CPtr ptr); + private synchronized native void _openTable(CPtr ptr); + private synchronized native void _openIo(CPtr ptr); + private synchronized native void _openOs(CPtr ptr); + private synchronized native void _openString(CPtr ptr); + private synchronized native void _openMath(CPtr ptr); + private synchronized native void _openDebug(CPtr ptr); + private synchronized native void _openPackage(CPtr ptr); + private synchronized native void _openLibs(CPtr ptr); + + // Java Interface ----------------------------------------------------- + + public LuaState newThread() + { + LuaState l = new LuaState(_newthread(luaState)); + LuaStateFactory.insertLuaState(l); + return l; + } + + // STACK MANIPULATION + + public int getTop() + { + return _getTop(luaState); + } + + public void setTop(int idx) + { + _setTop(luaState, idx); + } + + public void pushValue(int idx) + { + _pushValue(luaState, idx); + } + + public void remove(int idx) + { + _remove(luaState, idx); + } + + public void insert(int idx) + { + _insert(luaState, idx); + } + + public void replace(int idx) + { + _replace(luaState, idx); + } + + public int checkStack(int sz) + { + return _checkStack(luaState, sz); + } + + public void xmove(LuaState to, int n) + { + _xmove(luaState, to.luaState, n); + } + + // ACCESS FUNCTION + + public boolean isNumber(int idx) + { + return (_isNumber(luaState, idx)!=0); + } + + public boolean isString(int idx) + { + return (_isString(luaState, idx)!=0); + } + + public boolean isFunction(int idx) + { + return (_isFunction(luaState, idx)!=0); + } + + public boolean isCFunction(int idx) + { + return (_isCFunction(luaState, idx)!=0); + } + + public boolean isUserdata(int idx) + { + return (_isUserdata(luaState, idx)!=0); + } + + public boolean isTable(int idx) + { + return (_isTable(luaState, idx)!=0); + } + + public boolean isBoolean(int idx) + { + return (_isBoolean(luaState, idx)!=0); + } + + public boolean isNil(int idx) + { + return (_isNil(luaState, idx)!=0); + } + + public boolean isThread(int idx) + { + return (_isThread(luaState, idx)!=0); + } + + public boolean isNone(int idx) + { + return (_isNone(luaState, idx)!=0); + } + + public boolean isNoneOrNil(int idx) + { + return (_isNoneOrNil(luaState, idx)!=0); + } + + public int type(int idx) + { + return _type(luaState, idx); + } + + public String typeName(int tp) + { + return _typeName(luaState, tp); + } + + public int equal(int idx1, int idx2) + { + return _equal(luaState, idx1, idx2); + } + + public int rawequal(int idx1, int idx2) + { + return _rawequal(luaState, idx1, idx2); + } + + public int lessthan(int idx1, int idx2) + { + return _lessthan(luaState, idx1, idx2); + } + + public double toNumber(int idx) + { + return _toNumber(luaState, idx); + } + + public int toInteger(int idx) + { + return _toInteger(luaState, idx); + } + + public boolean toBoolean(int idx) + { + return (_toBoolean(luaState, idx)!=0); + } + + public String toString(int idx) + { + return _toString(luaState, idx); + } + + public int strLen(int idx) + { + return _strlen(luaState, idx); + } + + public int objLen(int idx) + { + return _objlen(luaState, idx); + } + + public LuaState toThread(int idx) + { + return new LuaState(_toThread(luaState, idx)); + } + + //PUSH FUNCTIONS + + public void pushNil() + { + _pushNil(luaState); + } + + public void pushNumber(double db) + { + _pushNumber(luaState, db); + } + + public void pushInteger(int integer) + { + _pushInteger(luaState, integer); + } + + public void pushString(String str) + { + if (str == null) + _pushNil(luaState); + else + _pushString(luaState, str); + } + + public void pushString(byte[] bytes) + { + if (bytes == null) + _pushNil(luaState); + else + _pushString(luaState, bytes, bytes.length); + } + + public void pushBoolean(boolean bool) + { + _pushBoolean(luaState, bool ? 1 : 0); + } + + // GET FUNCTIONS + + public void getTable(int idx) + { + _getTable(luaState, idx); + } + + public void getField(int idx, String k) + { + _getField(luaState, idx, k); + } + + public void rawGet(int idx) + { + _rawGet(luaState, idx); + } + + public void rawGetI(int idx, int n) + { + _rawGetI(luaState, idx, n); + } + + public void createTable(int narr, int nrec) + { + _createTable(luaState, narr, nrec); + } + + public void newTable() + { + _newTable(luaState); + } + + // if returns 0, there is no metatable + public int getMetaTable(int idx) + { + return _getMetaTable(luaState, idx); + } + + public void getFEnv(int idx) + { + _getFEnv(luaState, idx); + } + + // SET FUNCTIONS + + public void setTable(int idx) + { + _setTable(luaState, idx); + } + + public void setField(int idx, String k) + { + _setField(luaState, idx, k); + } + + public void rawSet(int idx) + { + _rawSet(luaState, idx); + } + + public void rawSetI(int idx, int n) + { + _rawSetI(luaState, idx, n); + } + + // if returns 0, cannot set the metatable to the given object + public int setMetaTable(int idx) + { + return _setMetaTable(luaState, idx); + } + + // if object is not a function returns 0 + public int setFEnv(int idx) + { + return _setFEnv(luaState, idx); + } + + public void call(int nArgs, int nResults) + { + _call(luaState, nArgs, nResults); + } + + // returns 0 if ok of one of the error codes defined + public int pcall(int nArgs, int nResults, int errFunc) + { + return _pcall(luaState, nArgs, nResults, errFunc); + } + + public int yield(int nResults) + { + return _yield(luaState, nResults); + } + + public int resume(int nArgs) + { + return _resume(luaState, nArgs); + } + + public int status() + { + return _status(luaState); + } + + public int gc(int what, int data) + { + return _gc(luaState, what, data); + } + + public int getGcCount() + { + return _getGcCount(luaState); + } + + public int next(int idx) + { + return _next(luaState, idx); + } + + public int error() + { + return _error(luaState); + } + + public void concat(int n) + { + _concat(luaState, n); + } + + + // FUNCTION FROM lauxlib + // returns 0 if ok + public int LdoFile(String fileName) + { + return _LdoFile(luaState, fileName); + } + + // returns 0 if ok + public int LdoString(String str) + { + return _LdoString(luaState, str); + } + + public int LgetMetaField(int obj, String e) + { + return _LgetMetaField(luaState, obj, e); + } + + public int LcallMeta(int obj, String e) + { + return _LcallMeta(luaState, obj, e); + } + + public int Ltyperror(int nArg, String tName) + { + return _Ltyperror(luaState, nArg, tName); + } + + public int LargError(int numArg, String extraMsg) + { + return _LargError(luaState, numArg, extraMsg); + } + + public String LcheckString(int numArg) + { + return _LcheckString(luaState, numArg); + } + + public String LoptString(int numArg, String def) + { + return _LoptString(luaState, numArg, def); + } + + public double LcheckNumber(int numArg) + { + return _LcheckNumber(luaState, numArg); + } + + public double LoptNumber(int numArg, double def) + { + return _LoptNumber(luaState, numArg, def); + } + + public int LcheckInteger(int numArg) + { + return _LcheckInteger(luaState, numArg); + } + + public int LoptInteger(int numArg, int def) + { + return _LoptInteger(luaState, numArg, def); + } + + public void LcheckStack(int sz, String msg) + { + _LcheckStack(luaState, sz, msg); + } + + public void LcheckType(int nArg, int t) + { + _LcheckType(luaState, nArg, t); + } + + public void LcheckAny(int nArg) + { + _LcheckAny(luaState, nArg); + } + + public int LnewMetatable(String tName) + { + return _LnewMetatable(luaState, tName); + } + + public void LgetMetatable(String tName) + { + _LgetMetatable(luaState, tName); + } + + public void Lwhere(int lvl) + { + _Lwhere(luaState, lvl); + } + + public int Lref(int t) + { + return _Lref(luaState, t); + } + + public void LunRef(int t, int ref) + { + _LunRef(luaState, t, ref); + } + + public int LgetN(int t) + { + return _LgetN(luaState, t); + } + + public void LsetN(int t, int n) + { + _LsetN(luaState, t, n); + } + + public int LloadFile(String fileName) + { + return _LloadFile(luaState, fileName); + } + + public int LloadString(String s) + { + return _LloadString(luaState, s); + } + + public int LloadBuffer(byte[] buff, String name) + { + return _LloadBuffer(luaState, buff, buff.length, name); + } + + public String Lgsub(String s, String p, String r) + { + return _Lgsub(luaState, s, p, r); + } + + public String LfindTable(int idx, String fname, int szhint) + { + return _LfindTable(luaState, idx, fname, szhint); + } + + //IMPLEMENTED C MACROS + + public void pop(int n) + { + //setTop(- (n) - 1); + _pop(luaState, n); + } + + public synchronized void getGlobal(String global) + { +// pushString(global); +// getTable(LUA_GLOBALSINDEX.intValue()); + _getGlobal(luaState, global); + } + + public synchronized void setGlobal(String name) + { + //pushString(name); + //insert(-2); + //setTable(LUA_GLOBALSINDEX.intValue()); + _setGlobal(luaState, name); + } + + // Functions to open lua libraries + public void openBase() + { + _openBase(luaState); + } + public void openTable() + { + _openTable(luaState); + } + public void openIo() + { + _openIo(luaState); + } + public void openOs() + { + _openOs(luaState); + } + public void openString() + { + _openString(luaState); + } + public void openMath() + { + _openMath(luaState); + } + public void openDebug() + { + _openDebug(luaState); + } + public void openPackage() + { + _openPackage(luaState); + } + public void openLibs() + { + _openLibs(luaState); + } + + + /********************** Luajava API Library **********************/ + + /** + * Initializes lua State to be used by luajava + * @param cptr + * @param stateId + */ + private synchronized native void luajava_open(CPtr cptr, int stateId); + /** + * Gets a Object from a userdata + * @param L + * @param idx index of the lua stack + * @return Object + */ + private synchronized native Object _getObjectFromUserdata(CPtr L, int idx) throws LuaException; + + /** + * Returns whether a userdata contains a Java Object + * @param L + * @param idx index of the lua stack + * @return boolean + */ + private synchronized native boolean _isObject(CPtr L, int idx); + + /** + * Pushes a Java Object into the state stack + * @param L + * @param obj + */ + private synchronized native void _pushJavaObject(CPtr L, Object obj); + + /** + * Pushes a JavaFunction into the state stack + * @param L + * @param func + */ + private synchronized native void _pushJavaFunction(CPtr L, JavaFunction func) throws LuaException; + + /** + * Returns whether a userdata contains a Java Function + * @param L + * @param idx index of the lua stack + * @return boolean + */ + private synchronized native boolean _isJavaFunction(CPtr L, int idx); + + /** + * Gets a Object from Lua + * @param idx index of the lua stack + * @return Object + * @throws LuaException if the lua object does not represent a java object. + */ + public Object getObjectFromUserdata(int idx) throws LuaException + { + return _getObjectFromUserdata(luaState, idx); + } + + /** + * Tells whether a lua index contains a java Object + * @param idx index of the lua stack + * @return boolean + */ + public boolean isObject(int idx) + { + return _isObject(luaState, idx); + } + + /** + * Pushes a Java Object into the lua stack.
+ * This function does not check if the object is from a class that could + * be represented by a lua type. Eg: java.lang.String could be a lua string. + * @param obj Object to be pushed into lua + */ + public void pushJavaObject(Object obj) + { + _pushJavaObject(luaState, obj); + } + + /** + * Pushes a JavaFunction into the state stack + * @param func + */ + public void pushJavaFunction(JavaFunction func) throws LuaException + { + _pushJavaFunction(luaState, func); + } + + /** + * Returns whether a userdata contains a Java Function + * @param idx index of the lua stack + * @return boolean + */ + public boolean isJavaFunction(int idx) + { + return _isJavaFunction(luaState, idx); + } + + /** + * Pushes into the stack any object value.
+ * This function checks if the object could be pushed as a lua type, if not + * pushes the java object. + * @param obj + */ + public void pushObjectValue(Object obj) throws LuaException + { + if (obj == null) + { + pushNil(); + } + else if (obj instanceof Boolean) + { + Boolean bool = (Boolean) obj; + pushBoolean(bool.booleanValue()); + } + else if (obj instanceof Number) + { + pushNumber(((Number) obj).doubleValue()); + } + else if (obj instanceof String) + { + pushString((String) obj); + } + else if (obj instanceof JavaFunction) + { + JavaFunction func = (JavaFunction) obj; + pushJavaFunction(func); + } + else if (obj instanceof LuaObject) + { + LuaObject ref = (LuaObject) obj; + ref.push(); + } + else if (obj instanceof byte[]) + { + pushString((byte[]) obj); + } + else + { + pushJavaObject(obj); + } + } + + /** + * Function that returns a Java Object equivalent to the one in the given + * position of the Lua Stack. + * @param idx Index in the Lua Stack + * @return Java object equivalent to the Lua one + */ + public synchronized Object toJavaObject( int idx ) throws LuaException + { + Object obj = null; + + if (isBoolean(idx)) + { + obj = new Boolean(toBoolean(idx)); + } + else if (type(idx) == LuaState.LUA_TSTRING.intValue()) + { + obj = toString(idx); + } + else if (isFunction(idx)) + { + obj = getLuaObject(idx); + } + else if (isTable(idx)) + { + obj = getLuaObject(idx); + } + else if (type(idx) == LuaState.LUA_TNUMBER.intValue()) + { + obj = new Double(toNumber(idx)); + } + else if (isUserdata(idx)) + { + if (isObject(idx)) + { + obj = getObjectFromUserdata(idx); + } + else + { + obj = getLuaObject(idx); + } + } + else if (isNil(idx)) + { + obj = null; + } + + return obj; + } + + /** + * Creates a reference to an object in the variable globalName + * @param globalName + * @return LuaObject + */ + public LuaObject getLuaObject(String globalName) + { + return new LuaObject(this, globalName); + } + + /** + * Creates a reference to an object inside another object + * @param parent The Lua Table or Userdata that contains the Field. + * @param name The name that index the field + * @return LuaObject + * @throws LuaException if parent is not a table or userdata + */ + public LuaObject getLuaObject(LuaObject parent, String name) + throws LuaException + { + if (parent.L.getCPtrPeer() != luaState.getPeer()) + throw new LuaException("Object must have the same LuaState as the parent!"); + + return new LuaObject(parent, name); + } + + /** + * This constructor creates a LuaObject from a table that is indexed by a number. + * @param parent The Lua Table or Userdata that contains the Field. + * @param name The name (number) that index the field + * @return LuaObject + * @throws LuaException When the parent object isn't a Table or Userdata + */ + public LuaObject getLuaObject(LuaObject parent, Number name) + throws LuaException + { + if (parent.L.getCPtrPeer() != luaState.getPeer()) + throw new LuaException("Object must have the same LuaState as the parent!"); + + return new LuaObject(parent, name); + } + + /** + * This constructor creates a LuaObject from a table that is indexed by any LuaObject. + * @param parent The Lua Table or Userdata that contains the Field. + * @param name The name (LuaObject) that index the field + * @return LuaObject + * @throws LuaException When the parent object isn't a Table or Userdata + */ + public LuaObject getLuaObject(LuaObject parent, LuaObject name) + throws LuaException + { + if (parent.getLuaState().getCPtrPeer() != luaState.getPeer() || + parent.getLuaState().getCPtrPeer() != name.getLuaState().getCPtrPeer()) + throw new LuaException("Object must have the same LuaState as the parent!"); + + return new LuaObject(parent, name); + } + + /** + * Creates a reference to an object in the index position + * of the stack + * @param index position on the stack + * @return LuaObject + */ + public LuaObject getLuaObject(int index) + { + return new LuaObject(this, index); + } + + /** + * When you call a function in lua, it may return a number, and the + * number will be interpreted as a Double.
+ * This function converts the number into a type specified by + * retType + * @param db lua number to be converted + * @param retType type to convert to + * @return The converted number + */ + public static Number convertLuaNumber(Double db, Class retType) + { + // checks if retType is a primitive type + if (retType.isPrimitive()) + { + if (retType == Integer.TYPE) + { + return new Integer(db.intValue()); + } + else if (retType == Long.TYPE) + { + return new Long(db.longValue()); + } + else if (retType == Float.TYPE) + { + return new Float(db.floatValue()); + } + else if (retType == Double.TYPE) + { + return db; + } + else if (retType == Byte.TYPE) + { + return new Byte(db.byteValue()); + } + else if (retType == Short.TYPE) + { + return new Short(db.shortValue()); + } + } + else if (retType.isAssignableFrom(Number.class)) + { + // Checks all possibilities of number types + if (retType.isAssignableFrom(Integer.class)) + { + return new Integer(db.intValue()); + } + else if (retType.isAssignableFrom(Long.class)) + { + return new Long(db.longValue()); + } + else if (retType.isAssignableFrom(Float.class)) + { + return new Float(db.floatValue()); + } + else if (retType.isAssignableFrom(Double.class)) + { + return db; + } + else if (retType.isAssignableFrom(Byte.class)) + { + return new Byte(db.byteValue()); + } + else if (retType.isAssignableFrom(Short.class)) + { + return new Short(db.shortValue()); + } + } + + // if all checks fail, return null + return null; + } + + public String dumpStack() { + int n = getTop(); + StringBuilder sb = new StringBuilder(); + for (int i = 1; i <= n; i++) { + int t = type(i); + sb.append(i).append(": ").append(typeName(t)); + if (t == LUA_TNUMBER) + sb.append(" = ").append(toNumber(i)); + else if (t == LUA_TSTRING) + sb.append(" = '").append(toString(i)).append("'"); + sb.append("\n"); + } + return sb.toString(); + } +} diff --git a/src/org/keplerproject/luajava/LuaStateFactory.java b/app/src/main/java/org/keplerproject/luajava/LuaStateFactory.java old mode 100755 new mode 100644 similarity index 96% rename from src/org/keplerproject/luajava/LuaStateFactory.java rename to app/src/main/java/org/keplerproject/luajava/LuaStateFactory.java index 17b7835..92b9617 --- a/src/org/keplerproject/luajava/LuaStateFactory.java +++ b/app/src/main/java/org/keplerproject/luajava/LuaStateFactory.java @@ -1,123 +1,123 @@ -/* - * $Id: LuaStateFactory.java,v 1.4 2006/12/22 14:06:40 thiago Exp $ - * Copyright (C) 2003-2007 Kepler Project. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -package org.keplerproject.luajava; - -import java.util.ArrayList; -import java.util.List; - -/** - * This class is responsible for instantiating new LuaStates. - * When a new LuaState is instantiated it is put into a List - * and an index is returned. This index is registred in Lua - * and it is used to find the right LuaState when lua calls - * a Java Function. - * - * @author Thiago Ponte - */ -public final class LuaStateFactory -{ - /** - * Array with all luaState's instances - */ - private static final List states = new ArrayList(); - - /** - * Non-public constructor. - */ - private LuaStateFactory() - {} - - /** - * Method that creates a new instance of LuaState - * @return LuaState - */ - public synchronized static LuaState newLuaState() - { - int i = getNextStateIndex(); - LuaState L = new LuaState(i); - - states.add(i, L); - - return L; - } - - /** - * Returns a existing instance of LuaState - * @param index - * @return LuaState - */ - public synchronized static LuaState getExistingState(int index) - { - return (LuaState) states.get(index); - } - - /** - * Receives a existing LuaState and checks if it exists in the states list. - * If it doesn't exist adds it to the list. - * @param L - * @return int - */ - public synchronized static int insertLuaState(LuaState L) - { - int i; - for (i = 0 ; i < states.size() ; i++) - { - LuaState state = (LuaState) states.get(i); - - if (state != null) - { - if (state.getCPtrPeer() == L.getCPtrPeer()) - return i; - } - } - - i = getNextStateIndex(); - - states.set(i, L); - - return i; - } - - /** - * removes the luaState from the states list - * @param idx - */ - public synchronized static void removeLuaState(int idx) - { - states.add(idx, null); - } - - /** - * Get next available index - * @return int - */ - private synchronized static int getNextStateIndex() - { - int i; - for ( i=0 ; i < states.size() && states.get(i) != null ; i++ ); - - return i; - } +/* + * $Id: LuaStateFactory.java,v 1.4 2006/12/22 14:06:40 thiago Exp $ + * Copyright (C) 2003-2007 Kepler Project. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package org.keplerproject.luajava; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class is responsible for instantiating new LuaStates. + * When a new LuaState is instantiated it is put into a List + * and an index is returned. This index is registred in Lua + * and it is used to find the right LuaState when lua calls + * a Java Function. + * + * @author Thiago Ponte + */ +public final class LuaStateFactory +{ + /** + * Array with all luaState's instances + */ + private static final List states = new ArrayList(); + + /** + * Non-public constructor. + */ + private LuaStateFactory() + {} + + /** + * Method that creates a new instance of LuaState + * @return LuaState + */ + public synchronized static LuaState newLuaState() + { + int i = getNextStateIndex(); + LuaState L = new LuaState(i); + + states.add(i, L); + + return L; + } + + /** + * Returns a existing instance of LuaState + * @param index + * @return LuaState + */ + public synchronized static LuaState getExistingState(int index) + { + return (LuaState) states.get(index); + } + + /** + * Receives a existing LuaState and checks if it exists in the states list. + * If it doesn't exist adds it to the list. + * @param L + * @return int + */ + public synchronized static int insertLuaState(LuaState L) + { + int i; + for (i = 0 ; i < states.size() ; i++) + { + LuaState state = (LuaState) states.get(i); + + if (state != null) + { + if (state.getCPtrPeer() == L.getCPtrPeer()) + return i; + } + } + + i = getNextStateIndex(); + + states.set(i, L); + + return i; + } + + /** + * removes the luaState from the states list + * @param idx + */ + public synchronized static void removeLuaState(int idx) + { + states.add(idx, null); + } + + /** + * Get next available index + * @return int + */ + private synchronized static int getNextStateIndex() + { + int i; + for ( i=0 ; i < states.size() && states.get(i) != null ; i++ ); + + return i; + } } \ No newline at end of file diff --git a/src/sk/kottman/androlua/Main.java b/app/src/main/java/sk/kottman/androlua/Main.java similarity index 100% rename from src/sk/kottman/androlua/Main.java rename to app/src/main/java/sk/kottman/androlua/Main.java diff --git a/jni/Android.mk b/app/src/main/jni/Android.mk similarity index 100% rename from jni/Android.mk rename to app/src/main/jni/Android.mk diff --git a/jni/lua/Android.mk b/app/src/main/jni/lua/Android.mk similarity index 100% rename from jni/lua/Android.mk rename to app/src/main/jni/lua/Android.mk diff --git a/jni/lua/lapi.c b/app/src/main/jni/lua/lapi.c similarity index 100% rename from jni/lua/lapi.c rename to app/src/main/jni/lua/lapi.c diff --git a/jni/lua/lapi.h b/app/src/main/jni/lua/lapi.h similarity index 100% rename from jni/lua/lapi.h rename to app/src/main/jni/lua/lapi.h diff --git a/jni/lua/lauxlib.c b/app/src/main/jni/lua/lauxlib.c similarity index 100% rename from jni/lua/lauxlib.c rename to app/src/main/jni/lua/lauxlib.c diff --git a/jni/lua/lauxlib.h b/app/src/main/jni/lua/lauxlib.h similarity index 100% rename from jni/lua/lauxlib.h rename to app/src/main/jni/lua/lauxlib.h diff --git a/jni/lua/lbaselib.c b/app/src/main/jni/lua/lbaselib.c similarity index 100% rename from jni/lua/lbaselib.c rename to app/src/main/jni/lua/lbaselib.c diff --git a/jni/lua/lcode.c b/app/src/main/jni/lua/lcode.c similarity index 100% rename from jni/lua/lcode.c rename to app/src/main/jni/lua/lcode.c diff --git a/jni/lua/lcode.h b/app/src/main/jni/lua/lcode.h similarity index 100% rename from jni/lua/lcode.h rename to app/src/main/jni/lua/lcode.h diff --git a/jni/lua/ldblib.c b/app/src/main/jni/lua/ldblib.c similarity index 100% rename from jni/lua/ldblib.c rename to app/src/main/jni/lua/ldblib.c diff --git a/jni/lua/ldebug.c b/app/src/main/jni/lua/ldebug.c similarity index 100% rename from jni/lua/ldebug.c rename to app/src/main/jni/lua/ldebug.c diff --git a/jni/lua/ldebug.h b/app/src/main/jni/lua/ldebug.h similarity index 100% rename from jni/lua/ldebug.h rename to app/src/main/jni/lua/ldebug.h diff --git a/jni/lua/ldo.c b/app/src/main/jni/lua/ldo.c similarity index 100% rename from jni/lua/ldo.c rename to app/src/main/jni/lua/ldo.c diff --git a/jni/lua/ldo.h b/app/src/main/jni/lua/ldo.h similarity index 100% rename from jni/lua/ldo.h rename to app/src/main/jni/lua/ldo.h diff --git a/jni/lua/ldump.c b/app/src/main/jni/lua/ldump.c similarity index 100% rename from jni/lua/ldump.c rename to app/src/main/jni/lua/ldump.c diff --git a/jni/lua/lfunc.c b/app/src/main/jni/lua/lfunc.c similarity index 100% rename from jni/lua/lfunc.c rename to app/src/main/jni/lua/lfunc.c diff --git a/jni/lua/lfunc.h b/app/src/main/jni/lua/lfunc.h similarity index 100% rename from jni/lua/lfunc.h rename to app/src/main/jni/lua/lfunc.h diff --git a/jni/lua/lgc.c b/app/src/main/jni/lua/lgc.c similarity index 100% rename from jni/lua/lgc.c rename to app/src/main/jni/lua/lgc.c diff --git a/jni/lua/lgc.h b/app/src/main/jni/lua/lgc.h similarity index 100% rename from jni/lua/lgc.h rename to app/src/main/jni/lua/lgc.h diff --git a/jni/lua/linit.c b/app/src/main/jni/lua/linit.c similarity index 100% rename from jni/lua/linit.c rename to app/src/main/jni/lua/linit.c diff --git a/jni/lua/liolib.c b/app/src/main/jni/lua/liolib.c similarity index 100% rename from jni/lua/liolib.c rename to app/src/main/jni/lua/liolib.c diff --git a/jni/lua/llex.c b/app/src/main/jni/lua/llex.c similarity index 100% rename from jni/lua/llex.c rename to app/src/main/jni/lua/llex.c diff --git a/jni/lua/llex.h b/app/src/main/jni/lua/llex.h similarity index 100% rename from jni/lua/llex.h rename to app/src/main/jni/lua/llex.h diff --git a/jni/lua/llimits.h b/app/src/main/jni/lua/llimits.h similarity index 100% rename from jni/lua/llimits.h rename to app/src/main/jni/lua/llimits.h diff --git a/jni/lua/lmathlib.c b/app/src/main/jni/lua/lmathlib.c similarity index 100% rename from jni/lua/lmathlib.c rename to app/src/main/jni/lua/lmathlib.c diff --git a/jni/lua/lmem.c b/app/src/main/jni/lua/lmem.c similarity index 100% rename from jni/lua/lmem.c rename to app/src/main/jni/lua/lmem.c diff --git a/jni/lua/lmem.h b/app/src/main/jni/lua/lmem.h similarity index 100% rename from jni/lua/lmem.h rename to app/src/main/jni/lua/lmem.h diff --git a/jni/lua/loadlib.c b/app/src/main/jni/lua/loadlib.c similarity index 100% rename from jni/lua/loadlib.c rename to app/src/main/jni/lua/loadlib.c diff --git a/jni/lua/lobject.c b/app/src/main/jni/lua/lobject.c similarity index 100% rename from jni/lua/lobject.c rename to app/src/main/jni/lua/lobject.c diff --git a/jni/lua/lobject.h b/app/src/main/jni/lua/lobject.h similarity index 100% rename from jni/lua/lobject.h rename to app/src/main/jni/lua/lobject.h diff --git a/jni/lua/lopcodes.c b/app/src/main/jni/lua/lopcodes.c similarity index 100% rename from jni/lua/lopcodes.c rename to app/src/main/jni/lua/lopcodes.c diff --git a/jni/lua/lopcodes.h b/app/src/main/jni/lua/lopcodes.h similarity index 100% rename from jni/lua/lopcodes.h rename to app/src/main/jni/lua/lopcodes.h diff --git a/jni/lua/loslib.c b/app/src/main/jni/lua/loslib.c similarity index 100% rename from jni/lua/loslib.c rename to app/src/main/jni/lua/loslib.c diff --git a/jni/lua/lparser.c b/app/src/main/jni/lua/lparser.c similarity index 100% rename from jni/lua/lparser.c rename to app/src/main/jni/lua/lparser.c diff --git a/jni/lua/lparser.h b/app/src/main/jni/lua/lparser.h similarity index 100% rename from jni/lua/lparser.h rename to app/src/main/jni/lua/lparser.h diff --git a/jni/lua/lstate.c b/app/src/main/jni/lua/lstate.c similarity index 100% rename from jni/lua/lstate.c rename to app/src/main/jni/lua/lstate.c diff --git a/jni/lua/lstate.h b/app/src/main/jni/lua/lstate.h similarity index 100% rename from jni/lua/lstate.h rename to app/src/main/jni/lua/lstate.h diff --git a/jni/lua/lstring.c b/app/src/main/jni/lua/lstring.c similarity index 100% rename from jni/lua/lstring.c rename to app/src/main/jni/lua/lstring.c diff --git a/jni/lua/lstring.h b/app/src/main/jni/lua/lstring.h similarity index 100% rename from jni/lua/lstring.h rename to app/src/main/jni/lua/lstring.h diff --git a/jni/lua/lstrlib.c b/app/src/main/jni/lua/lstrlib.c similarity index 100% rename from jni/lua/lstrlib.c rename to app/src/main/jni/lua/lstrlib.c diff --git a/jni/lua/ltable.c b/app/src/main/jni/lua/ltable.c similarity index 100% rename from jni/lua/ltable.c rename to app/src/main/jni/lua/ltable.c diff --git a/jni/lua/ltable.h b/app/src/main/jni/lua/ltable.h similarity index 100% rename from jni/lua/ltable.h rename to app/src/main/jni/lua/ltable.h diff --git a/jni/lua/ltablib.c b/app/src/main/jni/lua/ltablib.c similarity index 100% rename from jni/lua/ltablib.c rename to app/src/main/jni/lua/ltablib.c diff --git a/jni/lua/ltm.c b/app/src/main/jni/lua/ltm.c similarity index 100% rename from jni/lua/ltm.c rename to app/src/main/jni/lua/ltm.c diff --git a/jni/lua/ltm.h b/app/src/main/jni/lua/ltm.h similarity index 100% rename from jni/lua/ltm.h rename to app/src/main/jni/lua/ltm.h diff --git a/jni/lua/lua.h b/app/src/main/jni/lua/lua.h similarity index 100% rename from jni/lua/lua.h rename to app/src/main/jni/lua/lua.h diff --git a/jni/lua/luaconf.h b/app/src/main/jni/lua/luaconf.h similarity index 100% rename from jni/lua/luaconf.h rename to app/src/main/jni/lua/luaconf.h diff --git a/jni/lua/lualib.h b/app/src/main/jni/lua/lualib.h similarity index 100% rename from jni/lua/lualib.h rename to app/src/main/jni/lua/lualib.h diff --git a/jni/lua/lundump.c b/app/src/main/jni/lua/lundump.c similarity index 100% rename from jni/lua/lundump.c rename to app/src/main/jni/lua/lundump.c diff --git a/jni/lua/lundump.h b/app/src/main/jni/lua/lundump.h similarity index 100% rename from jni/lua/lundump.h rename to app/src/main/jni/lua/lundump.h diff --git a/jni/lua/lvm.c b/app/src/main/jni/lua/lvm.c similarity index 100% rename from jni/lua/lvm.c rename to app/src/main/jni/lua/lvm.c diff --git a/jni/lua/lvm.h b/app/src/main/jni/lua/lvm.h similarity index 100% rename from jni/lua/lvm.h rename to app/src/main/jni/lua/lvm.h diff --git a/jni/lua/lzio.c b/app/src/main/jni/lua/lzio.c similarity index 100% rename from jni/lua/lzio.c rename to app/src/main/jni/lua/lzio.c diff --git a/jni/lua/lzio.h b/app/src/main/jni/lua/lzio.h similarity index 100% rename from jni/lua/lzio.h rename to app/src/main/jni/lua/lzio.h diff --git a/jni/luajava/Android.mk b/app/src/main/jni/luajava/Android.mk similarity index 100% rename from jni/luajava/Android.mk rename to app/src/main/jni/luajava/Android.mk diff --git a/jni/luajava/luajava.c b/app/src/main/jni/luajava/luajava.c old mode 100755 new mode 100644 similarity index 96% rename from jni/luajava/luajava.c rename to app/src/main/jni/luajava/luajava.c index e26d80c..c7639e5 --- a/jni/luajava/luajava.c +++ b/app/src/main/jni/luajava/luajava.c @@ -1,3405 +1,3405 @@ - -/****************************************************************************** -* $Id$ -* Copyright (C) 2003-2007 Kepler Project. -* -* Permission is hereby granted, free of charge, to any person obtaining -* a copy of this software and associated documentation files (the -* "Software"), to deal in the Software without restriction, including -* without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to -* permit persons to whom the Software is furnished to do so, subject to -* the following conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -******************************************************************************/ - -/*************************************************************************** -* -* $ED -* This module is the implementation of luajava's dinamic library. -* In this module lua's functions are exported to be used in java by jni, -* and also the functions that will be used and exported to lua so that -* Java Objects' functions can be called. -* -*****************************************************************************/ - -#include -#include -#include - -#include "lua.h" -#include "lualib.h" -#include "lauxlib.h" - - -/* Constant that is used to index the JNI Environment */ -#define LUAJAVAJNIENVTAG "__JNIEnv" -/* Defines wheter the metatable is of a java Object */ -#define LUAJAVAOBJECTIND "__IsJavaObject" -/* Defines the lua State Index Property Name */ -#define LUAJAVASTATEINDEX "LuaJavaStateIndex" -/* Index metamethod name */ -#define LUAINDEXMETAMETHODTAG "__index" -/* Garbage collector metamethod name */ -#define LUAGCMETAMETHODTAG "__gc" -/* Call metamethod name */ -#define LUACALLMETAMETHODTAG "__call" -/* Constant that defines where in the metatable should I place the function name */ -#define LUAJAVAOBJFUNCCALLED "__FunctionCalled" - - - -static jclass throwable_class = NULL; -static jmethodID get_message_method = NULL; -static jclass java_function_class = NULL; -static jmethodID java_function_method = NULL; -static jclass luajava_api_class = NULL; -static jclass java_lang_class = NULL; - - -/*************************************************************************** -* -* $FC Function objectIndex -* -* $ED Description -* Function to be called by the metamethod __index of the java object -* -* $EP Function Parameters -* $P L - lua State -* $P Stack - Parameters will be received by the stack -* -* $FV Returned Value -* int - Number of values to be returned by the function -* -*$. **********************************************************************/ - - static int objectIndex( lua_State * L ); - - -/*************************************************************************** -* -* $FC Function objectIndexReturn -* -* $ED Description -* Function returned by the metamethod __index of a java Object. It is -* the actual function that is going to call the java method. -* -* $EP Function Parameters -* $P L - lua State -* $P Stack - Parameters will be received by the stack -* -* $FV Returned Value -* int - Number of values to be returned by the function -* -*$. **********************************************************************/ - - static int objectIndexReturn( lua_State * L ); - - -/*************************************************************************** -* -* $FC Function classIndex -* -* $ED Description -* Function to be called by the metamethod __index of the java class -* -* $EP Function Parameters -* $P L - lua State -* $P Stack - Parameters will be received by the stack -* -* $FV Returned Value -* int - Number of values to be returned by the function -* -*$. **********************************************************************/ - - static int classIndex( lua_State * L ); - - -/*************************************************************************** -* -* $FC Function GC -* -* $ED Description -* Function to be called by the metamethod __gc of the java object -* -* $EP Function Parameters -* $P L - lua State -* $P Stack - Parameters will be received by the stack -* -* $FV Returned Value -* int - Number of values to be returned by the function -* -*$. **********************************************************************/ - - static int gc( lua_State * L ); - - -/*************************************************************************** -* -* $FC Function javaBindClass -* -* $ED Description -* Implementation of lua function luajava.BindClass -* -* $EP Function Parameters -* $P L - lua State -* -* $FV Returned Value -* int - Number of values to be returned by the function -* -*$. **********************************************************************/ - - static int javaBindClass( lua_State * L ); - -/*************************************************************************** -* -* $FC Function createProxy -* -* $ED Description -* Implementation of lua function luajava.createProxy. -* Transform a lua table into a java class that implements a list -* of interfaces -* -* $EP Function Parameters -* $P L - lua State -* $P Stack - Parameters will be received by the stack -* -* $FV Returned Value -* int - Number of values to be returned by the function -* -*$. **********************************************************************/ - - static int createProxy( lua_State * L ); - -/*************************************************************************** -* -* $FC Function javaNew -* -* $ED Description -* Implementation of lua function luajava.new -* -* $EP Function Parameters -* $P L - lua State -* $P Stack - Parameters will be received by the stack -* -* $FV Returned Value -* int - Number of values to be returned by the function -* -*$. **********************************************************************/ - - static int javaNew( lua_State * L ); - - -/*************************************************************************** -* -* $FC Function javaNewInstance -* -* $ED Description -* Implementation of lua function luajava.newInstance -* -* $EP Function Parameters -* $P L - lua State -* $P Stack - Parameters will be received by the stack -* -* $FV Returned Value -* int - Number of values to be returned by the function -* -*$. **********************************************************************/ - - static int javaNewInstance( lua_State * L ); - - -/*************************************************************************** -* -* $FC Function javaLoadLib -* -* $ED Description -* Implementation of lua function luajava.loadLib -* -* $EP Function Parameters -* $P L - lua State -* $P Stack - Parameters will be received by the stack -* -* $FV Returned Value -* int - Number of values to be returned by the function -* -*$. **********************************************************************/ - - static int javaLoadLib( lua_State * L ); - - -/*************************************************************************** -/* -* $FC pushJavaObject -* -* $ED Description -* Function to create a lua proxy to a java object -* -* $EP Function Parameters -* $P L - lua State -* $P javaObject - Java Object to be pushed on the stack -* -* $FV Returned Value -* int - Number of values to be returned by the function -* -*$. **********************************************************************/ - - static int pushJavaObject( lua_State * L , jobject javaObject ); - - -/*************************************************************************** -* -* $FC pushJavaClass -* -* $ED Description -* Function to create a lua proxy to a java class -* -* $EP Function Parameters -* $P L - lua State -* $P javaObject - Java Class to be pushed on the stack -* -* $FV Returned Value -* int - Number of values to be returned by the function -* -*$. **********************************************************************/ - - static int pushJavaClass( lua_State * L , jobject javaObject ); - - -/*************************************************************************** -* -* $FC isJavaObject -* -* $ED Description -* Returns 1 is given index represents a java object -* -* $EP Function Parameters -* $P L - lua State -* $P idx - index on the stack -* -* $FV Returned Value -* int - Boolean. -* -*$. **********************************************************************/ - - static int isJavaObject( lua_State * L , int idx ); - - -/*************************************************************************** -* -* $FC getStateFromCPtr -* -* $ED Description -* Returns the lua_State from the CPtr Java Object -* -* $EP Function Parameters -* $P L - lua State -* $P cptr - CPtr object -* -* $FV Returned Value -* int - Number of values to be returned by the function. -* -*$. **********************************************************************/ - - static lua_State * getStateFromCPtr( JNIEnv * env , jobject cptr ); - - -/*************************************************************************** -* -* $FC luaJavaFunctionCall -* -* $ED Description -* function called by metamethod __call of instances of JavaFunctionWrapper -* -* $EP Function Parameters -* $P L - lua State -* $P Stack - Parameters will be received by the stack -* -* $FV Returned Value -* int - Number of values to be returned by the function. -* -*$. **********************************************************************/ - - static int luaJavaFunctionCall( lua_State * L ); - - -/*************************************************************************** -* -* $FC pushJNIEnv -* -* $ED Description -* function that pushes the jni environment into the lua state -* -* $EP Function Parameters -* $P env - java environment -* $P L - lua State -* -* $FV Returned Value -* void -* -*$. **********************************************************************/ - - static void pushJNIEnv( JNIEnv * env , lua_State * L ); - - - /*************************************************************************** -* -* $FC getEnvFromState -* -* $ED Description -* auxiliar function to get the JNIEnv from the lua state -* -* $EP Function Parameters -* $P L - lua State -* -* $FV Returned Value -* JNIEnv * - JNI environment -* -*$. **********************************************************************/ - - static JNIEnv * getEnvFromState( lua_State * L ); - - -/********************* Implementations ***************************/ - -/*************************************************************************** -* -* Function: objectIndex -* ****/ - -int objectIndex( lua_State * L ) -{ - lua_Number stateIndex; - const char * key; - jmethodID method; - jint checkField; - jobject * obj; - jstring str; - jthrowable exp; - JNIEnv * javaEnv; - - /* Gets the luaState index */ - lua_pushstring( L , LUAJAVASTATEINDEX ); - lua_rawget( L , LUA_REGISTRYINDEX ); - - if ( !lua_isnumber( L , -1 ) ) - { - lua_pushstring( L , "Impossible to identify luaState id." ); - lua_error( L ); - } - - stateIndex = lua_tonumber( L , -1 ); - lua_pop( L , 1 ); - - if ( !lua_isstring( L , -1 ) ) - { - lua_pushstring( L , "Invalid Function call." ); - lua_error( L ); - } - - key = lua_tostring( L , -1 ); - - if ( !isJavaObject( L , 1 ) ) - { - lua_pushstring( L , "Not a valid Java Object." ); - lua_error( L ); - } - - javaEnv = getEnvFromState( L ); - if ( javaEnv == NULL ) - { - lua_pushstring( L , "Invalid JNI Environment." ); - lua_error( L ); - } - - obj = ( jobject * ) lua_touserdata( L , 1 ); - - method = ( *javaEnv )->GetStaticMethodID( javaEnv , luajava_api_class , "checkField" , - "(ILjava/lang/Object;Ljava/lang/String;)I" ); - - str = ( *javaEnv )->NewStringUTF( javaEnv , key ); - - checkField = ( *javaEnv )->CallStaticIntMethod( javaEnv , luajava_api_class , method , - (jint)stateIndex , *obj , str ); - - exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); - - /* Handles exception */ - if ( exp != NULL ) - { - jobject jstr; - const char * cStr; - - ( *javaEnv )->ExceptionClear( javaEnv ); - jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); - - ( *javaEnv )->DeleteLocalRef( javaEnv , str ); - - if ( jstr == NULL ) - { - jmethodID methodId; - - methodId = ( *javaEnv )->GetMethodID( javaEnv , throwable_class , "toString" , "()Ljava/lang/String;" ); - jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , methodId ); - } - - cStr = ( *javaEnv )->GetStringUTFChars( javaEnv , jstr , NULL ); - - lua_pushstring( L , cStr ); - - ( *javaEnv )->ReleaseStringUTFChars( javaEnv , jstr, cStr ); - - lua_error( L ); - } - - ( *javaEnv )->DeleteLocalRef( javaEnv , str ); - - if ( checkField != 0 ) - { - return checkField; - } - - lua_getmetatable( L , 1 ); - - if ( !lua_istable( L , -1 ) ) - { - lua_pushstring( L , "Invalid MetaTable." ); - lua_error( L ); - } - - lua_pushstring( L , LUAJAVAOBJFUNCCALLED ); - lua_pushstring( L , key ); - lua_rawset( L , -3 ); - - lua_pop( L , 1 ); - - lua_pushcfunction( L , &objectIndexReturn ); - - return 1; -} - - -/*************************************************************************** -* -* Function: objectIndexReturn -* ****/ - -int objectIndexReturn( lua_State * L ) -{ - lua_Number stateIndex; - jobject * pObject; - jmethodID method; - jthrowable exp; - const char * methodName; - jint ret; - jstring str; - JNIEnv * javaEnv; - - /* Gets the luaState index */ - lua_pushstring( L , LUAJAVASTATEINDEX ); - lua_rawget( L , LUA_REGISTRYINDEX ); - - if ( !lua_isnumber( L , -1 ) ) - { - lua_pushstring( L , "Impossible to identify luaState id." ); - lua_error( L ); - } - - stateIndex = lua_tonumber( L , -1 ); - lua_pop( L , 1 ); - - /* Checks if is a valid java object */ - if ( !isJavaObject( L , 1 ) ) - { - lua_pushstring( L , "Not a valid OO function call." ); - lua_error( L ); - } - - lua_getmetatable( L , 1 ); - if ( lua_type( L , -1 ) == LUA_TNIL ) - { - lua_pushstring( L , "Not a valid java Object." ); - lua_error( L ); - } - - lua_pushstring( L , LUAJAVAOBJECTIND ); - lua_rawget( L , -2 ); - if ( lua_type( L , -1 ) == LUA_TNIL ) - { - lua_pushstring( L , "Not a valid java Object." ); - lua_error( L ); - } - lua_pop( L , 1 ); - - /* Gets the method Name */ - lua_pushstring( L , LUAJAVAOBJFUNCCALLED ); - lua_rawget( L , -2 ); - if ( lua_type( L , -1 ) == LUA_TNIL ) - { - lua_pushstring( L , "Not a OO function call." ); - lua_error( L ); - } - methodName = lua_tostring( L , -1 ); - - lua_pop( L , 2 ); - - /* Gets the object reference */ - pObject = ( jobject* ) lua_touserdata( L , 1 ); - - /* Gets the JNI Environment */ - javaEnv = getEnvFromState( L ); - if ( javaEnv == NULL ) - { - lua_pushstring( L , "Invalid JNI Environment." ); - lua_error( L ); - } - - /* Gets method */ - method = ( *javaEnv )->GetStaticMethodID( javaEnv , luajava_api_class , "objectIndex" , - "(ILjava/lang/Object;Ljava/lang/String;)I" ); - - str = ( *javaEnv )->NewStringUTF( javaEnv , methodName ); - - ret = ( *javaEnv )->CallStaticIntMethod( javaEnv , luajava_api_class , method , (jint)stateIndex , - *pObject , str ); - - exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); - - /* Handles exception */ - if ( exp != NULL ) - { - jobject jstr; - const char * cStr; - - ( *javaEnv )->ExceptionClear( javaEnv ); - jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); - - ( *javaEnv )->DeleteLocalRef( javaEnv , str ); - - if ( jstr == NULL ) - { - jmethodID methodId; - - methodId = ( *javaEnv )->GetMethodID( javaEnv , throwable_class , "toString" , "()Ljava/lang/String;" ); - jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , methodId ); - } - - cStr = ( *javaEnv )->GetStringUTFChars( javaEnv , jstr , NULL ); - - lua_pushstring( L , cStr ); - - ( *javaEnv )->ReleaseStringUTFChars( javaEnv , jstr, cStr ); - - lua_error( L ); - } - - ( *javaEnv )->DeleteLocalRef( javaEnv , str ); - - /* pushes new object into lua stack */ - return ret; -} - - -/*************************************************************************** -* -* Function: classIndex -* ****/ - -int classIndex( lua_State * L ) -{ - lua_Number stateIndex; - jobject * obj; - jmethodID method; - const char * fieldName; - jstring str; - jint ret; - jthrowable exp; - JNIEnv * javaEnv; - - /* Gets the luaState index */ - lua_pushstring( L , LUAJAVASTATEINDEX ); - lua_rawget( L , LUA_REGISTRYINDEX ); - - if ( !lua_isnumber( L , -1 ) ) - { - lua_pushstring( L , "Impossible to identify luaState id." ); - lua_error( L ); - } - - stateIndex = lua_tonumber( L , -1 ); - lua_pop( L , 1 ); - - if ( !isJavaObject( L , 1 ) ) - { - lua_pushstring( L , "Not a valid java class." ); - lua_error( L ); - } - - /* Gets the field Name */ - - if ( !lua_isstring( L , 2 ) ) - { - lua_pushstring( L , "Not a valid field call." ); - lua_error( L ); - } - - fieldName = lua_tostring( L , 2 ); - - /* Gets the object reference */ - obj = ( jobject* ) lua_touserdata( L , 1 ); - - /* Gets the JNI Environment */ - javaEnv = getEnvFromState( L ); - if ( javaEnv == NULL ) - { - lua_pushstring( L , "Invalid JNI Environment." ); - lua_error( L ); - } - - method = ( *javaEnv )->GetStaticMethodID( javaEnv , luajava_api_class , "classIndex" , - "(ILjava/lang/Class;Ljava/lang/String;)I" ); - - str = ( *javaEnv )->NewStringUTF( javaEnv , fieldName ); - - /* Return 1 for field, 2 for method or 0 for error */ - ret = ( *javaEnv )->CallStaticIntMethod( javaEnv , luajava_api_class , method, (jint)stateIndex , - *obj , str ); - - exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); - - /* Handles exception */ - if ( exp != NULL ) - { - jobject jstr; - const char * cStr; - - ( *javaEnv )->ExceptionClear( javaEnv ); - jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); - - ( *javaEnv )->DeleteLocalRef( javaEnv , str ); - - if ( jstr == NULL ) - { - jmethodID methodId; - - methodId = ( *javaEnv )->GetMethodID( javaEnv , throwable_class , "toString" , "()Ljava/lang/String;" ); - jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , methodId ); - } - - cStr = ( *javaEnv )->GetStringUTFChars( javaEnv , jstr , NULL ); - - lua_pushstring( L , cStr ); - - ( *javaEnv )->ReleaseStringUTFChars( javaEnv , jstr, cStr ); - - lua_error( L ); - } - - ( *javaEnv )->DeleteLocalRef( javaEnv , str ); - - if ( ret == 0 ) - { - lua_pushstring( L , "Name is not a static field or function." ); - lua_error( L ); - } - - if ( ret == 2 ) - { - lua_getmetatable( L , 1 ); - lua_pushstring( L , LUAJAVAOBJFUNCCALLED ); - lua_pushstring( L , fieldName ); - lua_rawset( L , -3 ); - - lua_pop( L , 1 ); - - lua_pushcfunction( L , &objectIndexReturn ); - - return 1; - } - - return ret; -} - - -/*************************************************************************** -* -* Function: gc -* ****/ - -int gc( lua_State * L ) -{ - jobject * pObj; - JNIEnv * javaEnv; - - if ( !isJavaObject( L , 1 ) ) - { - return 0; - } - - pObj = ( jobject * ) lua_touserdata( L , 1 ); - - /* Gets the JNI Environment */ - javaEnv = getEnvFromState( L ); - if ( javaEnv == NULL ) - { - lua_pushstring( L , "Invalid JNI Environment." ); - lua_error( L ); - } - - ( *javaEnv )->DeleteGlobalRef( javaEnv , *pObj ); - - return 0; -} - - -/*************************************************************************** -* -* Function: javaBindClass -* ****/ - -int javaBindClass( lua_State * L ) -{ - int top; - jmethodID method; - const char * className; - jstring javaClassName; - jobject classInstance; - jthrowable exp; - JNIEnv * javaEnv; - - top = lua_gettop( L ); - - if ( top != 1 ) - { - luaL_error( L , "Error. Function javaBindClass received %d arguments, expected 1." , top ); - } - - /* Gets the JNI Environment */ - javaEnv = getEnvFromState( L ); - if ( javaEnv == NULL ) - { - lua_pushstring( L , "Invalid JNI Environment." ); - lua_error( L ); - } - - /* get the string parameter */ - if ( !lua_isstring( L , 1 ) ) - { - lua_pushstring( L , "Invalid parameter type. String expected." ); - lua_error( L ); - } - className = lua_tostring( L , 1 ); - - method = ( *javaEnv )->GetStaticMethodID( javaEnv , java_lang_class , "forName" , - "(Ljava/lang/String;)Ljava/lang/Class;" ); - - javaClassName = ( *javaEnv )->NewStringUTF( javaEnv , className ); - - classInstance = ( *javaEnv )->CallStaticObjectMethod( javaEnv , java_lang_class , - method , javaClassName ); - - exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); - - /* Handles exception */ - if ( exp != NULL ) - { - jobject jstr; - const char * cStr; - - ( *javaEnv )->ExceptionClear( javaEnv ); - jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); - - ( *javaEnv )->DeleteLocalRef( javaEnv , javaClassName ); - - if ( jstr == NULL ) - { - jmethodID methodId; - - methodId = ( *javaEnv )->GetMethodID( javaEnv , throwable_class , "toString" , "()Ljava/lang/String;" ); - jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , methodId ); - } - - cStr = ( *javaEnv )->GetStringUTFChars( javaEnv , jstr , NULL ); - - lua_pushstring( L , cStr ); - - ( *javaEnv )->ReleaseStringUTFChars( javaEnv , jstr, cStr ); - - lua_error( L ); - } - - ( *javaEnv )->DeleteLocalRef( javaEnv , javaClassName ); - - /* pushes new object into lua stack */ - - return pushJavaClass( L , classInstance ); -} - - -/*************************************************************************** -* -* Function: createProxy -* ****/ -int createProxy( lua_State * L ) -{ - jint ret; - lua_Number stateIndex; - const char * impl; - jmethodID method; - jthrowable exp; - jstring str; - JNIEnv * javaEnv; - - if ( lua_gettop( L ) != 2 ) - { - lua_pushstring( L , "Error. Function createProxy expects 2 arguments." ); - lua_error( L ); - } - - /* Gets the luaState index */ - lua_pushstring( L , LUAJAVASTATEINDEX ); - lua_rawget( L , LUA_REGISTRYINDEX ); - - if ( !lua_isnumber( L , -1 ) ) - { - lua_pushstring( L , "Impossible to identify luaState id." ); - lua_error( L ); - } - - stateIndex = lua_tonumber( L , -1 ); - lua_pop( L , 1 ); - - if ( !lua_isstring( L , 1 ) || !lua_istable( L , 2 ) ) - { - lua_pushstring( L , "Invalid Argument types. Expected (string, table)." ); - lua_error( L ); - } - - /* Gets the JNI Environment */ - javaEnv = getEnvFromState( L ); - if ( javaEnv == NULL ) - { - lua_pushstring( L , "Invalid JNI Environment." ); - lua_error( L ); - } - - method = ( *javaEnv )->GetStaticMethodID( javaEnv , luajava_api_class , "createProxyObject" , - "(ILjava/lang/String;)I" ); - - impl = lua_tostring( L , 1 ); - - str = ( *javaEnv )->NewStringUTF( javaEnv , impl ); - - ret = ( *javaEnv )->CallStaticIntMethod( javaEnv , luajava_api_class , method, (jint)stateIndex , str ); - - exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); - - /* Handles exception */ - if ( exp != NULL ) - { - jobject jstr; - const char * cStr; - - ( *javaEnv )->ExceptionClear( javaEnv ); - jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); - - ( *javaEnv )->DeleteLocalRef( javaEnv , str ); - - if ( jstr == NULL ) - { - jmethodID methodId; - - methodId = ( *javaEnv )->GetMethodID( javaEnv , throwable_class , "toString" , "()Ljava/lang/String;" ); - jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , methodId ); - } - - cStr = ( *javaEnv )->GetStringUTFChars( javaEnv , jstr , NULL ); - - lua_pushstring( L , cStr ); - - ( *javaEnv )->ReleaseStringUTFChars( javaEnv , jstr, cStr ); - - lua_error( L ); - } - - ( *javaEnv )->DeleteLocalRef( javaEnv , str ); - - return ret; -} - -/*************************************************************************** -* -* Function: javaNew -* ****/ - -int javaNew( lua_State * L ) -{ - int top; - jint ret; - jclass clazz; - jmethodID method; - jobject classInstance ; - jthrowable exp; - jobject * userData; - lua_Number stateIndex; - JNIEnv * javaEnv; - - top = lua_gettop( L ); - - if ( top == 0 ) - { - lua_pushstring( L , "Error. Invalid number of parameters." ); - lua_error( L ); - } - - /* Gets the luaState index */ - lua_pushstring( L , LUAJAVASTATEINDEX ); - lua_rawget( L , LUA_REGISTRYINDEX ); - - if ( !lua_isnumber( L , -1 ) ) - { - lua_pushstring( L , "Impossible to identify luaState id." ); - lua_error( L ); - } - - stateIndex = lua_tonumber( L , -1 ); - lua_pop( L , 1 ); - - /* Gets the java Class reference */ - if ( !isJavaObject( L , 1 ) ) - { - lua_pushstring( L , "Argument not a valid Java Class." ); - lua_error( L ); - } - - /* Gets the JNI Environment */ - javaEnv = getEnvFromState( L ); - if ( javaEnv == NULL ) - { - lua_pushstring( L , "Invalid JNI Environment." ); - lua_error( L ); - } - - clazz = ( *javaEnv )->FindClass( javaEnv , "java/lang/Class" ); - - userData = ( jobject * ) lua_touserdata( L , 1 ); - - classInstance = ( jobject ) *userData; - - if ( ( *javaEnv )->IsInstanceOf( javaEnv , classInstance , clazz ) == JNI_FALSE ) - { - lua_pushstring( L , "Argument not a valid Java Class." ); - lua_error( L ); - } - - method = ( *javaEnv )->GetStaticMethodID( javaEnv , luajava_api_class , "javaNew" , - "(ILjava/lang/Class;)I" ); - - if ( clazz == NULL || method == NULL ) - { - lua_pushstring( L , "Invalid method org.keplerproject.luajava.LuaJavaAPI.javaNew." ); - lua_error( L ); - } - - ret = ( *javaEnv )->CallStaticIntMethod( javaEnv , clazz , method , (jint)stateIndex , classInstance ); - - exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); - - /* Handles exception */ - if ( exp != NULL ) - { - jobject jstr; - const char * str; - - ( *javaEnv )->ExceptionClear( javaEnv ); - jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); - - if ( jstr == NULL ) - { - jmethodID methodId; - - methodId = ( *javaEnv )->GetMethodID( javaEnv , throwable_class , "toString" , "()Ljava/lang/String;" ); - jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , methodId ); - } - - str = ( *javaEnv )->GetStringUTFChars( javaEnv , jstr , NULL ); - - lua_pushstring( L , str ); - - ( *javaEnv )->ReleaseStringUTFChars( javaEnv , jstr, str ); - - lua_error( L ); - } - return ret; -} - - -/*************************************************************************** -* -* Function: javaNewInstance -* ****/ - -int javaNewInstance( lua_State * L ) -{ - jint ret; - jmethodID method; - const char * className; - jstring javaClassName; - jthrowable exp; - lua_Number stateIndex; - JNIEnv * javaEnv; - - /* Gets the luaState index */ - lua_pushstring( L , LUAJAVASTATEINDEX ); - lua_rawget( L , LUA_REGISTRYINDEX ); - - if ( !lua_isnumber( L , -1 ) ) - { - lua_pushstring( L , "Impossible to identify luaState id." ); - lua_error( L ); - } - - stateIndex = lua_tonumber( L , -1 ); - lua_pop( L , 1 ); - - /* get the string parameter */ - if ( !lua_isstring( L , 1 ) ) - { - lua_pushstring( L , "Invalid parameter type. String expected as first parameter." ); - lua_error( L ); - } - - className = lua_tostring( L , 1 ); - - /* Gets the JNI Environment */ - javaEnv = getEnvFromState( L ); - if ( javaEnv == NULL ) - { - lua_pushstring( L , "Invalid JNI Environment." ); - lua_error( L ); - } - - method = ( *javaEnv )->GetStaticMethodID( javaEnv , luajava_api_class , "javaNewInstance" , - "(ILjava/lang/String;)I" ); - - javaClassName = ( *javaEnv )->NewStringUTF( javaEnv , className ); - - ret = ( *javaEnv )->CallStaticIntMethod( javaEnv , luajava_api_class , method, (jint)stateIndex , - javaClassName ); - - exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); - - /* Handles exception */ - if ( exp != NULL ) - { - jobject jstr; - const char * str; - - ( *javaEnv )->ExceptionClear( javaEnv ); - jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); - - ( *javaEnv )->DeleteLocalRef( javaEnv , javaClassName ); - - if ( jstr == NULL ) - { - jmethodID methodId; - - methodId = ( *javaEnv )->GetMethodID( javaEnv , throwable_class , "toString" , "()Ljava/lang/String;" ); - jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , methodId ); - } - - str = ( *javaEnv )->GetStringUTFChars( javaEnv , jstr , NULL ); - - lua_pushstring( L , str ); - - ( *javaEnv )->ReleaseStringUTFChars( javaEnv , jstr, str ); - - lua_error( L ); - } - - ( *javaEnv )->DeleteLocalRef( javaEnv , javaClassName ); - - return ret; -} - - -/*************************************************************************** -* -* Function: javaLoadLib -* ****/ - -int javaLoadLib( lua_State * L ) -{ - jint ret; - int top; - const char * className, * methodName; - lua_Number stateIndex; - jmethodID method; - jthrowable exp; - jstring javaClassName , javaMethodName; - JNIEnv * javaEnv; - - top = lua_gettop( L ); - - if ( top != 2 ) - { - lua_pushstring( L , "Error. Invalid number of parameters." ); - lua_error( L ); - } - - /* Gets the luaState index */ - lua_pushstring( L , LUAJAVASTATEINDEX ); - lua_rawget( L , LUA_REGISTRYINDEX ); - - if ( !lua_isnumber( L , -1 ) ) - { - lua_pushstring( L , "Impossible to identify luaState id." ); - lua_error( L ); - } - - stateIndex = lua_tonumber( L , -1 ); - lua_pop( L , 1 ); - - - if ( !lua_isstring( L , 1 ) || !lua_isstring( L , 2 ) ) - { - lua_pushstring( L , "Invalid parameter. Strings expected." ); - lua_error( L ); - } - - className = lua_tostring( L , 1 ); - methodName = lua_tostring( L , 2 ); - - /* Gets the JNI Environment */ - javaEnv = getEnvFromState( L ); - if ( javaEnv == NULL ) - { - lua_pushstring( L , "Invalid JNI Environment." ); - lua_error( L ); - } - - method = ( *javaEnv )->GetStaticMethodID( javaEnv , luajava_api_class , "javaLoadLib" , - "(ILjava/lang/String;Ljava/lang/String;)I" ); - - javaClassName = ( *javaEnv )->NewStringUTF( javaEnv , className ); - javaMethodName = ( *javaEnv )->NewStringUTF( javaEnv , methodName ); - - ret = ( *javaEnv )->CallStaticIntMethod( javaEnv , luajava_api_class , method, (jint)stateIndex , - javaClassName , javaMethodName ); - - exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); - - /* Handles exception */ - if ( exp != NULL ) - { - jobject jstr; - const char * str; - - ( *javaEnv )->ExceptionClear( javaEnv ); - jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); - - ( *javaEnv )->DeleteLocalRef( javaEnv , javaClassName ); - ( *javaEnv )->DeleteLocalRef( javaEnv , javaMethodName ); - - if ( jstr == NULL ) - { - jmethodID methodId; - - methodId = ( *javaEnv )->GetMethodID( javaEnv , throwable_class , "toString" , "()Ljava/lang/String;" ); - jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , methodId ); - } - - str = ( *javaEnv )->GetStringUTFChars( javaEnv , jstr , NULL ); - - lua_pushstring( L , str ); - - ( *javaEnv )->ReleaseStringUTFChars( javaEnv , jstr, str ); - - lua_error( L ); - } - - ( *javaEnv )->DeleteLocalRef( javaEnv , javaClassName ); - ( *javaEnv )->DeleteLocalRef( javaEnv , javaMethodName ); - - return ret; -} - - -/*************************************************************************** -* -* Function: pushJavaClass -* ****/ - -int pushJavaClass( lua_State * L , jobject javaObject ) -{ - jobject * userData , globalRef; - - /* Gets the JNI Environment */ - JNIEnv * javaEnv = getEnvFromState( L ); - if ( javaEnv == NULL ) - { - lua_pushstring( L , "Invalid JNI Environment." ); - lua_error( L ); - } - - globalRef = ( *javaEnv )->NewGlobalRef( javaEnv , javaObject ); - - userData = ( jobject * ) lua_newuserdata( L , sizeof( jobject ) ); - *userData = globalRef; - - /* Creates metatable */ - lua_newtable( L ); - - /* pushes the __index metamethod */ - lua_pushstring( L , LUAINDEXMETAMETHODTAG ); - lua_pushcfunction( L , &classIndex ); - lua_rawset( L , -3 ); - - /* pushes the __gc metamethod */ - lua_pushstring( L , LUAGCMETAMETHODTAG ); - lua_pushcfunction( L , &gc ); - lua_rawset( L , -3 ); - - /* Is Java Object boolean */ - lua_pushstring( L , LUAJAVAOBJECTIND ); - lua_pushboolean( L , 1 ); - lua_rawset( L , -3 ); - - if ( lua_setmetatable( L , -2 ) == 0 ) - { - lua_pushstring( L , "Cannot create proxy to java class." ); - lua_error( L ); - } - - return 1; -} - - -/*************************************************************************** -* -* Function: pushJavaObject -* ****/ - -int pushJavaObject( lua_State * L , jobject javaObject ) -{ - jobject * userData , globalRef; - - /* Gets the JNI Environment */ - JNIEnv * javaEnv = getEnvFromState( L ); - if ( javaEnv == NULL ) - { - lua_pushstring( L , "Invalid JNI Environment." ); - lua_error( L ); - } - - globalRef = ( *javaEnv )->NewGlobalRef( javaEnv , javaObject ); - - userData = ( jobject * ) lua_newuserdata( L , sizeof( jobject ) ); - *userData = globalRef; - - /* Creates metatable */ - lua_newtable( L ); - - /* pushes the __index metamethod */ - lua_pushstring( L , LUAINDEXMETAMETHODTAG ); - lua_pushcfunction( L , &objectIndex ); - lua_rawset( L , -3 ); - - /* pushes the __gc metamethod */ - lua_pushstring( L , LUAGCMETAMETHODTAG ); - lua_pushcfunction( L , &gc ); - lua_rawset( L , -3 ); - - /* Is Java Object boolean */ - lua_pushstring( L , LUAJAVAOBJECTIND ); - lua_pushboolean( L , 1 ); - lua_rawset( L , -3 ); - - if ( lua_setmetatable( L , -2 ) == 0 ) - { - lua_pushstring( L , "Cannot create proxy to java object." ); - lua_error( L ); - } - - return 1; -} - - -/*************************************************************************** -* -* Function: isJavaObject -* ****/ - -int isJavaObject( lua_State * L , int idx ) -{ - if ( !lua_isuserdata( L , idx ) ) - return 0; - - if ( lua_getmetatable( L , idx ) == 0 ) - return 0; - - lua_pushstring( L , LUAJAVAOBJECTIND ); - lua_rawget( L , -2 ); - - if (lua_isnil( L, -1 )) - { - lua_pop( L , 2 ); - return 0; - } - lua_pop( L , 2 ); - return 1; -} - - -/*************************************************************************** -* -* Function: getStateFromCPtr -* ****/ - -lua_State * getStateFromCPtr( JNIEnv * env , jobject cptr ) -{ - lua_State * L; - - jclass classPtr = ( *env )->GetObjectClass( env , cptr ); - jfieldID CPtr_peer_ID = ( *env )->GetFieldID( env , classPtr , "peer" , "J" ); - jbyte * peer = ( jbyte * ) ( *env )->GetLongField( env , cptr , CPtr_peer_ID ); - - L = ( lua_State * ) peer; - - pushJNIEnv( env , L ); - - return L; -} - - -/*************************************************************************** -* -* Function: luaJavaFunctionCall -* ****/ - -int luaJavaFunctionCall( lua_State * L ) -{ - jobject * obj; - jthrowable exp; - int ret; - JNIEnv * javaEnv; - - if ( !isJavaObject( L , 1 ) ) - { - lua_pushstring( L , "Not a java Function." ); - lua_error( L ); - } - - obj = lua_touserdata( L , 1 ); - - /* Gets the JNI Environment */ - javaEnv = getEnvFromState( L ); - if ( javaEnv == NULL ) - { - lua_pushstring( L , "Invalid JNI Environment." ); - lua_error( L ); - } - - /* the Object must be an instance of the JavaFunction class */ - if ( ( *javaEnv )->IsInstanceOf( javaEnv , *obj , java_function_class ) == - JNI_FALSE ) - { - fprintf( stderr , "Called Java object is not a JavaFunction\n"); - return 0; - } - - ret = ( *javaEnv )->CallIntMethod( javaEnv , *obj , java_function_method ); - - exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); - - /* Handles exception */ - if ( exp != NULL ) - { - jobject jstr; - const char * str; - - ( *javaEnv )->ExceptionClear( javaEnv ); - jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); - - if ( jstr == NULL ) - { - jmethodID methodId; - - methodId = ( *javaEnv )->GetMethodID( javaEnv , throwable_class , "toString" , "()Ljava/lang/String;" ); - jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , methodId ); - } - - str = ( *javaEnv )->GetStringUTFChars( javaEnv , jstr , NULL ); - - lua_pushstring( L , str ); - - ( *javaEnv )->ReleaseStringUTFChars( javaEnv , jstr, str ); - - lua_error( L ); - } - return ret; -} - - -/*************************************************************************** -* -* Function: luaJavaFunctionCall -* ****/ - -JNIEnv * getEnvFromState( lua_State * L ) -{ - JNIEnv ** udEnv; - - lua_pushstring( L , LUAJAVAJNIENVTAG ); - lua_rawget( L , LUA_REGISTRYINDEX ); - - if ( !lua_isuserdata( L , -1 ) ) - { - lua_pop( L , 1 ); - return NULL; - } - - udEnv = ( JNIEnv ** ) lua_touserdata( L , -1 ); - - lua_pop( L , 1 ); - - return * udEnv; -} - - -/*************************************************************************** -* -* Function: pushJNIEnv -* ****/ - -void pushJNIEnv( JNIEnv * env , lua_State * L ) -{ - JNIEnv ** udEnv; - - lua_pushstring( L , LUAJAVAJNIENVTAG ); - lua_rawget( L , LUA_REGISTRYINDEX ); - - if ( !lua_isnil( L , -1 ) ) - { - udEnv = ( JNIEnv ** ) lua_touserdata( L , -1 ); - *udEnv = env; - lua_pop( L , 1 ); - } - else - { - lua_pop( L , 1 ); - udEnv = ( JNIEnv ** ) lua_newuserdata( L , sizeof( JNIEnv * ) ); - *udEnv = env; - - lua_pushstring( L , LUAJAVAJNIENVTAG ); - lua_insert( L , -2 ); - lua_rawset( L , LUA_REGISTRYINDEX ); - } -} - -/* -** Assumes the table is on top of the stack. -*/ -static void set_info (lua_State *L) { - lua_pushliteral (L, "_COPYRIGHT"); - lua_pushliteral (L, "Copyright (C) 2003-2007 Kepler Project"); - lua_settable (L, -3); - lua_pushliteral (L, "_DESCRIPTION"); - lua_pushliteral (L, "LuaJava is a script tool for Java"); - lua_settable (L, -3); - lua_pushliteral (L, "_NAME"); - lua_pushliteral (L, "LuaJava"); - lua_settable (L, -3); - lua_pushliteral (L, "_VERSION"); - lua_pushliteral (L, "1.1"); - lua_settable (L, -3); -} - -/**************************** JNI FUNCTIONS ****************************/ - -/************************************************************************ -* JNI Called function -* LuaJava API Functin -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState_luajava_1open - ( JNIEnv * env , jobject jobj , jobject cptr , jint stateId ) -{ - lua_State* L; - - jclass tempClass; - - L = getStateFromCPtr( env , cptr ); - - lua_pushstring( L , LUAJAVASTATEINDEX ); - lua_pushnumber( L , (lua_Number)stateId ); - lua_settable( L , LUA_REGISTRYINDEX ); - - - lua_newtable( L ); - - lua_setglobal( L , "luajava" ); - - lua_getglobal( L , "luajava" ); - - set_info( L); - - lua_pushstring( L , "bindClass" ); - lua_pushcfunction( L , &javaBindClass ); - lua_settable( L , -3 ); - - lua_pushstring( L , "new" ); - lua_pushcfunction( L , &javaNew ); - lua_settable( L , -3 ); - - lua_pushstring( L , "newInstance" ); - lua_pushcfunction( L , &javaNewInstance ); - lua_settable( L , -3 ); - - lua_pushstring( L , "loadLib" ); - lua_pushcfunction( L , &javaLoadLib ); - lua_settable( L , -3 ); - - lua_pushstring( L , "createProxy" ); - lua_pushcfunction( L , &createProxy ); - lua_settable( L , -3 ); - - lua_pop( L , 1 ); - - if ( luajava_api_class == NULL ) - { - tempClass = ( *env )->FindClass( env , "org/keplerproject/luajava/LuaJavaAPI" ); - - if ( tempClass == NULL ) - { - fprintf( stderr , "Could not find LuaJavaAPI class\n" ); - exit( 1 ); - } - - if ( ( luajava_api_class = ( *env )->NewGlobalRef( env , tempClass ) ) == NULL ) - { - fprintf( stderr , "Could not bind to LuaJavaAPI class\n" ); - exit( 1 ); - } - } - - if ( java_function_class == NULL ) - { - tempClass = ( *env )->FindClass( env , "org/keplerproject/luajava/JavaFunction" ); - - if ( tempClass == NULL ) - { - fprintf( stderr , "Could not find JavaFunction interface\n" ); - exit( 1 ); - } - - if ( ( java_function_class = ( *env )->NewGlobalRef( env , tempClass ) ) == NULL ) - { - fprintf( stderr , "Could not bind to JavaFunction interface\n" ); - exit( 1 ); - } - } - - if ( java_function_method == NULL ) - { - java_function_method = ( *env )->GetMethodID( env , java_function_class , "execute" , "()I"); - if ( !java_function_method ) - { - fprintf( stderr , "Could not find method in JavaFunction\n" ); - exit( 1 ); - } - } - - if ( throwable_class == NULL ) - { - tempClass = ( *env )->FindClass( env , "java/lang/Throwable" ); - - if ( tempClass == NULL ) - { - fprintf( stderr , "Error. Couldn't bind java class java.lang.Throwable\n" ); - exit( 1 ); - } - - throwable_class = ( *env )->NewGlobalRef( env , tempClass ); - - if ( throwable_class == NULL ) - { - fprintf( stderr , "Error. Couldn't bind java class java.lang.Throwable\n" ); - exit( 1 ); - } - } - - if ( get_message_method == NULL ) - { - get_message_method = ( *env )->GetMethodID( env , throwable_class , "getMessage" , - "()Ljava/lang/String;" ); - - if ( get_message_method == NULL ) - { - fprintf(stderr, "Could not find method in java.lang.Throwable\n"); - exit(1); - } - } - - if ( java_lang_class == NULL ) - { - tempClass = ( *env )->FindClass( env , "java/lang/Class" ); - - if ( tempClass == NULL ) - { - fprintf( stderr , "Error. Coundn't bind java class java.lang.Class\n" ); - exit( 1 ); - } - - java_lang_class = ( *env )->NewGlobalRef( env , tempClass ); - - if ( java_lang_class == NULL ) - { - fprintf( stderr , "Error. Couldn't bind java class java.lang.Throwable\n" ); - exit( 1 ); - } - } - - pushJNIEnv( env , L ); -} - -/************************************************************************ -* JNI Called function -* LuaJava API Functin -************************************************************************/ - -JNIEXPORT jobject JNICALL Java_org_keplerproject_luajava_LuaState__1getObjectFromUserdata - (JNIEnv * env , jobject jobj , jobject cptr , jint index ) -{ - /* Get luastate */ - lua_State * L = getStateFromCPtr( env , cptr ); - jobject * obj; - - if ( !isJavaObject( L , index ) ) - { - ( *env )->ThrowNew( env , ( *env )->FindClass( env , "java/lang/Exception" ) , - "Index is not a java object" ); - return NULL; - } - - obj = ( jobject * ) lua_touserdata( L , index ); - - return *obj; -} - - -/************************************************************************ -* JNI Called function -* LuaJava API Functin -************************************************************************/ - -JNIEXPORT jboolean JNICALL Java_org_keplerproject_luajava_LuaState__1isObject - (JNIEnv * env , jobject jobj , jobject cptr , jint index ) -{ - /* Get luastate */ - lua_State * L = getStateFromCPtr( env , cptr ); - - return (isJavaObject( L , index ) ? JNI_TRUE : JNI_FALSE ); -} - - -/************************************************************************ -* JNI Called function -* LuaJava API Functin -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushJavaObject - (JNIEnv * env , jobject jobj , jobject cptr , jobject obj ) -{ - /* Get luastate */ - lua_State* L = getStateFromCPtr( env , cptr ); - - pushJavaObject( L , obj ); -} - - -/************************************************************************ -* JNI Called function -* LuaJava API Functin -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushJavaFunction - (JNIEnv * env , jobject jobj , jobject cptr , jobject obj ) -{ - /* Get luastate */ - lua_State* L = getStateFromCPtr( env , cptr ); - - jobject * userData , globalRef; - - globalRef = ( *env )->NewGlobalRef( env , obj ); - - userData = ( jobject * ) lua_newuserdata( L , sizeof( jobject ) ); - *userData = globalRef; - - /* Creates metatable */ - lua_newtable( L ); - - /* pushes the __index metamethod */ - lua_pushstring( L , LUACALLMETAMETHODTAG ); - lua_pushcfunction( L , &luaJavaFunctionCall ); - lua_rawset( L , -3 ); - - /* pusher the __gc metamethod */ - lua_pushstring( L , LUAGCMETAMETHODTAG ); - lua_pushcfunction( L , &gc ); - lua_rawset( L , -3 ); - - lua_pushstring( L , LUAJAVAOBJECTIND ); - lua_pushboolean( L , 1 ); - lua_rawset( L , -3 ); - - if ( lua_setmetatable( L , -2 ) == 0 ) - { - ( *env )->ThrowNew( env , ( *env )->FindClass( env , "org/keplerproject/luajava/LuaException" ) , - "Index is not a java object" ); - } -} - - -/************************************************************************ -* JNI Called function -* LuaJava API Functin -************************************************************************/ - -JNIEXPORT jboolean JNICALL Java_org_keplerproject_luajava_LuaState__1isJavaFunction - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - /* Get luastate */ - lua_State* L = getStateFromCPtr( env , cptr ); - jobject * obj; - - if ( !isJavaObject( L , idx ) ) - { - return JNI_FALSE; - } - - obj = ( jobject * ) lua_touserdata( L , idx ); - - return ( *env )->IsInstanceOf( env , *obj , java_function_class ); - -} - - -/*********************** LUA API FUNCTIONS ******************************/ - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jobject JNICALL Java_org_keplerproject_luajava_LuaState__1open - (JNIEnv * env , jobject jobj) -{ - lua_State * L = lua_open(); - - jobject obj; - jclass tempClass; - - tempClass = ( *env )->FindClass( env , "org/keplerproject/luajava/CPtr" ); - - obj = ( *env )->AllocObject( env , tempClass ); - if ( obj ) - { - ( *env )->SetLongField( env , obj , ( *env )->GetFieldID( env , tempClass , "peer", "J" ) , ( jlong ) L ); - } - return obj; - -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openBase - (JNIEnv * env , jobject jobj , jobject cptr) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - //luaopen_base( L ); - lua_pushcfunction( L , luaopen_base ); - lua_pushstring( L , "" ); - lua_call(L , 1 , 0 ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openTable - (JNIEnv * env , jobject jobj , jobject cptr) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - //luaopen_table( L ); - lua_pushcfunction( L , luaopen_table ); - lua_pushstring( L , LUA_TABLIBNAME ); - lua_call(L , 1 , 0 ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openIo - (JNIEnv * env , jobject jobj , jobject cptr) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - //luaopen_io( L ); - lua_pushcfunction( L , luaopen_io ); - lua_pushstring( L , LUA_IOLIBNAME ); - lua_call(L , 1 , 0 ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openOs - (JNIEnv * env , jobject jobj , jobject cptr) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - //luaopen_os( L ); - lua_pushcfunction( L , luaopen_os ); - lua_pushstring( L , LUA_OSLIBNAME ); - lua_call(L , 1 , 0 ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openString - (JNIEnv * env , jobject jobj , jobject cptr) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - //luaopen_string( L ); - lua_pushcfunction( L , luaopen_string ); - lua_pushstring( L , LUA_STRLIBNAME ); - lua_call(L , 1 , 0 ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openMath - (JNIEnv * env , jobject jobj , jobject cptr) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - //luaopen_math( L ); - lua_pushcfunction( L , luaopen_math ); - lua_pushstring( L , LUA_MATHLIBNAME ); - lua_call(L , 1 , 0 ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openDebug - (JNIEnv * env, jobject jobj , jobject cptr) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - //luaopen_debug( L ); - lua_pushcfunction( L , luaopen_debug ); - lua_pushstring( L , LUA_DBLIBNAME ); - lua_call(L , 1 , 0 ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openPackage - (JNIEnv * env, jobject jobj , jobject cptr) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - //luaopen_package( L ); - lua_pushcfunction( L , luaopen_package ); - lua_pushstring( L , LUA_LOADLIBNAME ); - lua_call(L , 1 , 0 ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openLibs - (JNIEnv * env, jobject jobj , jobject cptr) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - luaL_openlibs( L ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1close - (JNIEnv * env , jobject jobj , jobject cptr) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - lua_close( L ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jobject JNICALL Java_org_keplerproject_luajava_LuaState__1newthread - (JNIEnv * env , jobject jobj , jobject cptr) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - lua_State * newThread; - - jobject obj; - jclass tempClass; - - newThread = lua_newthread( L ); - - tempClass = ( *env )->FindClass( env , "org/keplerproject/luajava/CPtr" ); - obj = ( *env )->AllocObject( env , tempClass ); - if ( obj ) - { - ( *env )->SetLongField( env , obj , ( *env )->GetFieldID( env , tempClass , - "peer" , "J" ), ( jlong ) L ); - } - - return obj; - -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1getTop - (JNIEnv * env , jobject jobj , jobject cptr) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_gettop( L ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1setTop - (JNIEnv * env , jobject jobj , jobject cptr , jint top) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - lua_settop( L , ( int ) top ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushValue - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - lua_pushvalue( L , ( int ) idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1remove - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - lua_remove( L , ( int ) idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1insert - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - lua_insert( L , ( int ) idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1replace - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - lua_replace( L , ( int ) idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1checkStack - (JNIEnv * env , jobject jobj , jobject cptr , jint sz) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_checkstack( L , ( int ) sz ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1xmove - (JNIEnv * env , jobject jobj , jobject from , jobject to , jint n) -{ - lua_State * fr = getStateFromCPtr( env , from ); - lua_State * t = getStateFromCPtr( env , to ); - - lua_xmove( fr , t , ( int ) n ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isNumber - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_isnumber( L , ( int ) idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isString - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_isstring( L , ( int ) idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isFunction - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_isfunction( L , ( int ) idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isCFunction - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_iscfunction( L , ( int ) idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isUserdata - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_isuserdata( L , ( int ) idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isTable - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_istable( L , ( int ) idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isBoolean - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_isboolean( L , ( int ) idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isNil - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_isnil( L , ( int ) idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isNone - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_isnone( L , ( int ) idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isNoneOrNil - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_isnoneornil( L , ( int ) idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1type - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_type( L , ( int ) idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1typeName - (JNIEnv * env , jobject jobj , jobject cptr , jint tp) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - const char * name = lua_typename( L , tp ); - - return ( *env )->NewStringUTF( env , name ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1equal - (JNIEnv * env , jobject jobj , jobject cptr , jint idx1 , jint idx2) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_equal( L , idx1 , idx2 ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1rawequal - (JNIEnv * env , jobject jobj , jobject cptr , jint idx1 , jint idx2) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_rawequal( L , idx1 , idx2 ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1lessthan - (JNIEnv * env , jobject jobj , jobject cptr , jint idx1 , jint idx2) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_lessthan( L , idx1 ,idx2 ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jdouble JNICALL Java_org_keplerproject_luajava_LuaState__1toNumber - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jdouble ) lua_tonumber( L , idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1toInteger - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_tointeger( L , idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1toBoolean - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_toboolean( L , idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1toString - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - const char * str = lua_tostring( L , idx ); - - return ( *env )->NewStringUTF( env , str ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1strlen - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_strlen( L , idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1objlen - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_objlen( L , idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jobject JNICALL Java_org_keplerproject_luajava_LuaState__1toThread - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L , * thr; - - jobject obj; - jclass tempClass; - - L = getStateFromCPtr( env , cptr ); - - thr = lua_tothread( L , ( int ) idx ); - - tempClass = ( *env )->FindClass( env , "org/keplerproject/luajava/CPtr" ); - - obj = ( *env )->AllocObject( env , tempClass ); - if ( obj ) - { - ( *env )->SetLongField( env , obj , ( *env )->GetFieldID( env , tempClass , "peer", "J" ) , ( jlong ) thr ); - } - return obj; - -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushNil - (JNIEnv * env , jobject jobj , jobject cptr) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - lua_pushnil( L ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushNumber - (JNIEnv * env , jobject jobj , jobject cptr , jdouble number) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - lua_pushnumber( L , ( lua_Number ) number ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushString__Lorg_keplerproject_luajava_CPtr_2Ljava_lang_String_2 - (JNIEnv * env , jobject jobj , jobject cptr , jstring str) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - const char * uniStr; - - uniStr = ( *env )->GetStringUTFChars( env , str , NULL ); - - lua_pushstring( L , uniStr ); - - ( *env )->ReleaseStringUTFChars( env , str , uniStr ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushString__Lorg_keplerproject_luajava_CPtr_2_3BI - (JNIEnv * env , jobject jobj , jobject cptr , jbyteArray bytes , jint n) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - char * cBytes; - - cBytes = ( char * ) ( *env )->GetByteArrayElements( env , bytes, NULL ); - - lua_pushlstring( L , cBytes , n ); - - ( *env )->ReleaseByteArrayElements( env , bytes , cBytes , 0 ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushBoolean - (JNIEnv * env , jobject jobj , jobject cptr , jint jbool) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - lua_pushboolean( L , ( int ) jbool ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1getTable - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - lua_gettable( L , ( int ) idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1getField - (JNIEnv * env , jobject jobj , jobject cptr , jint idx , jstring k) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - const char * uniStr; - uniStr = ( *env )->GetStringUTFChars( env , k , NULL ); - - lua_getfield( L , ( int ) idx , uniStr ); - - ( *env )->ReleaseStringUTFChars( env , k , uniStr ); -} - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1rawGet - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - lua_rawget( L , (int)idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1rawGetI - (JNIEnv * env , jobject jobj , jobject cptr , jint idx, jint n) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - lua_rawgeti( L , idx , n ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1createTable - (JNIEnv * env , jobject jobj , jobject cptr , jint narr , jint nrec) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - lua_createtable( L , ( int ) narr , ( int ) nrec ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1newTable - (JNIEnv * env , jobject jobj , jobject cptr) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - lua_newtable( L ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1getMetaTable - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return lua_getmetatable( L , idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1getFEnv - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - lua_getfenv( L , ( int ) idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1setTable - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - lua_settable( L , ( int ) idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1setField - (JNIEnv * env , jobject jobj , jobject cptr , jint idx , jstring k) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - const char * uniStr; - uniStr = ( *env )->GetStringUTFChars( env , k , NULL ); - - lua_setfield( L , ( int ) idx , uniStr ); - - ( *env )->ReleaseStringUTFChars( env , k , uniStr ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1rawSet - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - lua_rawset( L , (int)idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1rawSetI - (JNIEnv * env , jobject jobj , jobject cptr , jint idx, jint n) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - lua_rawseti( L , idx , n ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1setMetaTable - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return lua_setmetatable( L , idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1setFEnv - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return lua_setfenv( L , idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1call - (JNIEnv * env , jobject jobj , jobject cptr , jint nArgs , jint nResults) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - lua_call( L , nArgs , nResults ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1pcall - (JNIEnv * env , jobject jobj , jobject cptr , jint nArgs , jint nResults , jint errFunc) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_pcall( L , nArgs , nResults , errFunc ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1yield - (JNIEnv * env , jobject jobj , jobject cptr , jint nResults) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_yield( L , nResults ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1resume - (JNIEnv * env , jobject jobj , jobject cptr , jint nArgs) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_resume( L , nArgs ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1status - (JNIEnv * env , jobject jobj , jobject cptr) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_status( L ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1gc - (JNIEnv * env , jobject jobj , jobject cptr , jint what , jint data) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_gc( L , what , data ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1getGcCount - (JNIEnv * env , jobject jobj , jobject cptr) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_getgccount( L ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1next - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_next( L , idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1error - (JNIEnv * env , jobject jobj , jobject cptr) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_error( L ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1concat - (JNIEnv * env , jobject jobj , jobject cptr , jint n) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - lua_concat( L , n ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pop - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - lua_pop( L , ( int ) idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1setGlobal - (JNIEnv * env , jobject jobj , jobject cptr , jstring name) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - const char * str = ( *env )->GetStringUTFChars( env , name, NULL ); - - lua_setglobal( L , str ); - - ( *env )->ReleaseStringUTFChars( env , name , str ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1getGlobal - (JNIEnv * env , jobject jobj , jobject cptr , jstring name) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - const char * str = ( *env )->GetStringUTFChars( env , name, NULL ); - - lua_getglobal( L , str ); - - ( *env )->ReleaseStringUTFChars( env , name , str ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LdoFile - (JNIEnv * env , jobject jobj , jobject cptr , jstring fileName) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - const char * file = ( *env )->GetStringUTFChars( env , fileName, NULL ); - - int ret; - - ret = luaL_dofile( L , file ); - - ( *env )->ReleaseStringUTFChars( env , fileName , file ); - - return ( jint ) ret; -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LdoString - (JNIEnv * env , jobject jobj , jobject cptr , jstring str) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - const char * utfStr = ( * env )->GetStringUTFChars( env , str , NULL ); - - int ret; - - ret = luaL_dostring( L , utfStr ); - - return ( jint ) ret; -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LgetMetaField - (JNIEnv * env , jobject jobj , jobject cptr , jint obj , jstring e) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - const char * str = ( *env )->GetStringUTFChars( env , e , NULL ); - int ret; - - ret = luaL_getmetafield( L , ( int ) obj , str ); - - ( *env )->ReleaseStringUTFChars( env , e , str ); - - return ( jint ) ret; -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LcallMeta - (JNIEnv * env , jobject jobj , jobject cptr , jint obj , jstring e) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - const char * str = ( *env )->GetStringUTFChars( env , e , NULL ); - int ret; - - ret = luaL_callmeta( L , ( int ) obj, str ); - - ( *env )->ReleaseStringUTFChars( env , e , str ); - - return ( jint ) ret; -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1Ltyperror - (JNIEnv * env , jobject jobj , jobject cptr , jint nArg , jstring tName) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - const char * name = ( *env )->GetStringUTFChars( env , tName , NULL ); - int ret; - - ret = luaL_typerror( L , ( int ) nArg , name ); - - ( *env )->ReleaseStringUTFChars( env , tName , name ); - - return ( jint ) ret; -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LargError - (JNIEnv * env , jobject jobj , jobject cptr , jint numArg , jstring extraMsg) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - const char * msg = ( *env )->GetStringUTFChars( env , extraMsg , NULL ); - int ret; - - ret = luaL_argerror( L , ( int ) numArg , msg ); - - ( *env )->ReleaseStringUTFChars( env , extraMsg , msg ); - - return ( jint ) ret;; -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckString - (JNIEnv * env , jobject jobj , jobject cptr , jint numArg) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - const char * res; - - res = luaL_checkstring( L , ( int ) numArg ); - - return ( *env )->NewStringUTF( env , res ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1LoptString - (JNIEnv * env , jobject jobj , jobject cptr , jint numArg , jstring def) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - const char * d = ( *env )->GetStringUTFChars( env , def , NULL ); - const char * res; - jstring ret; - - res = luaL_optstring( L , ( int ) numArg , d ); - - ret = ( *env )->NewStringUTF( env , res ); - - ( *env )->ReleaseStringUTFChars( env , def , d ); - - return ret; -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jdouble JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckNumber - (JNIEnv * env , jobject jobj , jobject cptr , jint numArg) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jdouble ) luaL_checknumber( L , ( int ) numArg ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jdouble JNICALL Java_org_keplerproject_luajava_LuaState__1LoptNumber - (JNIEnv * env , jobject jobj , jobject cptr , jint numArg , jdouble def) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jdouble ) luaL_optnumber( L , ( int ) numArg , ( lua_Number ) def ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckInteger - (JNIEnv * env , jobject jobj , jobject cptr , jint numArg) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) luaL_checkinteger( L , ( int ) numArg ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LoptInteger - (JNIEnv * env , jobject jobj , jobject cptr , jint numArg , jint def) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) luaL_optinteger( L , ( int ) numArg , ( lua_Integer ) def ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckStack - (JNIEnv * env , jobject jobj , jobject cptr , jint sz , jstring msg) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - const char * m = ( *env )->GetStringUTFChars( env , msg , NULL ); - - luaL_checkstack( L , ( int ) sz , m ); - - ( *env )->ReleaseStringUTFChars( env , msg , m ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckType - (JNIEnv * env , jobject jobj , jobject cptr , jint nArg , jint t) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - luaL_checktype( L , ( int ) nArg , ( int ) t ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckAny - (JNIEnv * env , jobject jobj , jobject cptr , jint nArg) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - luaL_checkany( L , ( int ) nArg ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LnewMetatable - (JNIEnv * env , jobject jobj , jobject cptr , jstring tName) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - const char * name = ( *env )->GetStringUTFChars( env , tName , NULL ); - int ret; - - ret = luaL_newmetatable( L , name ); - - ( *env )->ReleaseStringUTFChars( env , tName , name ); - - return ( jint ) ret;; -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1LgetMetatable - (JNIEnv * env , jobject jobj , jobject cptr , jstring tName) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - const char * name = ( *env )->GetStringUTFChars( env , tName , NULL ); - - luaL_getmetatable( L , name ); - - ( *env )->ReleaseStringUTFChars( env , tName , name ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1Lwhere - (JNIEnv * env , jobject jobj , jobject cptr , jint lvl) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - luaL_where( L , ( int ) lvl ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1Lref - (JNIEnv * env , jobject jobj , jobject cptr , jint t) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) luaL_ref( L , ( int ) t ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1LunRef - (JNIEnv * env , jobject jobj , jobject cptr , jint t , jint ref) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - luaL_unref( L , ( int ) t , ( int ) ref ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LgetN - (JNIEnv * env , jobject jobj , jobject cptr , jint t) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) luaL_getn( L , ( int ) t ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1LsetN - (JNIEnv * env , jobject jobj , jobject cptr , jint t , jint n) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - luaL_setn( L , ( int ) t , ( int ) n ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LloadFile - (JNIEnv * env , jobject jobj , jobject cptr , jstring fileName) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - const char * fn = ( *env )->GetStringUTFChars( env , fileName , NULL ); - int ret; - - ret = luaL_loadfile( L , fn ); - - ( *env )->ReleaseStringUTFChars( env , fileName , fn ); - - return ( jint ) ret; -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LloadBuffer - (JNIEnv * env , jobject jobj , jobject cptr , jbyteArray buff , jlong sz , jstring n) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - jbyte * cBuff = ( *env )->GetByteArrayElements( env , buff, NULL ); - const char * name = ( * env )->GetStringUTFChars( env , n , NULL ); - int ret; - - ret = luaL_loadbuffer( L , ( const char * ) cBuff, ( int ) sz, name ); - - ( *env )->ReleaseStringUTFChars( env , n , name ); - - ( *env )->ReleaseByteArrayElements( env , buff , cBuff , 0 ); - - return ( jint ) ret; -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LloadString - (JNIEnv * env , jobject jobj , jobject cptr , jstring str) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - const char * fn = ( *env )->GetStringUTFChars( env , str , NULL ); - int ret; - - ret = luaL_loadstring( L , fn ); - - ( *env )->ReleaseStringUTFChars( env , str , fn ); - - return ( jint ) ret; -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1Lgsub - (JNIEnv * env , jobject jobj , jobject cptr , jstring s , jstring p , jstring r) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - const char * utS = ( *env )->GetStringUTFChars( env , s , NULL ); - const char * utP = ( *env )->GetStringUTFChars( env , p , NULL ); - const char * utR = ( *env )->GetStringUTFChars( env , r , NULL ); - - const char * sub = luaL_gsub( L , utS , utP , utR ); - - ( *env )->ReleaseStringUTFChars( env , s , utS ); - ( *env )->ReleaseStringUTFChars( env , p , utP ); - ( *env )->ReleaseStringUTFChars( env , r , utR ); - - return ( *env )->NewStringUTF( env , sub ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1LfindTable - (JNIEnv * env , jobject jobj , jobject cptr , jint idx , jstring fname , jint szhint) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - const char * name = ( *env )->GetStringUTFChars( env , fname , NULL ); - - const char * sub = luaL_findtable( L , ( int ) idx , name , ( int ) szhint ); - - ( *env )->ReleaseStringUTFChars( env , fname , name ); - - return ( *env )->NewStringUTF( env , sub ); -} + +/****************************************************************************** +* $Id$ +* Copyright (C) 2003-2007 Kepler Project. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + +/*************************************************************************** +* +* $ED +* This module is the implementation of luajava's dinamic library. +* In this module lua's functions are exported to be used in java by jni, +* and also the functions that will be used and exported to lua so that +* Java Objects' functions can be called. +* +*****************************************************************************/ + +#include +#include +#include + +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" + + +/* Constant that is used to index the JNI Environment */ +#define LUAJAVAJNIENVTAG "__JNIEnv" +/* Defines wheter the metatable is of a java Object */ +#define LUAJAVAOBJECTIND "__IsJavaObject" +/* Defines the lua State Index Property Name */ +#define LUAJAVASTATEINDEX "LuaJavaStateIndex" +/* Index metamethod name */ +#define LUAINDEXMETAMETHODTAG "__index" +/* Garbage collector metamethod name */ +#define LUAGCMETAMETHODTAG "__gc" +/* Call metamethod name */ +#define LUACALLMETAMETHODTAG "__call" +/* Constant that defines where in the metatable should I place the function name */ +#define LUAJAVAOBJFUNCCALLED "__FunctionCalled" + + + +static jclass throwable_class = NULL; +static jmethodID get_message_method = NULL; +static jclass java_function_class = NULL; +static jmethodID java_function_method = NULL; +static jclass luajava_api_class = NULL; +static jclass java_lang_class = NULL; + + +/*************************************************************************** +* +* $FC Function objectIndex +* +* $ED Description +* Function to be called by the metamethod __index of the java object +* +* $EP Function Parameters +* $P L - lua State +* $P Stack - Parameters will be received by the stack +* +* $FV Returned Value +* int - Number of values to be returned by the function +* +*$. **********************************************************************/ + + static int objectIndex( lua_State * L ); + + +/*************************************************************************** +* +* $FC Function objectIndexReturn +* +* $ED Description +* Function returned by the metamethod __index of a java Object. It is +* the actual function that is going to call the java method. +* +* $EP Function Parameters +* $P L - lua State +* $P Stack - Parameters will be received by the stack +* +* $FV Returned Value +* int - Number of values to be returned by the function +* +*$. **********************************************************************/ + + static int objectIndexReturn( lua_State * L ); + + +/*************************************************************************** +* +* $FC Function classIndex +* +* $ED Description +* Function to be called by the metamethod __index of the java class +* +* $EP Function Parameters +* $P L - lua State +* $P Stack - Parameters will be received by the stack +* +* $FV Returned Value +* int - Number of values to be returned by the function +* +*$. **********************************************************************/ + + static int classIndex( lua_State * L ); + + +/*************************************************************************** +* +* $FC Function GC +* +* $ED Description +* Function to be called by the metamethod __gc of the java object +* +* $EP Function Parameters +* $P L - lua State +* $P Stack - Parameters will be received by the stack +* +* $FV Returned Value +* int - Number of values to be returned by the function +* +*$. **********************************************************************/ + + static int gc( lua_State * L ); + + +/*************************************************************************** +* +* $FC Function javaBindClass +* +* $ED Description +* Implementation of lua function luajava.BindClass +* +* $EP Function Parameters +* $P L - lua State +* +* $FV Returned Value +* int - Number of values to be returned by the function +* +*$. **********************************************************************/ + + static int javaBindClass( lua_State * L ); + +/*************************************************************************** +* +* $FC Function createProxy +* +* $ED Description +* Implementation of lua function luajava.createProxy. +* Transform a lua table into a java class that implements a list +* of interfaces +* +* $EP Function Parameters +* $P L - lua State +* $P Stack - Parameters will be received by the stack +* +* $FV Returned Value +* int - Number of values to be returned by the function +* +*$. **********************************************************************/ + + static int createProxy( lua_State * L ); + +/*************************************************************************** +* +* $FC Function javaNew +* +* $ED Description +* Implementation of lua function luajava.new +* +* $EP Function Parameters +* $P L - lua State +* $P Stack - Parameters will be received by the stack +* +* $FV Returned Value +* int - Number of values to be returned by the function +* +*$. **********************************************************************/ + + static int javaNew( lua_State * L ); + + +/*************************************************************************** +* +* $FC Function javaNewInstance +* +* $ED Description +* Implementation of lua function luajava.newInstance +* +* $EP Function Parameters +* $P L - lua State +* $P Stack - Parameters will be received by the stack +* +* $FV Returned Value +* int - Number of values to be returned by the function +* +*$. **********************************************************************/ + + static int javaNewInstance( lua_State * L ); + + +/*************************************************************************** +* +* $FC Function javaLoadLib +* +* $ED Description +* Implementation of lua function luajava.loadLib +* +* $EP Function Parameters +* $P L - lua State +* $P Stack - Parameters will be received by the stack +* +* $FV Returned Value +* int - Number of values to be returned by the function +* +*$. **********************************************************************/ + + static int javaLoadLib( lua_State * L ); + + +/*************************************************************************** +/* +* $FC pushJavaObject +* +* $ED Description +* Function to create a lua proxy to a java object +* +* $EP Function Parameters +* $P L - lua State +* $P javaObject - Java Object to be pushed on the stack +* +* $FV Returned Value +* int - Number of values to be returned by the function +* +*$. **********************************************************************/ + + static int pushJavaObject( lua_State * L , jobject javaObject ); + + +/*************************************************************************** +* +* $FC pushJavaClass +* +* $ED Description +* Function to create a lua proxy to a java class +* +* $EP Function Parameters +* $P L - lua State +* $P javaObject - Java Class to be pushed on the stack +* +* $FV Returned Value +* int - Number of values to be returned by the function +* +*$. **********************************************************************/ + + static int pushJavaClass( lua_State * L , jobject javaObject ); + + +/*************************************************************************** +* +* $FC isJavaObject +* +* $ED Description +* Returns 1 is given index represents a java object +* +* $EP Function Parameters +* $P L - lua State +* $P idx - index on the stack +* +* $FV Returned Value +* int - Boolean. +* +*$. **********************************************************************/ + + static int isJavaObject( lua_State * L , int idx ); + + +/*************************************************************************** +* +* $FC getStateFromCPtr +* +* $ED Description +* Returns the lua_State from the CPtr Java Object +* +* $EP Function Parameters +* $P L - lua State +* $P cptr - CPtr object +* +* $FV Returned Value +* int - Number of values to be returned by the function. +* +*$. **********************************************************************/ + + static lua_State * getStateFromCPtr( JNIEnv * env , jobject cptr ); + + +/*************************************************************************** +* +* $FC luaJavaFunctionCall +* +* $ED Description +* function called by metamethod __call of instances of JavaFunctionWrapper +* +* $EP Function Parameters +* $P L - lua State +* $P Stack - Parameters will be received by the stack +* +* $FV Returned Value +* int - Number of values to be returned by the function. +* +*$. **********************************************************************/ + + static int luaJavaFunctionCall( lua_State * L ); + + +/*************************************************************************** +* +* $FC pushJNIEnv +* +* $ED Description +* function that pushes the jni environment into the lua state +* +* $EP Function Parameters +* $P env - java environment +* $P L - lua State +* +* $FV Returned Value +* void +* +*$. **********************************************************************/ + + static void pushJNIEnv( JNIEnv * env , lua_State * L ); + + + /*************************************************************************** +* +* $FC getEnvFromState +* +* $ED Description +* auxiliar function to get the JNIEnv from the lua state +* +* $EP Function Parameters +* $P L - lua State +* +* $FV Returned Value +* JNIEnv * - JNI environment +* +*$. **********************************************************************/ + + static JNIEnv * getEnvFromState( lua_State * L ); + + +/********************* Implementations ***************************/ + +/*************************************************************************** +* +* Function: objectIndex +* ****/ + +int objectIndex( lua_State * L ) +{ + lua_Number stateIndex; + const char * key; + jmethodID method; + jint checkField; + jobject * obj; + jstring str; + jthrowable exp; + JNIEnv * javaEnv; + + /* Gets the luaState index */ + lua_pushstring( L , LUAJAVASTATEINDEX ); + lua_rawget( L , LUA_REGISTRYINDEX ); + + if ( !lua_isnumber( L , -1 ) ) + { + lua_pushstring( L , "Impossible to identify luaState id." ); + lua_error( L ); + } + + stateIndex = lua_tonumber( L , -1 ); + lua_pop( L , 1 ); + + if ( !lua_isstring( L , -1 ) ) + { + lua_pushstring( L , "Invalid Function call." ); + lua_error( L ); + } + + key = lua_tostring( L , -1 ); + + if ( !isJavaObject( L , 1 ) ) + { + lua_pushstring( L , "Not a valid Java Object." ); + lua_error( L ); + } + + javaEnv = getEnvFromState( L ); + if ( javaEnv == NULL ) + { + lua_pushstring( L , "Invalid JNI Environment." ); + lua_error( L ); + } + + obj = ( jobject * ) lua_touserdata( L , 1 ); + + method = ( *javaEnv )->GetStaticMethodID( javaEnv , luajava_api_class , "checkField" , + "(ILjava/lang/Object;Ljava/lang/String;)I" ); + + str = ( *javaEnv )->NewStringUTF( javaEnv , key ); + + checkField = ( *javaEnv )->CallStaticIntMethod( javaEnv , luajava_api_class , method , + (jint)stateIndex , *obj , str ); + + exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); + + /* Handles exception */ + if ( exp != NULL ) + { + jobject jstr; + const char * cStr; + + ( *javaEnv )->ExceptionClear( javaEnv ); + jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); + + ( *javaEnv )->DeleteLocalRef( javaEnv , str ); + + if ( jstr == NULL ) + { + jmethodID methodId; + + methodId = ( *javaEnv )->GetMethodID( javaEnv , throwable_class , "toString" , "()Ljava/lang/String;" ); + jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , methodId ); + } + + cStr = ( *javaEnv )->GetStringUTFChars( javaEnv , jstr , NULL ); + + lua_pushstring( L , cStr ); + + ( *javaEnv )->ReleaseStringUTFChars( javaEnv , jstr, cStr ); + + lua_error( L ); + } + + ( *javaEnv )->DeleteLocalRef( javaEnv , str ); + + if ( checkField != 0 ) + { + return checkField; + } + + lua_getmetatable( L , 1 ); + + if ( !lua_istable( L , -1 ) ) + { + lua_pushstring( L , "Invalid MetaTable." ); + lua_error( L ); + } + + lua_pushstring( L , LUAJAVAOBJFUNCCALLED ); + lua_pushstring( L , key ); + lua_rawset( L , -3 ); + + lua_pop( L , 1 ); + + lua_pushcfunction( L , &objectIndexReturn ); + + return 1; +} + + +/*************************************************************************** +* +* Function: objectIndexReturn +* ****/ + +int objectIndexReturn( lua_State * L ) +{ + lua_Number stateIndex; + jobject * pObject; + jmethodID method; + jthrowable exp; + const char * methodName; + jint ret; + jstring str; + JNIEnv * javaEnv; + + /* Gets the luaState index */ + lua_pushstring( L , LUAJAVASTATEINDEX ); + lua_rawget( L , LUA_REGISTRYINDEX ); + + if ( !lua_isnumber( L , -1 ) ) + { + lua_pushstring( L , "Impossible to identify luaState id." ); + lua_error( L ); + } + + stateIndex = lua_tonumber( L , -1 ); + lua_pop( L , 1 ); + + /* Checks if is a valid java object */ + if ( !isJavaObject( L , 1 ) ) + { + lua_pushstring( L , "Not a valid OO function call." ); + lua_error( L ); + } + + lua_getmetatable( L , 1 ); + if ( lua_type( L , -1 ) == LUA_TNIL ) + { + lua_pushstring( L , "Not a valid java Object." ); + lua_error( L ); + } + + lua_pushstring( L , LUAJAVAOBJECTIND ); + lua_rawget( L , -2 ); + if ( lua_type( L , -1 ) == LUA_TNIL ) + { + lua_pushstring( L , "Not a valid java Object." ); + lua_error( L ); + } + lua_pop( L , 1 ); + + /* Gets the method Name */ + lua_pushstring( L , LUAJAVAOBJFUNCCALLED ); + lua_rawget( L , -2 ); + if ( lua_type( L , -1 ) == LUA_TNIL ) + { + lua_pushstring( L , "Not a OO function call." ); + lua_error( L ); + } + methodName = lua_tostring( L , -1 ); + + lua_pop( L , 2 ); + + /* Gets the object reference */ + pObject = ( jobject* ) lua_touserdata( L , 1 ); + + /* Gets the JNI Environment */ + javaEnv = getEnvFromState( L ); + if ( javaEnv == NULL ) + { + lua_pushstring( L , "Invalid JNI Environment." ); + lua_error( L ); + } + + /* Gets method */ + method = ( *javaEnv )->GetStaticMethodID( javaEnv , luajava_api_class , "objectIndex" , + "(ILjava/lang/Object;Ljava/lang/String;)I" ); + + str = ( *javaEnv )->NewStringUTF( javaEnv , methodName ); + + ret = ( *javaEnv )->CallStaticIntMethod( javaEnv , luajava_api_class , method , (jint)stateIndex , + *pObject , str ); + + exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); + + /* Handles exception */ + if ( exp != NULL ) + { + jobject jstr; + const char * cStr; + + ( *javaEnv )->ExceptionClear( javaEnv ); + jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); + + ( *javaEnv )->DeleteLocalRef( javaEnv , str ); + + if ( jstr == NULL ) + { + jmethodID methodId; + + methodId = ( *javaEnv )->GetMethodID( javaEnv , throwable_class , "toString" , "()Ljava/lang/String;" ); + jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , methodId ); + } + + cStr = ( *javaEnv )->GetStringUTFChars( javaEnv , jstr , NULL ); + + lua_pushstring( L , cStr ); + + ( *javaEnv )->ReleaseStringUTFChars( javaEnv , jstr, cStr ); + + lua_error( L ); + } + + ( *javaEnv )->DeleteLocalRef( javaEnv , str ); + + /* pushes new object into lua stack */ + return ret; +} + + +/*************************************************************************** +* +* Function: classIndex +* ****/ + +int classIndex( lua_State * L ) +{ + lua_Number stateIndex; + jobject * obj; + jmethodID method; + const char * fieldName; + jstring str; + jint ret; + jthrowable exp; + JNIEnv * javaEnv; + + /* Gets the luaState index */ + lua_pushstring( L , LUAJAVASTATEINDEX ); + lua_rawget( L , LUA_REGISTRYINDEX ); + + if ( !lua_isnumber( L , -1 ) ) + { + lua_pushstring( L , "Impossible to identify luaState id." ); + lua_error( L ); + } + + stateIndex = lua_tonumber( L , -1 ); + lua_pop( L , 1 ); + + if ( !isJavaObject( L , 1 ) ) + { + lua_pushstring( L , "Not a valid java class." ); + lua_error( L ); + } + + /* Gets the field Name */ + + if ( !lua_isstring( L , 2 ) ) + { + lua_pushstring( L , "Not a valid field call." ); + lua_error( L ); + } + + fieldName = lua_tostring( L , 2 ); + + /* Gets the object reference */ + obj = ( jobject* ) lua_touserdata( L , 1 ); + + /* Gets the JNI Environment */ + javaEnv = getEnvFromState( L ); + if ( javaEnv == NULL ) + { + lua_pushstring( L , "Invalid JNI Environment." ); + lua_error( L ); + } + + method = ( *javaEnv )->GetStaticMethodID( javaEnv , luajava_api_class , "classIndex" , + "(ILjava/lang/Class;Ljava/lang/String;)I" ); + + str = ( *javaEnv )->NewStringUTF( javaEnv , fieldName ); + + /* Return 1 for field, 2 for method or 0 for error */ + ret = ( *javaEnv )->CallStaticIntMethod( javaEnv , luajava_api_class , method, (jint)stateIndex , + *obj , str ); + + exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); + + /* Handles exception */ + if ( exp != NULL ) + { + jobject jstr; + const char * cStr; + + ( *javaEnv )->ExceptionClear( javaEnv ); + jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); + + ( *javaEnv )->DeleteLocalRef( javaEnv , str ); + + if ( jstr == NULL ) + { + jmethodID methodId; + + methodId = ( *javaEnv )->GetMethodID( javaEnv , throwable_class , "toString" , "()Ljava/lang/String;" ); + jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , methodId ); + } + + cStr = ( *javaEnv )->GetStringUTFChars( javaEnv , jstr , NULL ); + + lua_pushstring( L , cStr ); + + ( *javaEnv )->ReleaseStringUTFChars( javaEnv , jstr, cStr ); + + lua_error( L ); + } + + ( *javaEnv )->DeleteLocalRef( javaEnv , str ); + + if ( ret == 0 ) + { + lua_pushstring( L , "Name is not a static field or function." ); + lua_error( L ); + } + + if ( ret == 2 ) + { + lua_getmetatable( L , 1 ); + lua_pushstring( L , LUAJAVAOBJFUNCCALLED ); + lua_pushstring( L , fieldName ); + lua_rawset( L , -3 ); + + lua_pop( L , 1 ); + + lua_pushcfunction( L , &objectIndexReturn ); + + return 1; + } + + return ret; +} + + +/*************************************************************************** +* +* Function: gc +* ****/ + +int gc( lua_State * L ) +{ + jobject * pObj; + JNIEnv * javaEnv; + + if ( !isJavaObject( L , 1 ) ) + { + return 0; + } + + pObj = ( jobject * ) lua_touserdata( L , 1 ); + + /* Gets the JNI Environment */ + javaEnv = getEnvFromState( L ); + if ( javaEnv == NULL ) + { + lua_pushstring( L , "Invalid JNI Environment." ); + lua_error( L ); + } + + ( *javaEnv )->DeleteGlobalRef( javaEnv , *pObj ); + + return 0; +} + + +/*************************************************************************** +* +* Function: javaBindClass +* ****/ + +int javaBindClass( lua_State * L ) +{ + int top; + jmethodID method; + const char * className; + jstring javaClassName; + jobject classInstance; + jthrowable exp; + JNIEnv * javaEnv; + + top = lua_gettop( L ); + + if ( top != 1 ) + { + luaL_error( L , "Error. Function javaBindClass received %d arguments, expected 1." , top ); + } + + /* Gets the JNI Environment */ + javaEnv = getEnvFromState( L ); + if ( javaEnv == NULL ) + { + lua_pushstring( L , "Invalid JNI Environment." ); + lua_error( L ); + } + + /* get the string parameter */ + if ( !lua_isstring( L , 1 ) ) + { + lua_pushstring( L , "Invalid parameter type. String expected." ); + lua_error( L ); + } + className = lua_tostring( L , 1 ); + + method = ( *javaEnv )->GetStaticMethodID( javaEnv , java_lang_class , "forName" , + "(Ljava/lang/String;)Ljava/lang/Class;" ); + + javaClassName = ( *javaEnv )->NewStringUTF( javaEnv , className ); + + classInstance = ( *javaEnv )->CallStaticObjectMethod( javaEnv , java_lang_class , + method , javaClassName ); + + exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); + + /* Handles exception */ + if ( exp != NULL ) + { + jobject jstr; + const char * cStr; + + ( *javaEnv )->ExceptionClear( javaEnv ); + jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); + + ( *javaEnv )->DeleteLocalRef( javaEnv , javaClassName ); + + if ( jstr == NULL ) + { + jmethodID methodId; + + methodId = ( *javaEnv )->GetMethodID( javaEnv , throwable_class , "toString" , "()Ljava/lang/String;" ); + jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , methodId ); + } + + cStr = ( *javaEnv )->GetStringUTFChars( javaEnv , jstr , NULL ); + + lua_pushstring( L , cStr ); + + ( *javaEnv )->ReleaseStringUTFChars( javaEnv , jstr, cStr ); + + lua_error( L ); + } + + ( *javaEnv )->DeleteLocalRef( javaEnv , javaClassName ); + + /* pushes new object into lua stack */ + + return pushJavaClass( L , classInstance ); +} + + +/*************************************************************************** +* +* Function: createProxy +* ****/ +int createProxy( lua_State * L ) +{ + jint ret; + lua_Number stateIndex; + const char * impl; + jmethodID method; + jthrowable exp; + jstring str; + JNIEnv * javaEnv; + + if ( lua_gettop( L ) != 2 ) + { + lua_pushstring( L , "Error. Function createProxy expects 2 arguments." ); + lua_error( L ); + } + + /* Gets the luaState index */ + lua_pushstring( L , LUAJAVASTATEINDEX ); + lua_rawget( L , LUA_REGISTRYINDEX ); + + if ( !lua_isnumber( L , -1 ) ) + { + lua_pushstring( L , "Impossible to identify luaState id." ); + lua_error( L ); + } + + stateIndex = lua_tonumber( L , -1 ); + lua_pop( L , 1 ); + + if ( !lua_isstring( L , 1 ) || !lua_istable( L , 2 ) ) + { + lua_pushstring( L , "Invalid Argument types. Expected (string, table)." ); + lua_error( L ); + } + + /* Gets the JNI Environment */ + javaEnv = getEnvFromState( L ); + if ( javaEnv == NULL ) + { + lua_pushstring( L , "Invalid JNI Environment." ); + lua_error( L ); + } + + method = ( *javaEnv )->GetStaticMethodID( javaEnv , luajava_api_class , "createProxyObject" , + "(ILjava/lang/String;)I" ); + + impl = lua_tostring( L , 1 ); + + str = ( *javaEnv )->NewStringUTF( javaEnv , impl ); + + ret = ( *javaEnv )->CallStaticIntMethod( javaEnv , luajava_api_class , method, (jint)stateIndex , str ); + + exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); + + /* Handles exception */ + if ( exp != NULL ) + { + jobject jstr; + const char * cStr; + + ( *javaEnv )->ExceptionClear( javaEnv ); + jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); + + ( *javaEnv )->DeleteLocalRef( javaEnv , str ); + + if ( jstr == NULL ) + { + jmethodID methodId; + + methodId = ( *javaEnv )->GetMethodID( javaEnv , throwable_class , "toString" , "()Ljava/lang/String;" ); + jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , methodId ); + } + + cStr = ( *javaEnv )->GetStringUTFChars( javaEnv , jstr , NULL ); + + lua_pushstring( L , cStr ); + + ( *javaEnv )->ReleaseStringUTFChars( javaEnv , jstr, cStr ); + + lua_error( L ); + } + + ( *javaEnv )->DeleteLocalRef( javaEnv , str ); + + return ret; +} + +/*************************************************************************** +* +* Function: javaNew +* ****/ + +int javaNew( lua_State * L ) +{ + int top; + jint ret; + jclass clazz; + jmethodID method; + jobject classInstance ; + jthrowable exp; + jobject * userData; + lua_Number stateIndex; + JNIEnv * javaEnv; + + top = lua_gettop( L ); + + if ( top == 0 ) + { + lua_pushstring( L , "Error. Invalid number of parameters." ); + lua_error( L ); + } + + /* Gets the luaState index */ + lua_pushstring( L , LUAJAVASTATEINDEX ); + lua_rawget( L , LUA_REGISTRYINDEX ); + + if ( !lua_isnumber( L , -1 ) ) + { + lua_pushstring( L , "Impossible to identify luaState id." ); + lua_error( L ); + } + + stateIndex = lua_tonumber( L , -1 ); + lua_pop( L , 1 ); + + /* Gets the java Class reference */ + if ( !isJavaObject( L , 1 ) ) + { + lua_pushstring( L , "Argument not a valid Java Class." ); + lua_error( L ); + } + + /* Gets the JNI Environment */ + javaEnv = getEnvFromState( L ); + if ( javaEnv == NULL ) + { + lua_pushstring( L , "Invalid JNI Environment." ); + lua_error( L ); + } + + clazz = ( *javaEnv )->FindClass( javaEnv , "java/lang/Class" ); + + userData = ( jobject * ) lua_touserdata( L , 1 ); + + classInstance = ( jobject ) *userData; + + if ( ( *javaEnv )->IsInstanceOf( javaEnv , classInstance , clazz ) == JNI_FALSE ) + { + lua_pushstring( L , "Argument not a valid Java Class." ); + lua_error( L ); + } + + method = ( *javaEnv )->GetStaticMethodID( javaEnv , luajava_api_class , "javaNew" , + "(ILjava/lang/Class;)I" ); + + if ( clazz == NULL || method == NULL ) + { + lua_pushstring( L , "Invalid method org.keplerproject.luajava.LuaJavaAPI.javaNew." ); + lua_error( L ); + } + + ret = ( *javaEnv )->CallStaticIntMethod( javaEnv , clazz , method , (jint)stateIndex , classInstance ); + + exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); + + /* Handles exception */ + if ( exp != NULL ) + { + jobject jstr; + const char * str; + + ( *javaEnv )->ExceptionClear( javaEnv ); + jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); + + if ( jstr == NULL ) + { + jmethodID methodId; + + methodId = ( *javaEnv )->GetMethodID( javaEnv , throwable_class , "toString" , "()Ljava/lang/String;" ); + jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , methodId ); + } + + str = ( *javaEnv )->GetStringUTFChars( javaEnv , jstr , NULL ); + + lua_pushstring( L , str ); + + ( *javaEnv )->ReleaseStringUTFChars( javaEnv , jstr, str ); + + lua_error( L ); + } + return ret; +} + + +/*************************************************************************** +* +* Function: javaNewInstance +* ****/ + +int javaNewInstance( lua_State * L ) +{ + jint ret; + jmethodID method; + const char * className; + jstring javaClassName; + jthrowable exp; + lua_Number stateIndex; + JNIEnv * javaEnv; + + /* Gets the luaState index */ + lua_pushstring( L , LUAJAVASTATEINDEX ); + lua_rawget( L , LUA_REGISTRYINDEX ); + + if ( !lua_isnumber( L , -1 ) ) + { + lua_pushstring( L , "Impossible to identify luaState id." ); + lua_error( L ); + } + + stateIndex = lua_tonumber( L , -1 ); + lua_pop( L , 1 ); + + /* get the string parameter */ + if ( !lua_isstring( L , 1 ) ) + { + lua_pushstring( L , "Invalid parameter type. String expected as first parameter." ); + lua_error( L ); + } + + className = lua_tostring( L , 1 ); + + /* Gets the JNI Environment */ + javaEnv = getEnvFromState( L ); + if ( javaEnv == NULL ) + { + lua_pushstring( L , "Invalid JNI Environment." ); + lua_error( L ); + } + + method = ( *javaEnv )->GetStaticMethodID( javaEnv , luajava_api_class , "javaNewInstance" , + "(ILjava/lang/String;)I" ); + + javaClassName = ( *javaEnv )->NewStringUTF( javaEnv , className ); + + ret = ( *javaEnv )->CallStaticIntMethod( javaEnv , luajava_api_class , method, (jint)stateIndex , + javaClassName ); + + exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); + + /* Handles exception */ + if ( exp != NULL ) + { + jobject jstr; + const char * str; + + ( *javaEnv )->ExceptionClear( javaEnv ); + jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); + + ( *javaEnv )->DeleteLocalRef( javaEnv , javaClassName ); + + if ( jstr == NULL ) + { + jmethodID methodId; + + methodId = ( *javaEnv )->GetMethodID( javaEnv , throwable_class , "toString" , "()Ljava/lang/String;" ); + jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , methodId ); + } + + str = ( *javaEnv )->GetStringUTFChars( javaEnv , jstr , NULL ); + + lua_pushstring( L , str ); + + ( *javaEnv )->ReleaseStringUTFChars( javaEnv , jstr, str ); + + lua_error( L ); + } + + ( *javaEnv )->DeleteLocalRef( javaEnv , javaClassName ); + + return ret; +} + + +/*************************************************************************** +* +* Function: javaLoadLib +* ****/ + +int javaLoadLib( lua_State * L ) +{ + jint ret; + int top; + const char * className, * methodName; + lua_Number stateIndex; + jmethodID method; + jthrowable exp; + jstring javaClassName , javaMethodName; + JNIEnv * javaEnv; + + top = lua_gettop( L ); + + if ( top != 2 ) + { + lua_pushstring( L , "Error. Invalid number of parameters." ); + lua_error( L ); + } + + /* Gets the luaState index */ + lua_pushstring( L , LUAJAVASTATEINDEX ); + lua_rawget( L , LUA_REGISTRYINDEX ); + + if ( !lua_isnumber( L , -1 ) ) + { + lua_pushstring( L , "Impossible to identify luaState id." ); + lua_error( L ); + } + + stateIndex = lua_tonumber( L , -1 ); + lua_pop( L , 1 ); + + + if ( !lua_isstring( L , 1 ) || !lua_isstring( L , 2 ) ) + { + lua_pushstring( L , "Invalid parameter. Strings expected." ); + lua_error( L ); + } + + className = lua_tostring( L , 1 ); + methodName = lua_tostring( L , 2 ); + + /* Gets the JNI Environment */ + javaEnv = getEnvFromState( L ); + if ( javaEnv == NULL ) + { + lua_pushstring( L , "Invalid JNI Environment." ); + lua_error( L ); + } + + method = ( *javaEnv )->GetStaticMethodID( javaEnv , luajava_api_class , "javaLoadLib" , + "(ILjava/lang/String;Ljava/lang/String;)I" ); + + javaClassName = ( *javaEnv )->NewStringUTF( javaEnv , className ); + javaMethodName = ( *javaEnv )->NewStringUTF( javaEnv , methodName ); + + ret = ( *javaEnv )->CallStaticIntMethod( javaEnv , luajava_api_class , method, (jint)stateIndex , + javaClassName , javaMethodName ); + + exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); + + /* Handles exception */ + if ( exp != NULL ) + { + jobject jstr; + const char * str; + + ( *javaEnv )->ExceptionClear( javaEnv ); + jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); + + ( *javaEnv )->DeleteLocalRef( javaEnv , javaClassName ); + ( *javaEnv )->DeleteLocalRef( javaEnv , javaMethodName ); + + if ( jstr == NULL ) + { + jmethodID methodId; + + methodId = ( *javaEnv )->GetMethodID( javaEnv , throwable_class , "toString" , "()Ljava/lang/String;" ); + jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , methodId ); + } + + str = ( *javaEnv )->GetStringUTFChars( javaEnv , jstr , NULL ); + + lua_pushstring( L , str ); + + ( *javaEnv )->ReleaseStringUTFChars( javaEnv , jstr, str ); + + lua_error( L ); + } + + ( *javaEnv )->DeleteLocalRef( javaEnv , javaClassName ); + ( *javaEnv )->DeleteLocalRef( javaEnv , javaMethodName ); + + return ret; +} + + +/*************************************************************************** +* +* Function: pushJavaClass +* ****/ + +int pushJavaClass( lua_State * L , jobject javaObject ) +{ + jobject * userData , globalRef; + + /* Gets the JNI Environment */ + JNIEnv * javaEnv = getEnvFromState( L ); + if ( javaEnv == NULL ) + { + lua_pushstring( L , "Invalid JNI Environment." ); + lua_error( L ); + } + + globalRef = ( *javaEnv )->NewGlobalRef( javaEnv , javaObject ); + + userData = ( jobject * ) lua_newuserdata( L , sizeof( jobject ) ); + *userData = globalRef; + + /* Creates metatable */ + lua_newtable( L ); + + /* pushes the __index metamethod */ + lua_pushstring( L , LUAINDEXMETAMETHODTAG ); + lua_pushcfunction( L , &classIndex ); + lua_rawset( L , -3 ); + + /* pushes the __gc metamethod */ + lua_pushstring( L , LUAGCMETAMETHODTAG ); + lua_pushcfunction( L , &gc ); + lua_rawset( L , -3 ); + + /* Is Java Object boolean */ + lua_pushstring( L , LUAJAVAOBJECTIND ); + lua_pushboolean( L , 1 ); + lua_rawset( L , -3 ); + + if ( lua_setmetatable( L , -2 ) == 0 ) + { + lua_pushstring( L , "Cannot create proxy to java class." ); + lua_error( L ); + } + + return 1; +} + + +/*************************************************************************** +* +* Function: pushJavaObject +* ****/ + +int pushJavaObject( lua_State * L , jobject javaObject ) +{ + jobject * userData , globalRef; + + /* Gets the JNI Environment */ + JNIEnv * javaEnv = getEnvFromState( L ); + if ( javaEnv == NULL ) + { + lua_pushstring( L , "Invalid JNI Environment." ); + lua_error( L ); + } + + globalRef = ( *javaEnv )->NewGlobalRef( javaEnv , javaObject ); + + userData = ( jobject * ) lua_newuserdata( L , sizeof( jobject ) ); + *userData = globalRef; + + /* Creates metatable */ + lua_newtable( L ); + + /* pushes the __index metamethod */ + lua_pushstring( L , LUAINDEXMETAMETHODTAG ); + lua_pushcfunction( L , &objectIndex ); + lua_rawset( L , -3 ); + + /* pushes the __gc metamethod */ + lua_pushstring( L , LUAGCMETAMETHODTAG ); + lua_pushcfunction( L , &gc ); + lua_rawset( L , -3 ); + + /* Is Java Object boolean */ + lua_pushstring( L , LUAJAVAOBJECTIND ); + lua_pushboolean( L , 1 ); + lua_rawset( L , -3 ); + + if ( lua_setmetatable( L , -2 ) == 0 ) + { + lua_pushstring( L , "Cannot create proxy to java object." ); + lua_error( L ); + } + + return 1; +} + + +/*************************************************************************** +* +* Function: isJavaObject +* ****/ + +int isJavaObject( lua_State * L , int idx ) +{ + if ( !lua_isuserdata( L , idx ) ) + return 0; + + if ( lua_getmetatable( L , idx ) == 0 ) + return 0; + + lua_pushstring( L , LUAJAVAOBJECTIND ); + lua_rawget( L , -2 ); + + if (lua_isnil( L, -1 )) + { + lua_pop( L , 2 ); + return 0; + } + lua_pop( L , 2 ); + return 1; +} + + +/*************************************************************************** +* +* Function: getStateFromCPtr +* ****/ + +lua_State * getStateFromCPtr( JNIEnv * env , jobject cptr ) +{ + lua_State * L; + + jclass classPtr = ( *env )->GetObjectClass( env , cptr ); + jfieldID CPtr_peer_ID = ( *env )->GetFieldID( env , classPtr , "peer" , "J" ); + jbyte * peer = ( jbyte * ) ( *env )->GetLongField( env , cptr , CPtr_peer_ID ); + + L = ( lua_State * ) peer; + + pushJNIEnv( env , L ); + + return L; +} + + +/*************************************************************************** +* +* Function: luaJavaFunctionCall +* ****/ + +int luaJavaFunctionCall( lua_State * L ) +{ + jobject * obj; + jthrowable exp; + int ret; + JNIEnv * javaEnv; + + if ( !isJavaObject( L , 1 ) ) + { + lua_pushstring( L , "Not a java Function." ); + lua_error( L ); + } + + obj = lua_touserdata( L , 1 ); + + /* Gets the JNI Environment */ + javaEnv = getEnvFromState( L ); + if ( javaEnv == NULL ) + { + lua_pushstring( L , "Invalid JNI Environment." ); + lua_error( L ); + } + + /* the Object must be an instance of the JavaFunction class */ + if ( ( *javaEnv )->IsInstanceOf( javaEnv , *obj , java_function_class ) == + JNI_FALSE ) + { + fprintf( stderr , "Called Java object is not a JavaFunction\n"); + return 0; + } + + ret = ( *javaEnv )->CallIntMethod( javaEnv , *obj , java_function_method ); + + exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); + + /* Handles exception */ + if ( exp != NULL ) + { + jobject jstr; + const char * str; + + ( *javaEnv )->ExceptionClear( javaEnv ); + jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); + + if ( jstr == NULL ) + { + jmethodID methodId; + + methodId = ( *javaEnv )->GetMethodID( javaEnv , throwable_class , "toString" , "()Ljava/lang/String;" ); + jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , methodId ); + } + + str = ( *javaEnv )->GetStringUTFChars( javaEnv , jstr , NULL ); + + lua_pushstring( L , str ); + + ( *javaEnv )->ReleaseStringUTFChars( javaEnv , jstr, str ); + + lua_error( L ); + } + return ret; +} + + +/*************************************************************************** +* +* Function: luaJavaFunctionCall +* ****/ + +JNIEnv * getEnvFromState( lua_State * L ) +{ + JNIEnv ** udEnv; + + lua_pushstring( L , LUAJAVAJNIENVTAG ); + lua_rawget( L , LUA_REGISTRYINDEX ); + + if ( !lua_isuserdata( L , -1 ) ) + { + lua_pop( L , 1 ); + return NULL; + } + + udEnv = ( JNIEnv ** ) lua_touserdata( L , -1 ); + + lua_pop( L , 1 ); + + return * udEnv; +} + + +/*************************************************************************** +* +* Function: pushJNIEnv +* ****/ + +void pushJNIEnv( JNIEnv * env , lua_State * L ) +{ + JNIEnv ** udEnv; + + lua_pushstring( L , LUAJAVAJNIENVTAG ); + lua_rawget( L , LUA_REGISTRYINDEX ); + + if ( !lua_isnil( L , -1 ) ) + { + udEnv = ( JNIEnv ** ) lua_touserdata( L , -1 ); + *udEnv = env; + lua_pop( L , 1 ); + } + else + { + lua_pop( L , 1 ); + udEnv = ( JNIEnv ** ) lua_newuserdata( L , sizeof( JNIEnv * ) ); + *udEnv = env; + + lua_pushstring( L , LUAJAVAJNIENVTAG ); + lua_insert( L , -2 ); + lua_rawset( L , LUA_REGISTRYINDEX ); + } +} + +/* +** Assumes the table is on top of the stack. +*/ +static void set_info (lua_State *L) { + lua_pushliteral (L, "_COPYRIGHT"); + lua_pushliteral (L, "Copyright (C) 2003-2007 Kepler Project"); + lua_settable (L, -3); + lua_pushliteral (L, "_DESCRIPTION"); + lua_pushliteral (L, "LuaJava is a script tool for Java"); + lua_settable (L, -3); + lua_pushliteral (L, "_NAME"); + lua_pushliteral (L, "LuaJava"); + lua_settable (L, -3); + lua_pushliteral (L, "_VERSION"); + lua_pushliteral (L, "1.1"); + lua_settable (L, -3); +} + +/**************************** JNI FUNCTIONS ****************************/ + +/************************************************************************ +* JNI Called function +* LuaJava API Functin +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState_luajava_1open + ( JNIEnv * env , jobject jobj , jobject cptr , jint stateId ) +{ + lua_State* L; + + jclass tempClass; + + L = getStateFromCPtr( env , cptr ); + + lua_pushstring( L , LUAJAVASTATEINDEX ); + lua_pushnumber( L , (lua_Number)stateId ); + lua_settable( L , LUA_REGISTRYINDEX ); + + + lua_newtable( L ); + + lua_setglobal( L , "luajava" ); + + lua_getglobal( L , "luajava" ); + + set_info( L); + + lua_pushstring( L , "bindClass" ); + lua_pushcfunction( L , &javaBindClass ); + lua_settable( L , -3 ); + + lua_pushstring( L , "new" ); + lua_pushcfunction( L , &javaNew ); + lua_settable( L , -3 ); + + lua_pushstring( L , "newInstance" ); + lua_pushcfunction( L , &javaNewInstance ); + lua_settable( L , -3 ); + + lua_pushstring( L , "loadLib" ); + lua_pushcfunction( L , &javaLoadLib ); + lua_settable( L , -3 ); + + lua_pushstring( L , "createProxy" ); + lua_pushcfunction( L , &createProxy ); + lua_settable( L , -3 ); + + lua_pop( L , 1 ); + + if ( luajava_api_class == NULL ) + { + tempClass = ( *env )->FindClass( env , "org/keplerproject/luajava/LuaJavaAPI" ); + + if ( tempClass == NULL ) + { + fprintf( stderr , "Could not find LuaJavaAPI class\n" ); + exit( 1 ); + } + + if ( ( luajava_api_class = ( *env )->NewGlobalRef( env , tempClass ) ) == NULL ) + { + fprintf( stderr , "Could not bind to LuaJavaAPI class\n" ); + exit( 1 ); + } + } + + if ( java_function_class == NULL ) + { + tempClass = ( *env )->FindClass( env , "org/keplerproject/luajava/JavaFunction" ); + + if ( tempClass == NULL ) + { + fprintf( stderr , "Could not find JavaFunction interface\n" ); + exit( 1 ); + } + + if ( ( java_function_class = ( *env )->NewGlobalRef( env , tempClass ) ) == NULL ) + { + fprintf( stderr , "Could not bind to JavaFunction interface\n" ); + exit( 1 ); + } + } + + if ( java_function_method == NULL ) + { + java_function_method = ( *env )->GetMethodID( env , java_function_class , "execute" , "()I"); + if ( !java_function_method ) + { + fprintf( stderr , "Could not find method in JavaFunction\n" ); + exit( 1 ); + } + } + + if ( throwable_class == NULL ) + { + tempClass = ( *env )->FindClass( env , "java/lang/Throwable" ); + + if ( tempClass == NULL ) + { + fprintf( stderr , "Error. Couldn't bind java class java.lang.Throwable\n" ); + exit( 1 ); + } + + throwable_class = ( *env )->NewGlobalRef( env , tempClass ); + + if ( throwable_class == NULL ) + { + fprintf( stderr , "Error. Couldn't bind java class java.lang.Throwable\n" ); + exit( 1 ); + } + } + + if ( get_message_method == NULL ) + { + get_message_method = ( *env )->GetMethodID( env , throwable_class , "getMessage" , + "()Ljava/lang/String;" ); + + if ( get_message_method == NULL ) + { + fprintf(stderr, "Could not find method in java.lang.Throwable\n"); + exit(1); + } + } + + if ( java_lang_class == NULL ) + { + tempClass = ( *env )->FindClass( env , "java/lang/Class" ); + + if ( tempClass == NULL ) + { + fprintf( stderr , "Error. Coundn't bind java class java.lang.Class\n" ); + exit( 1 ); + } + + java_lang_class = ( *env )->NewGlobalRef( env , tempClass ); + + if ( java_lang_class == NULL ) + { + fprintf( stderr , "Error. Couldn't bind java class java.lang.Throwable\n" ); + exit( 1 ); + } + } + + pushJNIEnv( env , L ); +} + +/************************************************************************ +* JNI Called function +* LuaJava API Functin +************************************************************************/ + +JNIEXPORT jobject JNICALL Java_org_keplerproject_luajava_LuaState__1getObjectFromUserdata + (JNIEnv * env , jobject jobj , jobject cptr , jint index ) +{ + /* Get luastate */ + lua_State * L = getStateFromCPtr( env , cptr ); + jobject * obj; + + if ( !isJavaObject( L , index ) ) + { + ( *env )->ThrowNew( env , ( *env )->FindClass( env , "java/lang/Exception" ) , + "Index is not a java object" ); + return NULL; + } + + obj = ( jobject * ) lua_touserdata( L , index ); + + return *obj; +} + + +/************************************************************************ +* JNI Called function +* LuaJava API Functin +************************************************************************/ + +JNIEXPORT jboolean JNICALL Java_org_keplerproject_luajava_LuaState__1isObject + (JNIEnv * env , jobject jobj , jobject cptr , jint index ) +{ + /* Get luastate */ + lua_State * L = getStateFromCPtr( env , cptr ); + + return (isJavaObject( L , index ) ? JNI_TRUE : JNI_FALSE ); +} + + +/************************************************************************ +* JNI Called function +* LuaJava API Functin +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushJavaObject + (JNIEnv * env , jobject jobj , jobject cptr , jobject obj ) +{ + /* Get luastate */ + lua_State* L = getStateFromCPtr( env , cptr ); + + pushJavaObject( L , obj ); +} + + +/************************************************************************ +* JNI Called function +* LuaJava API Functin +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushJavaFunction + (JNIEnv * env , jobject jobj , jobject cptr , jobject obj ) +{ + /* Get luastate */ + lua_State* L = getStateFromCPtr( env , cptr ); + + jobject * userData , globalRef; + + globalRef = ( *env )->NewGlobalRef( env , obj ); + + userData = ( jobject * ) lua_newuserdata( L , sizeof( jobject ) ); + *userData = globalRef; + + /* Creates metatable */ + lua_newtable( L ); + + /* pushes the __index metamethod */ + lua_pushstring( L , LUACALLMETAMETHODTAG ); + lua_pushcfunction( L , &luaJavaFunctionCall ); + lua_rawset( L , -3 ); + + /* pusher the __gc metamethod */ + lua_pushstring( L , LUAGCMETAMETHODTAG ); + lua_pushcfunction( L , &gc ); + lua_rawset( L , -3 ); + + lua_pushstring( L , LUAJAVAOBJECTIND ); + lua_pushboolean( L , 1 ); + lua_rawset( L , -3 ); + + if ( lua_setmetatable( L , -2 ) == 0 ) + { + ( *env )->ThrowNew( env , ( *env )->FindClass( env , "org/keplerproject/luajava/LuaException" ) , + "Index is not a java object" ); + } +} + + +/************************************************************************ +* JNI Called function +* LuaJava API Functin +************************************************************************/ + +JNIEXPORT jboolean JNICALL Java_org_keplerproject_luajava_LuaState__1isJavaFunction + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + /* Get luastate */ + lua_State* L = getStateFromCPtr( env , cptr ); + jobject * obj; + + if ( !isJavaObject( L , idx ) ) + { + return JNI_FALSE; + } + + obj = ( jobject * ) lua_touserdata( L , idx ); + + return ( *env )->IsInstanceOf( env , *obj , java_function_class ); + +} + + +/*********************** LUA API FUNCTIONS ******************************/ + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jobject JNICALL Java_org_keplerproject_luajava_LuaState__1open + (JNIEnv * env , jobject jobj) +{ + lua_State * L = lua_open(); + + jobject obj; + jclass tempClass; + + tempClass = ( *env )->FindClass( env , "org/keplerproject/luajava/CPtr" ); + + obj = ( *env )->AllocObject( env , tempClass ); + if ( obj ) + { + ( *env )->SetLongField( env , obj , ( *env )->GetFieldID( env , tempClass , "peer", "J" ) , ( jlong ) L ); + } + return obj; + +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openBase + (JNIEnv * env , jobject jobj , jobject cptr) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + //luaopen_base( L ); + lua_pushcfunction( L , luaopen_base ); + lua_pushstring( L , "" ); + lua_call(L , 1 , 0 ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openTable + (JNIEnv * env , jobject jobj , jobject cptr) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + //luaopen_table( L ); + lua_pushcfunction( L , luaopen_table ); + lua_pushstring( L , LUA_TABLIBNAME ); + lua_call(L , 1 , 0 ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openIo + (JNIEnv * env , jobject jobj , jobject cptr) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + //luaopen_io( L ); + lua_pushcfunction( L , luaopen_io ); + lua_pushstring( L , LUA_IOLIBNAME ); + lua_call(L , 1 , 0 ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openOs + (JNIEnv * env , jobject jobj , jobject cptr) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + //luaopen_os( L ); + lua_pushcfunction( L , luaopen_os ); + lua_pushstring( L , LUA_OSLIBNAME ); + lua_call(L , 1 , 0 ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openString + (JNIEnv * env , jobject jobj , jobject cptr) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + //luaopen_string( L ); + lua_pushcfunction( L , luaopen_string ); + lua_pushstring( L , LUA_STRLIBNAME ); + lua_call(L , 1 , 0 ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openMath + (JNIEnv * env , jobject jobj , jobject cptr) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + //luaopen_math( L ); + lua_pushcfunction( L , luaopen_math ); + lua_pushstring( L , LUA_MATHLIBNAME ); + lua_call(L , 1 , 0 ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openDebug + (JNIEnv * env, jobject jobj , jobject cptr) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + //luaopen_debug( L ); + lua_pushcfunction( L , luaopen_debug ); + lua_pushstring( L , LUA_DBLIBNAME ); + lua_call(L , 1 , 0 ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openPackage + (JNIEnv * env, jobject jobj , jobject cptr) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + //luaopen_package( L ); + lua_pushcfunction( L , luaopen_package ); + lua_pushstring( L , LUA_LOADLIBNAME ); + lua_call(L , 1 , 0 ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openLibs + (JNIEnv * env, jobject jobj , jobject cptr) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + luaL_openlibs( L ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1close + (JNIEnv * env , jobject jobj , jobject cptr) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + lua_close( L ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jobject JNICALL Java_org_keplerproject_luajava_LuaState__1newthread + (JNIEnv * env , jobject jobj , jobject cptr) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + lua_State * newThread; + + jobject obj; + jclass tempClass; + + newThread = lua_newthread( L ); + + tempClass = ( *env )->FindClass( env , "org/keplerproject/luajava/CPtr" ); + obj = ( *env )->AllocObject( env , tempClass ); + if ( obj ) + { + ( *env )->SetLongField( env , obj , ( *env )->GetFieldID( env , tempClass , + "peer" , "J" ), ( jlong ) L ); + } + + return obj; + +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1getTop + (JNIEnv * env , jobject jobj , jobject cptr) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_gettop( L ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1setTop + (JNIEnv * env , jobject jobj , jobject cptr , jint top) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + lua_settop( L , ( int ) top ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushValue + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + lua_pushvalue( L , ( int ) idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1remove + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + lua_remove( L , ( int ) idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1insert + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + lua_insert( L , ( int ) idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1replace + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + lua_replace( L , ( int ) idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1checkStack + (JNIEnv * env , jobject jobj , jobject cptr , jint sz) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_checkstack( L , ( int ) sz ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1xmove + (JNIEnv * env , jobject jobj , jobject from , jobject to , jint n) +{ + lua_State * fr = getStateFromCPtr( env , from ); + lua_State * t = getStateFromCPtr( env , to ); + + lua_xmove( fr , t , ( int ) n ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isNumber + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_isnumber( L , ( int ) idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isString + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_isstring( L , ( int ) idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isFunction + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_isfunction( L , ( int ) idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isCFunction + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_iscfunction( L , ( int ) idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isUserdata + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_isuserdata( L , ( int ) idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isTable + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_istable( L , ( int ) idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isBoolean + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_isboolean( L , ( int ) idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isNil + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_isnil( L , ( int ) idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isNone + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_isnone( L , ( int ) idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isNoneOrNil + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_isnoneornil( L , ( int ) idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1type + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_type( L , ( int ) idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1typeName + (JNIEnv * env , jobject jobj , jobject cptr , jint tp) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + const char * name = lua_typename( L , tp ); + + return ( *env )->NewStringUTF( env , name ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1equal + (JNIEnv * env , jobject jobj , jobject cptr , jint idx1 , jint idx2) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_equal( L , idx1 , idx2 ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1rawequal + (JNIEnv * env , jobject jobj , jobject cptr , jint idx1 , jint idx2) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_rawequal( L , idx1 , idx2 ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1lessthan + (JNIEnv * env , jobject jobj , jobject cptr , jint idx1 , jint idx2) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_lessthan( L , idx1 ,idx2 ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jdouble JNICALL Java_org_keplerproject_luajava_LuaState__1toNumber + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jdouble ) lua_tonumber( L , idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1toInteger + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_tointeger( L , idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1toBoolean + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_toboolean( L , idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1toString + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + const char * str = lua_tostring( L , idx ); + + return ( *env )->NewStringUTF( env , str ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1strlen + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_strlen( L , idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1objlen + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_objlen( L , idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jobject JNICALL Java_org_keplerproject_luajava_LuaState__1toThread + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L , * thr; + + jobject obj; + jclass tempClass; + + L = getStateFromCPtr( env , cptr ); + + thr = lua_tothread( L , ( int ) idx ); + + tempClass = ( *env )->FindClass( env , "org/keplerproject/luajava/CPtr" ); + + obj = ( *env )->AllocObject( env , tempClass ); + if ( obj ) + { + ( *env )->SetLongField( env , obj , ( *env )->GetFieldID( env , tempClass , "peer", "J" ) , ( jlong ) thr ); + } + return obj; + +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushNil + (JNIEnv * env , jobject jobj , jobject cptr) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + lua_pushnil( L ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushNumber + (JNIEnv * env , jobject jobj , jobject cptr , jdouble number) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + lua_pushnumber( L , ( lua_Number ) number ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushString__Lorg_keplerproject_luajava_CPtr_2Ljava_lang_String_2 + (JNIEnv * env , jobject jobj , jobject cptr , jstring str) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + const char * uniStr; + + uniStr = ( *env )->GetStringUTFChars( env , str , NULL ); + + lua_pushstring( L , uniStr ); + + ( *env )->ReleaseStringUTFChars( env , str , uniStr ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushString__Lorg_keplerproject_luajava_CPtr_2_3BI + (JNIEnv * env , jobject jobj , jobject cptr , jbyteArray bytes , jint n) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + char * cBytes; + + cBytes = ( char * ) ( *env )->GetByteArrayElements( env , bytes, NULL ); + + lua_pushlstring( L , cBytes , n ); + + ( *env )->ReleaseByteArrayElements( env , bytes , cBytes , 0 ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushBoolean + (JNIEnv * env , jobject jobj , jobject cptr , jint jbool) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + lua_pushboolean( L , ( int ) jbool ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1getTable + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + lua_gettable( L , ( int ) idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1getField + (JNIEnv * env , jobject jobj , jobject cptr , jint idx , jstring k) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + const char * uniStr; + uniStr = ( *env )->GetStringUTFChars( env , k , NULL ); + + lua_getfield( L , ( int ) idx , uniStr ); + + ( *env )->ReleaseStringUTFChars( env , k , uniStr ); +} + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1rawGet + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + lua_rawget( L , (int)idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1rawGetI + (JNIEnv * env , jobject jobj , jobject cptr , jint idx, jint n) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + lua_rawgeti( L , idx , n ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1createTable + (JNIEnv * env , jobject jobj , jobject cptr , jint narr , jint nrec) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + lua_createtable( L , ( int ) narr , ( int ) nrec ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1newTable + (JNIEnv * env , jobject jobj , jobject cptr) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + lua_newtable( L ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1getMetaTable + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return lua_getmetatable( L , idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1getFEnv + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + lua_getfenv( L , ( int ) idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1setTable + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + lua_settable( L , ( int ) idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1setField + (JNIEnv * env , jobject jobj , jobject cptr , jint idx , jstring k) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + const char * uniStr; + uniStr = ( *env )->GetStringUTFChars( env , k , NULL ); + + lua_setfield( L , ( int ) idx , uniStr ); + + ( *env )->ReleaseStringUTFChars( env , k , uniStr ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1rawSet + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + lua_rawset( L , (int)idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1rawSetI + (JNIEnv * env , jobject jobj , jobject cptr , jint idx, jint n) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + lua_rawseti( L , idx , n ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1setMetaTable + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return lua_setmetatable( L , idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1setFEnv + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return lua_setfenv( L , idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1call + (JNIEnv * env , jobject jobj , jobject cptr , jint nArgs , jint nResults) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + lua_call( L , nArgs , nResults ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1pcall + (JNIEnv * env , jobject jobj , jobject cptr , jint nArgs , jint nResults , jint errFunc) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_pcall( L , nArgs , nResults , errFunc ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1yield + (JNIEnv * env , jobject jobj , jobject cptr , jint nResults) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_yield( L , nResults ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1resume + (JNIEnv * env , jobject jobj , jobject cptr , jint nArgs) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_resume( L , nArgs ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1status + (JNIEnv * env , jobject jobj , jobject cptr) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_status( L ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1gc + (JNIEnv * env , jobject jobj , jobject cptr , jint what , jint data) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_gc( L , what , data ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1getGcCount + (JNIEnv * env , jobject jobj , jobject cptr) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_getgccount( L ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1next + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_next( L , idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1error + (JNIEnv * env , jobject jobj , jobject cptr) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) lua_error( L ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1concat + (JNIEnv * env , jobject jobj , jobject cptr , jint n) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + lua_concat( L , n ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pop + (JNIEnv * env , jobject jobj , jobject cptr , jint idx) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + lua_pop( L , ( int ) idx ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1setGlobal + (JNIEnv * env , jobject jobj , jobject cptr , jstring name) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + const char * str = ( *env )->GetStringUTFChars( env , name, NULL ); + + lua_setglobal( L , str ); + + ( *env )->ReleaseStringUTFChars( env , name , str ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1getGlobal + (JNIEnv * env , jobject jobj , jobject cptr , jstring name) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + const char * str = ( *env )->GetStringUTFChars( env , name, NULL ); + + lua_getglobal( L , str ); + + ( *env )->ReleaseStringUTFChars( env , name , str ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LdoFile + (JNIEnv * env , jobject jobj , jobject cptr , jstring fileName) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + const char * file = ( *env )->GetStringUTFChars( env , fileName, NULL ); + + int ret; + + ret = luaL_dofile( L , file ); + + ( *env )->ReleaseStringUTFChars( env , fileName , file ); + + return ( jint ) ret; +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LdoString + (JNIEnv * env , jobject jobj , jobject cptr , jstring str) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + const char * utfStr = ( * env )->GetStringUTFChars( env , str , NULL ); + + int ret; + + ret = luaL_dostring( L , utfStr ); + + return ( jint ) ret; +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LgetMetaField + (JNIEnv * env , jobject jobj , jobject cptr , jint obj , jstring e) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + const char * str = ( *env )->GetStringUTFChars( env , e , NULL ); + int ret; + + ret = luaL_getmetafield( L , ( int ) obj , str ); + + ( *env )->ReleaseStringUTFChars( env , e , str ); + + return ( jint ) ret; +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LcallMeta + (JNIEnv * env , jobject jobj , jobject cptr , jint obj , jstring e) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + const char * str = ( *env )->GetStringUTFChars( env , e , NULL ); + int ret; + + ret = luaL_callmeta( L , ( int ) obj, str ); + + ( *env )->ReleaseStringUTFChars( env , e , str ); + + return ( jint ) ret; +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1Ltyperror + (JNIEnv * env , jobject jobj , jobject cptr , jint nArg , jstring tName) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + const char * name = ( *env )->GetStringUTFChars( env , tName , NULL ); + int ret; + + ret = luaL_typerror( L , ( int ) nArg , name ); + + ( *env )->ReleaseStringUTFChars( env , tName , name ); + + return ( jint ) ret; +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LargError + (JNIEnv * env , jobject jobj , jobject cptr , jint numArg , jstring extraMsg) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + const char * msg = ( *env )->GetStringUTFChars( env , extraMsg , NULL ); + int ret; + + ret = luaL_argerror( L , ( int ) numArg , msg ); + + ( *env )->ReleaseStringUTFChars( env , extraMsg , msg ); + + return ( jint ) ret;; +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckString + (JNIEnv * env , jobject jobj , jobject cptr , jint numArg) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + const char * res; + + res = luaL_checkstring( L , ( int ) numArg ); + + return ( *env )->NewStringUTF( env , res ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1LoptString + (JNIEnv * env , jobject jobj , jobject cptr , jint numArg , jstring def) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + const char * d = ( *env )->GetStringUTFChars( env , def , NULL ); + const char * res; + jstring ret; + + res = luaL_optstring( L , ( int ) numArg , d ); + + ret = ( *env )->NewStringUTF( env , res ); + + ( *env )->ReleaseStringUTFChars( env , def , d ); + + return ret; +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jdouble JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckNumber + (JNIEnv * env , jobject jobj , jobject cptr , jint numArg) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jdouble ) luaL_checknumber( L , ( int ) numArg ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jdouble JNICALL Java_org_keplerproject_luajava_LuaState__1LoptNumber + (JNIEnv * env , jobject jobj , jobject cptr , jint numArg , jdouble def) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jdouble ) luaL_optnumber( L , ( int ) numArg , ( lua_Number ) def ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckInteger + (JNIEnv * env , jobject jobj , jobject cptr , jint numArg) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) luaL_checkinteger( L , ( int ) numArg ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LoptInteger + (JNIEnv * env , jobject jobj , jobject cptr , jint numArg , jint def) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) luaL_optinteger( L , ( int ) numArg , ( lua_Integer ) def ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckStack + (JNIEnv * env , jobject jobj , jobject cptr , jint sz , jstring msg) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + const char * m = ( *env )->GetStringUTFChars( env , msg , NULL ); + + luaL_checkstack( L , ( int ) sz , m ); + + ( *env )->ReleaseStringUTFChars( env , msg , m ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckType + (JNIEnv * env , jobject jobj , jobject cptr , jint nArg , jint t) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + luaL_checktype( L , ( int ) nArg , ( int ) t ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckAny + (JNIEnv * env , jobject jobj , jobject cptr , jint nArg) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + luaL_checkany( L , ( int ) nArg ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LnewMetatable + (JNIEnv * env , jobject jobj , jobject cptr , jstring tName) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + const char * name = ( *env )->GetStringUTFChars( env , tName , NULL ); + int ret; + + ret = luaL_newmetatable( L , name ); + + ( *env )->ReleaseStringUTFChars( env , tName , name ); + + return ( jint ) ret;; +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1LgetMetatable + (JNIEnv * env , jobject jobj , jobject cptr , jstring tName) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + const char * name = ( *env )->GetStringUTFChars( env , tName , NULL ); + + luaL_getmetatable( L , name ); + + ( *env )->ReleaseStringUTFChars( env , tName , name ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1Lwhere + (JNIEnv * env , jobject jobj , jobject cptr , jint lvl) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + luaL_where( L , ( int ) lvl ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1Lref + (JNIEnv * env , jobject jobj , jobject cptr , jint t) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) luaL_ref( L , ( int ) t ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1LunRef + (JNIEnv * env , jobject jobj , jobject cptr , jint t , jint ref) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + luaL_unref( L , ( int ) t , ( int ) ref ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LgetN + (JNIEnv * env , jobject jobj , jobject cptr , jint t) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + return ( jint ) luaL_getn( L , ( int ) t ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1LsetN + (JNIEnv * env , jobject jobj , jobject cptr , jint t , jint n) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + + luaL_setn( L , ( int ) t , ( int ) n ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LloadFile + (JNIEnv * env , jobject jobj , jobject cptr , jstring fileName) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + const char * fn = ( *env )->GetStringUTFChars( env , fileName , NULL ); + int ret; + + ret = luaL_loadfile( L , fn ); + + ( *env )->ReleaseStringUTFChars( env , fileName , fn ); + + return ( jint ) ret; +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LloadBuffer + (JNIEnv * env , jobject jobj , jobject cptr , jbyteArray buff , jlong sz , jstring n) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + jbyte * cBuff = ( *env )->GetByteArrayElements( env , buff, NULL ); + const char * name = ( * env )->GetStringUTFChars( env , n , NULL ); + int ret; + + ret = luaL_loadbuffer( L , ( const char * ) cBuff, ( int ) sz, name ); + + ( *env )->ReleaseStringUTFChars( env , n , name ); + + ( *env )->ReleaseByteArrayElements( env , buff , cBuff , 0 ); + + return ( jint ) ret; +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LloadString + (JNIEnv * env , jobject jobj , jobject cptr , jstring str) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + const char * fn = ( *env )->GetStringUTFChars( env , str , NULL ); + int ret; + + ret = luaL_loadstring( L , fn ); + + ( *env )->ReleaseStringUTFChars( env , str , fn ); + + return ( jint ) ret; +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1Lgsub + (JNIEnv * env , jobject jobj , jobject cptr , jstring s , jstring p , jstring r) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + const char * utS = ( *env )->GetStringUTFChars( env , s , NULL ); + const char * utP = ( *env )->GetStringUTFChars( env , p , NULL ); + const char * utR = ( *env )->GetStringUTFChars( env , r , NULL ); + + const char * sub = luaL_gsub( L , utS , utP , utR ); + + ( *env )->ReleaseStringUTFChars( env , s , utS ); + ( *env )->ReleaseStringUTFChars( env , p , utP ); + ( *env )->ReleaseStringUTFChars( env , r , utR ); + + return ( *env )->NewStringUTF( env , sub ); +} + + +/************************************************************************ +* JNI Called function +* Lua Exported Function +************************************************************************/ + +JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1LfindTable + (JNIEnv * env , jobject jobj , jobject cptr , jint idx , jstring fname , jint szhint) +{ + lua_State * L = getStateFromCPtr( env , cptr ); + const char * name = ( *env )->GetStringUTFChars( env , fname , NULL ); + + const char * sub = luaL_findtable( L , ( int ) idx , name , ( int ) szhint ); + + ( *env )->ReleaseStringUTFChars( env , fname , name ); + + return ( *env )->NewStringUTF( env , sub ); +} diff --git a/res/drawable-hdpi/icon.png b/app/src/main/res/drawable-hdpi/icon.png similarity index 100% rename from res/drawable-hdpi/icon.png rename to app/src/main/res/drawable-hdpi/icon.png diff --git a/res/drawable-ldpi/icon.png b/app/src/main/res/drawable-ldpi/icon.png similarity index 100% rename from res/drawable-ldpi/icon.png rename to app/src/main/res/drawable-ldpi/icon.png diff --git a/res/drawable-mdpi/icon.png b/app/src/main/res/drawable-mdpi/icon.png similarity index 100% rename from res/drawable-mdpi/icon.png rename to app/src/main/res/drawable-mdpi/icon.png diff --git a/res/layout/main.xml b/app/src/main/res/layout/main.xml similarity index 100% rename from res/layout/main.xml rename to app/src/main/res/layout/main.xml diff --git a/res/values/strings.xml b/app/src/main/res/values/strings.xml similarity index 100% rename from res/values/strings.xml rename to app/src/main/res/values/strings.xml diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..aa14138 --- /dev/null +++ b/build.gradle @@ -0,0 +1,15 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.1.2' + } +} + +allprojects { + repositories { + jcenter() + } +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..13372aef5e24af05341d49695ee84e5f9b594659 GIT binary patch literal 53636 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ⅅ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 H-+%o-(+5aQ literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..122a0dc --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Mon Dec 28 10:00:20 PST 2015 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..9d82f78 --- /dev/null +++ b/gradlew @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..8a0b282 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/libs/armeabi/libluajava.so b/libs/armeabi/libluajava.so deleted file mode 100755 index d5ed9d671c738755aeeceb6ec6d44c2309d319d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 124136 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≪*J!4-ImdwU_h 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 diff --git a/project.properties b/project.properties deleted file mode 100644 index f049142..0000000 --- a/project.properties +++ /dev/null @@ -1,11 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system use, -# "ant.properties", and override values to adapt the script to your -# project structure. - -# Project target. -target=android-10 diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..e7b4def --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/src/org/keplerproject/luajava/package.html b/src/org/keplerproject/luajava/package.html deleted file mode 100755 index a5b7639..0000000 --- a/src/org/keplerproject/luajava/package.html +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - -

LuaJava is a scripting tool for Java. The goal of this tool is to allow scripts written in Lua to manipulate components developed in Java.

- -
- -

-LuaJava also allows Java to implement an interface using Lua. -This way any interface can be implemented in Lua and passed as parameter to -any method, and when called, the equivalent function will be called in Lua, -and it's result passed back to Java. -

- -

Related Documentation

- -For overviews, tutorials, examples, guides, and tool documentation, please see: - - - - - - From 99314378bcea3f8c30b24ca27ee037d613136c68 Mon Sep 17 00:00:00 2001 From: leon Date: Wed, 17 Aug 2016 11:47:45 +0800 Subject: [PATCH 2/2] update lua to 5.3.3 --- app/build.gradle | 7 + app/src/main/.gitignore | 1 + .../java/org/keplerproject/luajava/CPtr.java | 47 +- .../org/keplerproject/luajava/Console.java | 96 +- .../keplerproject/luajava/JavaFunction.java | 103 +- .../keplerproject/luajava/LuaException.java | 40 +- .../luajava/LuaInvocationHandler.java | 80 +- .../org/keplerproject/luajava/LuaJavaAPI.java | 164 +- .../org/keplerproject/luajava/LuaObject.java | 38 +- .../org/keplerproject/luajava/LuaState.java | 1185 ++++++------ .../luajava/LuaStateFactory.java | 86 +- .../main/java/sk/kottman/androlua/Main.java | 511 +++--- app/src/main/jni/Application.mk | 28 + app/src/main/jni/lua/Android.mk | 9 +- app/src/main/jni/lua/Makefile | 197 ++ app/src/main/jni/lua/lapi.c | 1015 +++++++---- app/src/main/jni/lua/lapi.h | 14 +- app/src/main/jni/lua/lauxlib.c | 1081 +++++++---- app/src/main/jni/lua/lauxlib.h | 204 ++- app/src/main/jni/lua/lbaselib.c | 647 +++---- app/src/main/jni/lua/lbitlib.c | 233 +++ app/src/main/jni/lua/lcode.c | 1042 +++++++---- app/src/main/jni/lua/lcode.h | 32 +- app/src/main/jni/lua/lcorolib.c | 168 ++ app/src/main/jni/lua/lctype.c | 55 + app/src/main/jni/lua/lctype.h | 95 + app/src/main/jni/lua/ldblib.c | 380 ++-- app/src/main/jni/lua/ldebug.c | 777 ++++---- app/src/main/jni/lua/ldebug.h | 32 +- app/src/main/jni/lua/ldo.c | 847 ++++++--- app/src/main/jni/lua/ldo.h | 47 +- app/src/main/jni/lua/ldump.c | 295 +-- app/src/main/jni/lua/lfunc.c | 153 +- app/src/main/jni/lua/lfunc.h | 39 +- app/src/main/jni/lua/lgc.c | 1434 ++++++++++----- app/src/main/jni/lua/lgc.h | 167 +- app/src/main/jni/lua/linit.c | 48 +- app/src/main/jni/lua/liolib.c | 666 ++++--- app/src/main/jni/lua/llex.c | 489 +++-- app/src/main/jni/lua/llex.h | 38 +- app/src/main/jni/lua/llimits.h | 275 ++- app/src/main/jni/lua/lmathlib.c | 356 ++-- app/src/main/jni/lua/lmem.c | 58 +- app/src/main/jni/lua/lmem.h | 40 +- app/src/main/jni/lua/loadlib.c | 739 ++++---- app/src/main/jni/lua/lobject.c | 513 ++++-- app/src/main/jni/lua/lobject.h | 492 +++-- app/src/main/jni/lua/lopcodes.c | 54 +- app/src/main/jni/lua/lopcodes.h | 131 +- app/src/main/jni/lua/loslib.c | 302 ++- app/src/main/jni/lua/lparser.c | 1109 ++++++++---- app/src/main/jni/lua/lparser.h | 127 +- app/src/main/jni/lua/lprefix.h | 45 + app/src/main/jni/lua/lstate.c | 325 +++- app/src/main/jni/lua/lstate.h | 217 ++- app/src/main/jni/lua/lstring.c | 275 ++- app/src/main/jni/lua/lstring.h | 32 +- app/src/main/jni/lua/lstrlib.c | 1297 ++++++++++--- app/src/main/jni/lua/ltable.c | 557 +++--- app/src/main/jni/lua/ltable.h | 34 +- app/src/main/jni/lua/ltablib.c | 473 +++-- app/src/main/jni/lua/ltm.c | 122 +- app/src/main/jni/lua/ltm.h | 34 +- app/src/main/jni/lua/lua.c | 609 +++++++ app/src/main/jni/lua/lua.h | 314 ++-- app/src/main/jni/lua/lua.hpp | 9 + app/src/main/jni/lua/luac.c | 449 +++++ app/src/main/jni/lua/luaconf.h | 962 +++++----- app/src/main/jni/lua/lualib.h | 31 +- app/src/main/jni/lua/lundump.c | 440 +++-- app/src/main/jni/lua/lundump.h | 32 +- app/src/main/jni/lua/lutf8lib.c | 256 +++ app/src/main/jni/lua/lvm.c | 1613 +++++++++++------ app/src/main/jni/lua/lvm.h | 107 +- app/src/main/jni/lua/lzio.c | 52 +- app/src/main/jni/lua/lzio.h | 17 +- app/src/main/jni/luajava/Android.mk | 4 + app/src/main/jni/luajava/log.h | 17 + app/src/main/jni/luajava/luajava.c | 579 +++--- app/src/main/jni/luajava/luajava.h | 219 +++ app/src/main/libs/armeabi-v7a/libluajava.so | Bin 0 -> 142032 bytes 81 files changed, 17018 insertions(+), 8889 deletions(-) create mode 100644 app/src/main/.gitignore create mode 100644 app/src/main/jni/Application.mk create mode 100644 app/src/main/jni/lua/Makefile create mode 100644 app/src/main/jni/lua/lbitlib.c create mode 100644 app/src/main/jni/lua/lcorolib.c create mode 100644 app/src/main/jni/lua/lctype.c create mode 100644 app/src/main/jni/lua/lctype.h create mode 100644 app/src/main/jni/lua/lprefix.h create mode 100644 app/src/main/jni/lua/lua.c create mode 100644 app/src/main/jni/lua/lua.hpp create mode 100644 app/src/main/jni/lua/luac.c create mode 100644 app/src/main/jni/lua/lutf8lib.c create mode 100644 app/src/main/jni/luajava/log.h create mode 100644 app/src/main/jni/luajava/luajava.h create mode 100755 app/src/main/libs/armeabi-v7a/libluajava.so diff --git a/app/build.gradle b/app/build.gradle index 016360b..b6376fd 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,4 +16,11 @@ android { proguardFiles 'proguard.cfg' } } + + sourceSets { + main { + jni.srcDirs = [] + jniLibs.srcDirs = ["src/main/libs"] + } + } } diff --git a/app/src/main/.gitignore b/app/src/main/.gitignore new file mode 100644 index 0000000..28a478f --- /dev/null +++ b/app/src/main/.gitignore @@ -0,0 +1 @@ +/obj diff --git a/app/src/main/java/org/keplerproject/luajava/CPtr.java b/app/src/main/java/org/keplerproject/luajava/CPtr.java index 08956e9..5110e22 100644 --- a/app/src/main/java/org/keplerproject/luajava/CPtr.java +++ b/app/src/main/java/org/keplerproject/luajava/CPtr.java @@ -27,45 +27,44 @@ /** * An abstraction for a C pointer data type. A CPtr instance represents, on * the Java side, a C pointer. The C pointer could be any type of C - * pointer. + * pointer. */ -public class CPtr -{ - +public class CPtr { + /** * Compares this CPtr to the specified object. * * @param other a CPtr - * @return true if the class of this CPtr object and the - * class of other are exactly equal, and the C - * pointers being pointed to by these objects are also - * equal. Returns false otherwise. + * @return true if the class of this CPtr object and the + * class of other are exactly equal, and the C + * pointers being pointed to by these objects are also + * equal. Returns false otherwise. */ - public boolean equals(Object other) - { - if (other == null) - return false; - if (other == this) - return true; - if (CPtr.class != other.getClass()) - return false; - return peer == ((CPtr)other).peer; - } + public boolean equals(Object other) { + if (other == null) + return false; + if (other == this) + return true; + if (CPtr.class != other.getClass()) + return false; + return peer == ((CPtr) other).peer; + } /* Pointer value of the real C pointer. Use long to be 64-bit safe. */ private long peer; - + /** * Gets the value of the C pointer abstraction + * * @return long */ - protected long getPeer() - { - return peer; + protected long getPeer() { + return peer; } /* No-args constructor. */ - CPtr() {} - + CPtr() { + } + } diff --git a/app/src/main/java/org/keplerproject/luajava/Console.java b/app/src/main/java/org/keplerproject/luajava/Console.java index ee90ca6..19b223d 100644 --- a/app/src/main/java/org/keplerproject/luajava/Console.java +++ b/app/src/main/java/org/keplerproject/luajava/Console.java @@ -31,70 +31,58 @@ * Simple LuaJava console. * This is also an example on how to use the Java side of LuaJava and how to startup * a LuaJava application. - * + * * @author Thiago Ponte */ -public class Console -{ +public class Console { - /** - * Creates a console for user interaction. - * - * @param args names of the lua files to be executed - */ - public static void main(String[] args) - { - try - { - LuaState L = LuaStateFactory.newLuaState(); - L.openLibs(); + /** + * Creates a console for user interaction. + * + * @param args names of the lua files to be executed + */ + public static void main(String[] args) { + try { + LuaState L = LuaStateFactory.newLuaState(); + L.openLibs(); - if (args.length > 0) - { - for (int i = 0; i < args.length; i++) - { - int res = L.LloadFile(args[i]); - if (res == 0) - { - res = L.pcall(0, 0, 0); - } - if (res != 0) - { - throw new LuaException("Error on file: " + args[i] + ". " + L.toString(-1)); - } - } + if (args.length > 0) { + for (int i = 0; i < args.length; i++) { + int res = L.LloadFile(args[i]); + if (res == 0) { + res = L.pcall(0, 0, 0); + } + if (res != 0) { + throw new LuaException("Error on file: " + args[i] + ". " + L.toString(-1)); + } + } - return; - } + return; + } - System.out.println("API Lua Java - console mode."); + System.out.println("API Lua Java - console mode."); - BufferedReader inp = new BufferedReader(new InputStreamReader(System.in)); + BufferedReader inp = new BufferedReader(new InputStreamReader(System.in)); - String line; + String line; - System.out.print("> "); - while ((line = inp.readLine()) != null && !line.equals("exit")) - { - int ret = L.LloadBuffer(line.getBytes(), "from console"); - if (ret == 0) - { - ret = L.pcall(0, 0, 0); - } - if (ret != 0) - { - System.err.println("Error on line: " + line); - System.err.println(L.toString(-1)); - } System.out.print("> "); - } + while ((line = inp.readLine()) != null && !line.equals("exit")) { + int ret = L.LloadBuffer(line.getBytes(), "from console"); + if (ret == 0) { + ret = L.pcall(0, 0, 0); + } + if (ret != 0) { + System.err.println("Error on line: " + line); + System.err.println(L.toString(-1)); + } + System.out.print("> "); + } - L.close(); - } - catch (Exception e) - { - e.printStackTrace(); - } + L.close(); + } catch (Exception e) { + e.printStackTrace(); + } - } + } } \ No newline at end of file diff --git a/app/src/main/java/org/keplerproject/luajava/JavaFunction.java b/app/src/main/java/org/keplerproject/luajava/JavaFunction.java index edabfa1..7d96de0 100644 --- a/app/src/main/java/org/keplerproject/luajava/JavaFunction.java +++ b/app/src/main/java/org/keplerproject/luajava/JavaFunction.java @@ -26,61 +26,60 @@ /** * JavaFunction is a class that can be used to implement a Lua function in Java. - * JavaFunction is an abstract class, so in order to use it you must extend this - * class and implement the execute method. This execute + * JavaFunction is an abstract class, so in order to use it you must extend this + * class and implement the execute method. This execute * method is the method that will be called when you call the function from Lua. * To register the JavaFunction in Lua use the method register(String name). */ -public abstract class JavaFunction -{ - - /** - * This is the state in which this function will exist. - */ - protected LuaState L; - - /** - * This method is called from Lua. Any parameters can be taken with - * getParam. A reference to the JavaFunctionWrapper itself is - * always the first parameter received. Values passed back as results - * of the function must be pushed onto the stack. - * @return The number of values pushed onto the stack. - */ - public abstract int execute() throws LuaException; - - /** - * Constructor that receives a LuaState. - * @param L LuaState object associated with this JavaFunction object - */ - public JavaFunction(LuaState L) - { - this.L = L; - } +public abstract class JavaFunction { - /** - * Returns a parameter received from Lua. Parameters are numbered from 1. - * A reference to the JavaFunction itself is always the first parameter - * received (the same as this). - * @param idx Index of the parameter. - * @return Reference to parameter. - * @see LuaObject - */ - public LuaObject getParam(int idx) - { - return L.getLuaObject(idx); - } + /** + * This is the state in which this function will exist. + */ + protected LuaState L; - /** - * Register a JavaFunction with a given name. This method registers in a - * global variable the JavaFunction specified. - * @param name name of the function. - */ - public void register(String name) throws LuaException - { - synchronized (L) - { - L.pushJavaFunction(this); - L.setGlobal(name); - } - } + /** + * This method is called from Lua. Any parameters can be taken with + * getParam. A reference to the JavaFunctionWrapper itself is + * always the first parameter received. Values passed back as results + * of the function must be pushed onto the stack. + * + * @return The number of values pushed onto the stack. + */ + public abstract int execute() throws LuaException; + + /** + * Constructor that receives a LuaState. + * + * @param L LuaState object associated with this JavaFunction object + */ + public JavaFunction(LuaState L) { + this.L = L; + } + + /** + * Returns a parameter received from Lua. Parameters are numbered from 1. + * A reference to the JavaFunction itself is always the first parameter + * received (the same as this). + * + * @param idx Index of the parameter. + * @return Reference to parameter. + * @see LuaObject + */ + public LuaObject getParam(int idx) { + return L.getLuaObject(idx); + } + + /** + * Register a JavaFunction with a given name. This method registers in a + * global variable the JavaFunction specified. + * + * @param name name of the function. + */ + public void register(String name) throws LuaException { + synchronized (L) { + L.pushJavaFunction(this); + L.setGlobal(name); + } + } } diff --git a/app/src/main/java/org/keplerproject/luajava/LuaException.java b/app/src/main/java/org/keplerproject/luajava/LuaException.java index 8b36920..4075756 100644 --- a/app/src/main/java/org/keplerproject/luajava/LuaException.java +++ b/app/src/main/java/org/keplerproject/luajava/LuaException.java @@ -26,29 +26,25 @@ /** * LuaJava exception - * - * @author Thiago Ponte * + * @author Thiago Ponte */ -public class LuaException extends Exception -{ - /** - * - */ - private static final long serialVersionUID = 1L; +public class LuaException extends Exception { + /** + * + */ + private static final long serialVersionUID = 1L; + + public LuaException(String str) { + super(str); + } - public LuaException(String str) - { - super(str); - } - - /** - * Will work only on Java 1.4 or later. - * To work with Java 1.3, comment the first line and uncomment the second one. - */ - public LuaException(Exception e) - { - super((e.getCause() != null) ? e.getCause() : e); - //super(e.getMessage()); - } + /** + * Will work only on Java 1.4 or later. + * To work with Java 1.3, comment the first line and uncomment the second one. + */ + public LuaException(Exception e) { + super((e.getCause() != null) ? e.getCause() : e); + //super(e.getMessage()); + } } \ No newline at end of file diff --git a/app/src/main/java/org/keplerproject/luajava/LuaInvocationHandler.java b/app/src/main/java/org/keplerproject/luajava/LuaInvocationHandler.java index 1b90edb..0bc77c7 100644 --- a/app/src/main/java/org/keplerproject/luajava/LuaInvocationHandler.java +++ b/app/src/main/java/org/keplerproject/luajava/LuaInvocationHandler.java @@ -32,53 +32,45 @@ * This class is used in the LuaJava's proxy system. * When a proxy object is accessed, the method invoked is * called from Lua + * * @author Rizzato * @author Thiago Ponte */ -public class LuaInvocationHandler implements InvocationHandler -{ - private LuaObject obj; +public class LuaInvocationHandler implements InvocationHandler { + private LuaObject obj; + + + public LuaInvocationHandler(LuaObject obj) { + this.obj = obj; + } + + /** + * Function called when a proxy object function is invoked. + */ + public Object invoke(Object proxy, Method method, Object[] args) throws LuaException { + synchronized (obj.L) { + String methodName = method.getName(); + LuaObject func = obj.getField(methodName); + + if (func.isNil()) { + return null; + } + + Class retType = method.getReturnType(); + Object ret; - - public LuaInvocationHandler(LuaObject obj) - { - this.obj = obj; - } - - /** - * Function called when a proxy object function is invoked. - */ - public Object invoke(Object proxy, Method method, Object[] args) throws LuaException - { - synchronized(obj.L) - { - String methodName = method.getName(); - LuaObject func = obj.getField(methodName); - - if ( func.isNil() ) - { - return null; - } - - Class retType = method.getReturnType(); - Object ret; + // Checks if returned type is void. if it is returns null. + if (retType.equals(Void.class) || retType.equals(void.class)) { + func.call(args, 0); + ret = null; + } else { + ret = func.call(args, 1)[0]; + if (ret != null && ret instanceof Double) { + ret = LuaState.convertLuaNumber((Double) ret, retType); + } + } - // Checks if returned type is void. if it is returns null. - if ( retType.equals( Void.class ) || retType.equals( void.class ) ) - { - func.call( args , 0 ); - ret = null; - } - else - { - ret = func.call(args, 1)[0]; - if( ret != null && ret instanceof Double ) - { - ret = LuaState.convertLuaNumber((Double) ret, retType); - } - } - - return ret; - } - } + return ret; + } + } } diff --git a/app/src/main/java/org/keplerproject/luajava/LuaJavaAPI.java b/app/src/main/java/org/keplerproject/luajava/LuaJavaAPI.java index a60c123..4c07def 100644 --- a/app/src/main/java/org/keplerproject/luajava/LuaJavaAPI.java +++ b/app/src/main/java/org/keplerproject/luajava/LuaJavaAPI.java @@ -31,7 +31,7 @@ /** * Class that contains functions accessed by lua. - * + * * @author Thiago Ponte */ public final class LuaJavaAPI @@ -43,14 +43,14 @@ private LuaJavaAPI() /** * Java implementation of the metamethod __index - * + * * @param luaState int that indicates the state used * @param obj Object to be indexed * @param methodName the name of the method * @return number of returned objects */ public static int objectIndex(int luaState, Object obj, String methodName) - throws LuaException + throws LuaException { LuaState L = LuaStateFactory.getExistingState(luaState); @@ -121,7 +121,7 @@ public static int objectIndex(int luaState, Object obj, String methodName) { method.setAccessible(true); } - + if (obj instanceof Class) { ret = method.invoke(null, objs); @@ -153,7 +153,7 @@ public static int objectIndex(int luaState, Object obj, String methodName) * Java function to be called when a java Class metamethod __index is called. * This function returns 1 if there is a field with searchName and 2 if there * is a method if the searchName - * + * * @param luaState int that represents the state to be used * @param clazz class to be indexed * @param searchName name of the field or method to be accessed @@ -161,7 +161,7 @@ public static int objectIndex(int luaState, Object obj, String methodName) * @throws LuaException */ public static int classIndex(int luaState, Class clazz, String searchName) - throws LuaException + throws LuaException { synchronized (LuaStateFactory.getExistingState(luaState)) { @@ -187,14 +187,14 @@ public static int classIndex(int luaState, Class clazz, String searchName) /** * Pushes a new instance of a java Object of the type className - * + * * @param luaState int that represents the state to be used * @param className name of the class * @return number of returned objects * @throws LuaException */ public static int javaNewInstance(int luaState, String className) - throws LuaException + throws LuaException { LuaState L = LuaStateFactory.getExistingState(luaState); @@ -219,7 +219,7 @@ public static int javaNewInstance(int luaState, String className) /** * javaNew returns a new instance of a given clazz - * + * * @param luaState int that represents the state to be used * @param clazz class to be instanciated * @return number of returned objects @@ -249,10 +249,10 @@ public static int javaNew(int luaState, Class clazz) throws LuaException * @throws LuaException */ public static int javaLoadLib(int luaState, String className, String methodName) - throws LuaException + throws LuaException { LuaState L = LuaStateFactory.getExistingState(luaState); - + synchronized (L) { Class clazz; @@ -269,7 +269,7 @@ public static int javaLoadLib(int luaState, String className, String methodName) { Method mt = clazz.getMethod(methodName, new Class[] {LuaState.class}); Object obj = mt.invoke(null, new Object[] {L}); - + if (obj != null && obj instanceof Integer) { return ((Integer) obj).intValue(); @@ -285,82 +285,82 @@ public static int javaLoadLib(int luaState, String className, String methodName) } private static Object getObjInstance(LuaState L, Class clazz) - throws LuaException + throws LuaException { synchronized (L) { - int top = L.getTop(); - - Object[] objs = new Object[top - 1]; - - Constructor[] constructors = clazz.getConstructors(); - Constructor constructor = null; - - // gets method and arguments - for (int i = 0; i < constructors.length; i++) - { - Class[] parameters = constructors[i].getParameterTypes(); - if (parameters.length != top - 1) - continue; - - boolean okConstruc = true; - - for (int j = 0; j < parameters.length; j++) - { - try - { - objs[j] = compareTypes(L, parameters[j], j + 2); - } - catch (Exception e) - { - okConstruc = false; - break; - } - } - - if (okConstruc) - { - constructor = constructors[i]; - break; - } - - } - - // If method is null means there isn't one receiving the given arguments - if (constructor == null) - { - throw new LuaException("Invalid method call. No such method."); - } - - Object ret; - try - { - ret = constructor.newInstance(objs); - } - catch (Exception e) - { - throw new LuaException(e); - } - - if (ret == null) - { - throw new LuaException("Couldn't instantiate java Object"); - } - - return ret; + int top = L.getTop(); + + Object[] objs = new Object[top - 1]; + + Constructor[] constructors = clazz.getConstructors(); + Constructor constructor = null; + + // gets method and arguments + for (int i = 0; i < constructors.length; i++) + { + Class[] parameters = constructors[i].getParameterTypes(); + if (parameters.length != top - 1) + continue; + + boolean okConstruc = true; + + for (int j = 0; j < parameters.length; j++) + { + try + { + objs[j] = compareTypes(L, parameters[j], j + 2); + } + catch (Exception e) + { + okConstruc = false; + break; + } + } + + if (okConstruc) + { + constructor = constructors[i]; + break; + } + + } + + // If method is null means there isn't one receiving the given arguments + if (constructor == null) + { + throw new LuaException("Invalid method call. No such method."); + } + + Object ret; + try + { + ret = constructor.newInstance(objs); + } + catch (Exception e) + { + throw new LuaException(e); + } + + if (ret == null) + { + throw new LuaException("Couldn't instantiate java Object"); + } + + return ret; } } /** * Checks if there is a field on the obj with the given name - * + * * @param luaState int that represents the state to be used * @param obj object to be inspected * @param fieldName name of the field to be inpected * @return number of returned objects */ public static int checkField(int luaState, Object obj, String fieldName) - throws LuaException + throws LuaException { LuaState L = LuaStateFactory.getExistingState(luaState); @@ -415,7 +415,7 @@ public static int checkField(int luaState, Object obj, String fieldName) /** * Checks to see if there is a method with the given name. - * + * * @param luaState int that represents the state to be used * @param obj object to be inspected * @param methodName name of the field to be inpected @@ -452,14 +452,14 @@ public static int checkMethod(int luaState, Object obj, String methodName) /** * Function that creates an object proxy and pushes it into the stack - * + * * @param luaState int that represents the state to be used * @param implem interfaces implemented separated by comma (,) * @return number of returned objects * @throws LuaException */ public static int createProxyObject(int luaState, String implem) - throws LuaException + throws LuaException { LuaState L = LuaStateFactory.getExistingState(luaState); @@ -469,7 +469,7 @@ public static int createProxyObject(int luaState, String implem) { if (!(L.isTable(2))) throw new LuaException( - "Parameter is not a table. Can't create proxy."); + "Parameter is not a table. Can't create proxy."); LuaObject luaObj = L.getLuaObject(2); @@ -486,7 +486,7 @@ public static int createProxyObject(int luaState, String implem) } private static Object compareTypes(LuaState L, Class parameter, int idx) - throws LuaException + throws LuaException { boolean okType = true; Object obj = null; @@ -506,7 +506,7 @@ else if (!parameter.isAssignableFrom(Boolean.class)) } obj = new Boolean(L.toBoolean(idx)); } - else if (L.type(idx) == LuaState.LUA_TSTRING.intValue()) + else if (L.type(idx) == LuaState.LUA_TSTRING) { if (!parameter.isAssignableFrom(String.class)) { @@ -539,10 +539,10 @@ else if (L.isTable(idx)) obj = L.getLuaObject(idx); } } - else if (L.type(idx) == LuaState.LUA_TNUMBER.intValue()) + else if (L.type(idx) == LuaState.LUA_TNUMBER) { Double db = new Double(L.toNumber(idx)); - + obj = LuaState.convertLuaNumber(db, parameter); if (obj == null) { diff --git a/app/src/main/java/org/keplerproject/luajava/LuaObject.java b/app/src/main/java/org/keplerproject/luajava/LuaObject.java index e2fe116..b502cc6 100644 --- a/app/src/main/java/org/keplerproject/luajava/LuaObject.java +++ b/app/src/main/java/org/keplerproject/luajava/LuaObject.java @@ -40,14 +40,14 @@ * * The LuaObject will represent only the object itself, not a variable or a stack index, so when you change a string, * remember that strings are immutable objects in Lua, and the LuaObject you have will represent the old one. - * + * *

Proxies

- * + * * LuaJava allows you to implement a class in Lua, like said before. If you want to create this proxy from Java, you * should have a LuaObject representing the table that has the functions that implement the interface. From this * LuaObject you can call the createProxy(String implements). This method receives the string with the * name of the interfaces implemented by the object separated by comma. - * + * * @author Rizzato * @author Thiago Ponte */ @@ -59,7 +59,7 @@ public class LuaObject /** * Creates a reference to an object in the variable globalName - * + * * @param L * @param globalName */ @@ -76,7 +76,7 @@ protected LuaObject(LuaState L, String globalName) /** * Creates a reference to an object inside another object - * + * * @param parent * The Lua Table or Userdata that contains the Field. * @param name @@ -104,7 +104,7 @@ protected LuaObject(LuaObject parent, String name) throws LuaException /** * This constructor creates a LuaObject from a table that is indexed by a number. - * + * * @param parent * The Lua Table or Userdata that contains the Field. * @param name @@ -131,7 +131,7 @@ protected LuaObject(LuaObject parent, Number name) throws LuaException /** * This constructor creates a LuaObject from a table that is indexed by a LuaObject. - * + * * @param parent * The Lua Table or Userdata that contains the Field. * @param name @@ -161,7 +161,7 @@ protected LuaObject(LuaObject parent, LuaObject name) throws LuaException /** * Creates a reference to an object in the given index of the stack - * + * * @param L * @param index * of the object on the lua stack @@ -186,7 +186,7 @@ public LuaState getLuaState() /** * Creates the reference to the object in the registry table - * + * * @param index * of the object on the lua stack */ @@ -195,7 +195,7 @@ private void registerValue(int index) synchronized (L) { L.pushValue(index); - int key = L.Lref(LuaState.LUA_REGISTRYINDEX.intValue()); + int key = L.Lref(LuaState.LUA_REGISTRYINDEX); ref = new Integer(key); } } @@ -207,7 +207,7 @@ protected void finalize() synchronized (L) { if (L.getCPtrPeer() != 0) - L.LunRef(LuaState.LUA_REGISTRYINDEX.intValue(), ref.intValue()); + L.LunRef(LuaState.LUA_REGISTRYINDEX, ref.intValue()); } } catch (Exception e) @@ -221,7 +221,7 @@ protected void finalize() */ public void push() { - L.rawGetI(LuaState.LUA_REGISTRYINDEX.intValue(), ref.intValue()); + L.rawGetI(LuaState.LUA_REGISTRYINDEX, ref.intValue()); } public boolean isNil() @@ -389,7 +389,7 @@ public LuaObject getField(String field) throws LuaException /** * Calls the object represented by this using Lua function pcall. - * + * * @param args - * Call arguments * @param nres - @@ -432,15 +432,15 @@ public Object[] call(Object[] args, int nres) throws LuaException else str = ""; - if (err == LuaState.LUA_ERRRUN.intValue()) + if (err == LuaState.LUA_ERRRUN) { str = "Runtime error. " + str; } - else if (err == LuaState.LUA_ERRMEM.intValue()) + else if (err == LuaState.LUA_ERRMEM) { str = "Memory allocation error. " + str; } - else if (err == LuaState.LUA_ERRERR.intValue()) + else if (err == LuaState.LUA_ERRERR) { str = "Error while running the error handler function. " + str; } @@ -452,7 +452,7 @@ else if (err == LuaState.LUA_ERRERR.intValue()) throw new LuaException(str); } - if (nres == LuaState.LUA_MULTRET.intValue()) + if (nres == LuaState.LUA_MULTRET) nres = L.getTop() - top; if (L.getTop() - top < nres) { @@ -472,7 +472,7 @@ else if (err == LuaState.LUA_ERRERR.intValue()) /** * Calls the object represented by this using Lua function pcall. Returns 1 object - * + * * @param args - * Call arguments * @return Object - Returned Object @@ -519,7 +519,7 @@ else if (isJavaFunction()) /** * Function that creates a java proxy to the object represented by this - * + * * @param implem * Interfaces that are implemented, separated by , */ diff --git a/app/src/main/java/org/keplerproject/luajava/LuaState.java b/app/src/main/java/org/keplerproject/luajava/LuaState.java index 2868953..8594fbd 100644 --- a/app/src/main/java/org/keplerproject/luajava/LuaState.java +++ b/app/src/main/java/org/keplerproject/luajava/LuaState.java @@ -27,69 +27,46 @@ /** * LuaState if the main class of LuaJava for the Java developer. * LuaState is a mapping of most of Lua's C API functions. - * LuaState also provides many other functions that will be used to manipulate + * LuaState also provides many other functions that will be used to manipulate * objects between Lua and Java. + * * @author Thiago Ponte */ -public class LuaState -{ - private final static String LUAJAVA_LIB = "luajava"; - - final public static Integer LUA_GLOBALSINDEX = new Integer(-10002); - final public static Integer LUA_REGISTRYINDEX = new Integer(-10000); - - final public static Integer LUA_TNONE = new Integer(-1); - final public static Integer LUA_TNIL = new Integer(0); - final public static Integer LUA_TBOOLEAN = new Integer(1); - final public static Integer LUA_TLIGHTUSERDATA = new Integer(2); - final public static Integer LUA_TNUMBER = new Integer(3); - final public static Integer LUA_TSTRING = new Integer(4); - final public static Integer LUA_TTABLE = new Integer(5); - final public static Integer LUA_TFUNCTION = new Integer(6); - final public static Integer LUA_TUSERDATA = new Integer(7); - final public static Integer LUA_TTHREAD = new Integer(8); +public class LuaState { + + final public static int LUA_REGISTRYINDEX; + + final public static int LUA_TNONE = -1; + final public static int LUA_TNIL = 0; + final public static int LUA_TBOOLEAN = 1; + final public static int LUA_TLIGHTUSERDATA = 2; + final public static int LUA_TNUMBER = 3; + final public static int LUA_TSTRING = 4; + final public static int LUA_TTABLE = 5; + final public static int LUA_TFUNCTION = 6; + final public static int LUA_TUSERDATA = 7; + final public static int LUA_TTHREAD = 8; + final public static int LUA_NUMTAGS = 9; + + /** minimum Lua stack available to a C function */ + final public static int LUA_MINSTACK = 20; /** * Specifies that an unspecified (multiple) number of return arguments * will be returned by a call. */ - final public static Integer LUA_MULTRET = new Integer(-1); - - /* - * error codes for `lua_load' and `lua_pcall' - */ - /** - * a runtime error. - */ - final public static Integer LUA_ERRRUN = new Integer(1); - - /** - * - */ - final public static Integer LUA_YIELD = new Integer(2); - - /** - * syntax error during pre-compilation. - */ - final public static Integer LUA_ERRSYNTAX = new Integer(3); - - /** - * memory allocation error. For such errors, Lua does not call - * the error handler function. - */ - final public static Integer LUA_ERRMEM = new Integer(4); - - /** - * error while running the error handler function. - */ - final public static Integer LUA_ERRERR = new Integer(5); + final public static int LUA_MULTRET = -1; - /** - * Opens the library containing the luajava API - */ - static - { - System.loadLibrary(LUAJAVA_LIB); + final public static int LUA_OK = 0; + final public static int LUA_YIELD = 1; + final public static int LUA_ERRRUN = 2; + final public static int LUA_ERRSYNTAX = 3; + final public static int LUA_ERRMEM = 4; + final public static int LUA_ERRGCMM = 5; + final public static int LUA_ERRERR = 6; + + static { + LUA_REGISTRYINDEX = _registryIndex(); } private CPtr luaState; @@ -98,738 +75,679 @@ public class LuaState /** * Constructor to instance a new LuaState and initialize it with LuaJava's functions + * * @param stateId */ - protected LuaState(int stateId) - { - luaState = _open(); - luajava_open(luaState, stateId); + protected LuaState(int stateId) { + luaState = (CPtr)_open(); + _luajavaOpen(luaState, stateId); this.stateId = stateId; } /** * Receives a existing state and initializes it + * * @param luaState */ - protected LuaState(CPtr luaState) - { + protected LuaState(CPtr luaState) { this.luaState = luaState; this.stateId = LuaStateFactory.insertLuaState(this); - luajava_open(luaState, stateId); + _luajavaOpen(luaState, stateId); } /** * Closes state and removes the object from the LuaStateFactory */ - public synchronized void close() - { + public synchronized void close() { LuaStateFactory.removeLuaState(stateId); _close(luaState); this.luaState = null; } - + /** * Returns true if state is closed. */ - public synchronized boolean isClosed() - { + public synchronized boolean isClosed() { return luaState == null; } /** * Return the long representing the LuaState pointer + * * @return long */ - public long getCPtrPeer() - { - return (luaState != null)? luaState.getPeer() : 0; + public long getCPtrPeer() { + return (luaState != null) ? luaState.getPeer() : 0; } - /********************* Lua Native Interface *************************/ + /********************* + * Lua Native Interface + *************************/ + + private static native int _registryIndex(); + + private synchronized native Object _open(); - private synchronized native CPtr _open(); private synchronized native void _close(CPtr ptr); - private synchronized native CPtr _newthread(CPtr ptr); + + private synchronized native Object _newthread(CPtr ptr); // Stack manipulation - private synchronized native int _getTop(CPtr ptr); + private synchronized native int _getTop(CPtr ptr); + private synchronized native void _setTop(CPtr ptr, int idx); + private synchronized native void _pushValue(CPtr ptr, int idx); + private synchronized native void _remove(CPtr ptr, int idx); + private synchronized native void _insert(CPtr ptr, int idx); + private synchronized native void _replace(CPtr ptr, int idx); - private synchronized native int _checkStack(CPtr ptr, int sz); - + + private synchronized native int _checkStack(CPtr ptr, int sz); + private synchronized native void _xmove(CPtr from, CPtr to, int n); // Access functions - private synchronized native int _isNumber(CPtr ptr, int idx); - private synchronized native int _isString(CPtr ptr, int idx); - private synchronized native int _isCFunction(CPtr ptr, int idx); - private synchronized native int _isUserdata(CPtr ptr, int idx); - private synchronized native int _type(CPtr ptr, int idx); + private synchronized native int _isNumber(CPtr ptr, int idx); + + private synchronized native int _isString(CPtr ptr, int idx); + + private synchronized native int _isCFunction(CPtr ptr, int idx); + + private synchronized native int _isUserdata(CPtr ptr, int idx); + + private synchronized native int _type(CPtr ptr, int idx); + private synchronized native String _typeName(CPtr ptr, int tp); private synchronized native int _equal(CPtr ptr, int idx1, int idx2); + private synchronized native int _rawequal(CPtr ptr, int idx1, int idx2); + private synchronized native int _lessthan(CPtr ptr, int idx1, int idx2); private synchronized native double _toNumber(CPtr ptr, int idx); - private synchronized native int _toInteger(CPtr ptr, int idx); - private synchronized native int _toBoolean(CPtr ptr, int idx); + + private synchronized native int _toInteger(CPtr ptr, int idx); + + private synchronized native int _toBoolean(CPtr ptr, int idx); + private synchronized native String _toString(CPtr ptr, int idx); - private synchronized native int _objlen(CPtr ptr, int idx); - private synchronized native CPtr _toThread(CPtr ptr, int idx); + + private synchronized native int _objlen(CPtr ptr, int idx); + + private synchronized native Object _toThread(CPtr ptr, int idx); // Push functions private synchronized native void _pushNil(CPtr ptr); + private synchronized native void _pushNumber(CPtr ptr, double number); + private synchronized native void _pushInteger(CPtr ptr, int integer); + private synchronized native void _pushString(CPtr ptr, String str); - private synchronized native void _pushString(CPtr ptr, byte[] bytes, int n); + + private synchronized native void _pushString2(CPtr ptr, byte[] bytes, int n); + private synchronized native void _pushBoolean(CPtr ptr, int bool); // Get functions private synchronized native void _getTable(CPtr ptr, int idx); + private synchronized native void _getField(CPtr ptr, int idx, String k); + private synchronized native void _rawGet(CPtr ptr, int idx); + private synchronized native void _rawGetI(CPtr ptr, int idx, int n); + private synchronized native void _createTable(CPtr ptr, int narr, int nrec); - private synchronized native int _getMetaTable(CPtr ptr, int idx); - private synchronized native void _getFEnv(CPtr ptr, int idx); + + private synchronized native int _getMetaTable(CPtr ptr, int idx); // Set functions private synchronized native void _setTable(CPtr ptr, int idx); + private synchronized native void _setField(CPtr ptr, int idx, String k); + private synchronized native void _rawSet(CPtr ptr, int idx); + private synchronized native void _rawSetI(CPtr ptr, int idx, int n); - private synchronized native int _setMetaTable(CPtr ptr, int idx); - private synchronized native int _setFEnv(CPtr ptr, int idx); + + private synchronized native int _setMetaTable(CPtr ptr, int idx); private synchronized native void _call(CPtr ptr, int nArgs, int nResults); - private synchronized native int _pcall(CPtr ptr, int nArgs, int Results, int errFunc); + + private synchronized native int _pcall(CPtr ptr, int nArgs, int Results, int errFunc); // Coroutine Functions private synchronized native int _yield(CPtr ptr, int nResults); - private synchronized native int _resume(CPtr ptr, int nargs); + + private synchronized native int _resume(CPtr ptr, CPtr from, int nargs); + private synchronized native int _status(CPtr ptr); - + // Gargabe Collection Functions - final public static Integer LUA_GCSTOP = new Integer(0); - final public static Integer LUA_GCRESTART = new Integer(1); - final public static Integer LUA_GCCOLLECT = new Integer(2); - final public static Integer LUA_GCCOUNT = new Integer(3); - final public static Integer LUA_GCCOUNTB = new Integer(4); - final public static Integer LUA_GCSTEP = new Integer(5); - final public static Integer LUA_GCSETPAUSE = new Integer(6); + final public static Integer LUA_GCSTOP = new Integer(0); + final public static Integer LUA_GCRESTART = new Integer(1); + final public static Integer LUA_GCCOLLECT = new Integer(2); + final public static Integer LUA_GCCOUNT = new Integer(3); + final public static Integer LUA_GCCOUNTB = new Integer(4); + final public static Integer LUA_GCSTEP = new Integer(5); + final public static Integer LUA_GCSETPAUSE = new Integer(6); final public static Integer LUA_GCSETSTEPMUL = new Integer(7); - private synchronized native int _gc(CPtr ptr, int what, int data); + + private synchronized native int _gc(CPtr ptr, int what, int data); // Miscellaneous Functions - private synchronized native int _error(CPtr ptr); - private synchronized native int _next(CPtr ptr, int idx); - private synchronized native void _concat(CPtr ptr, int n); + private synchronized native int _error(CPtr ptr); + + private synchronized native int _next(CPtr ptr, int idx); + + private synchronized native void _concat(CPtr ptr, int n); // Some macros private synchronized native void _pop(CPtr ptr, int n); + private synchronized native void _newTable(CPtr ptr); - private synchronized native int _strlen(CPtr ptr, int idx); - private synchronized native int _isFunction(CPtr ptr, int idx); - private synchronized native int _isTable(CPtr ptr, int idx); - private synchronized native int _isNil(CPtr ptr, int idx); - private synchronized native int _isBoolean(CPtr ptr, int idx); - private synchronized native int _isThread(CPtr ptr, int idx); - private synchronized native int _isNone(CPtr ptr, int idx); - private synchronized native int _isNoneOrNil(CPtr ptr, int idx); - + + private synchronized native int _strlen(CPtr ptr, int idx); + + private synchronized native int _isFunction(CPtr ptr, int idx); + + private synchronized native int _isTable(CPtr ptr, int idx); + + private synchronized native int _isNil(CPtr ptr, int idx); + + private synchronized native int _isBoolean(CPtr ptr, int idx); + + private synchronized native int _isThread(CPtr ptr, int idx); + + private synchronized native int _isNone(CPtr ptr, int idx); + + private synchronized native int _isNoneOrNil(CPtr ptr, int idx); + private synchronized native void _setGlobal(CPtr ptr, String name); - private synchronized native void _getGlobal(CPtr ptr, String name); - - private synchronized native int _getGcCount(CPtr ptr); + private synchronized native void _getGlobal(CPtr ptr, String name); // LuaLibAux private synchronized native int _LdoFile(CPtr ptr, String fileName); + private synchronized native int _LdoString(CPtr ptr, String string); //private synchronized native int _doBuffer(CPtr ptr, byte[] buff, long sz, String n); - - private synchronized native int _LgetMetaField(CPtr ptr, int obj, String e); - private synchronized native int _LcallMeta(CPtr ptr, int obj, String e); - private synchronized native int _Ltyperror(CPtr ptr, int nArg, String tName); - private synchronized native int _LargError(CPtr ptr, int numArg, String extraMsg); + + private synchronized native int _LgetMetaField(CPtr ptr, int obj, String e); + + private synchronized native int _LcallMeta(CPtr ptr, int obj, String e); + + private synchronized native int _LargError(CPtr ptr, int numArg, String extraMsg); + private synchronized native String _LcheckString(CPtr ptr, int numArg); + private synchronized native String _LoptString(CPtr ptr, int numArg, String def); + private synchronized native double _LcheckNumber(CPtr ptr, int numArg); + private synchronized native double _LoptNumber(CPtr ptr, int numArg, double def); - - private synchronized native int _LcheckInteger(CPtr ptr, int numArg); - private synchronized native int _LoptInteger(CPtr ptr, int numArg, int def); - + + private synchronized native int _LcheckInteger(CPtr ptr, int numArg); + + private synchronized native int _LoptInteger(CPtr ptr, int numArg, int def); + private synchronized native void _LcheckStack(CPtr ptr, int sz, String msg); + private synchronized native void _LcheckType(CPtr ptr, int nArg, int t); + private synchronized native void _LcheckAny(CPtr ptr, int nArg); - - private synchronized native int _LnewMetatable(CPtr ptr, String tName); + + private synchronized native int _LnewMetatable(CPtr ptr, String tName); + private synchronized native void _LgetMetatable(CPtr ptr, String tName); - + private synchronized native void _Lwhere(CPtr ptr, int lvl); - - private synchronized native int _Lref(CPtr ptr, int t); + + private synchronized native int _Lref(CPtr ptr, int t); + private synchronized native void _LunRef(CPtr ptr, int t, int ref); - - private synchronized native int _LgetN(CPtr ptr, int t); - private synchronized native void _LsetN(CPtr ptr, int t, int n); - + private synchronized native int _LloadFile(CPtr ptr, String fileName); + private synchronized native int _LloadBuffer(CPtr ptr, byte[] buff, long sz, String name); + private synchronized native int _LloadString(CPtr ptr, String s); private synchronized native String _Lgsub(CPtr ptr, String s, String p, String r); - private synchronized native String _LfindTable(CPtr ptr, int idx, String fname, int szhint); - - + private synchronized native void _openBase(CPtr ptr); + private synchronized native void _openTable(CPtr ptr); + private synchronized native void _openIo(CPtr ptr); + private synchronized native void _openOs(CPtr ptr); + private synchronized native void _openString(CPtr ptr); + private synchronized native void _openMath(CPtr ptr); + private synchronized native void _openDebug(CPtr ptr); + private synchronized native void _openPackage(CPtr ptr); + private synchronized native void _openLibs(CPtr ptr); // Java Interface ----------------------------------------------------- - public LuaState newThread() - { - LuaState l = new LuaState(_newthread(luaState)); - LuaStateFactory.insertLuaState(l); + public LuaState newThread() { + LuaState l = new LuaState((CPtr) _newthread(luaState)); + LuaStateFactory.insertLuaState(l); return l; } // STACK MANIPULATION - public int getTop() - { + public int getTop() { return _getTop(luaState); } - public void setTop(int idx) - { + public void setTop(int idx) { _setTop(luaState, idx); } - public void pushValue(int idx) - { + public void pushValue(int idx) { _pushValue(luaState, idx); } - public void remove(int idx) - { + public void remove(int idx) { _remove(luaState, idx); } - public void insert(int idx) - { + public void insert(int idx) { _insert(luaState, idx); } - public void replace(int idx) - { + public void replace(int idx) { _replace(luaState, idx); } - public int checkStack(int sz) - { + public int checkStack(int sz) { return _checkStack(luaState, sz); } - - public void xmove(LuaState to, int n) - { + + public void xmove(LuaState to, int n) { _xmove(luaState, to.luaState, n); } // ACCESS FUNCTION - public boolean isNumber(int idx) - { - return (_isNumber(luaState, idx)!=0); + public boolean isNumber(int idx) { + return (_isNumber(luaState, idx) != 0); } - public boolean isString(int idx) - { - return (_isString(luaState, idx)!=0); + public boolean isString(int idx) { + return (_isString(luaState, idx) != 0); } - public boolean isFunction(int idx) - { - return (_isFunction(luaState, idx)!=0); + public boolean isFunction(int idx) { + return (_isFunction(luaState, idx) != 0); } - - public boolean isCFunction(int idx) - { - return (_isCFunction(luaState, idx)!=0); + + public boolean isCFunction(int idx) { + return (_isCFunction(luaState, idx) != 0); } - public boolean isUserdata(int idx) - { - return (_isUserdata(luaState, idx)!=0); + public boolean isUserdata(int idx) { + return (_isUserdata(luaState, idx) != 0); } - public boolean isTable(int idx) - { - return (_isTable(luaState, idx)!=0); + public boolean isTable(int idx) { + return (_isTable(luaState, idx) != 0); } - public boolean isBoolean(int idx) - { - return (_isBoolean(luaState, idx)!=0); + public boolean isBoolean(int idx) { + return (_isBoolean(luaState, idx) != 0); } - - public boolean isNil(int idx) - { - return (_isNil(luaState, idx)!=0); + + public boolean isNil(int idx) { + return (_isNil(luaState, idx) != 0); } - - public boolean isThread(int idx) - { - return (_isThread(luaState, idx)!=0); + + public boolean isThread(int idx) { + return (_isThread(luaState, idx) != 0); } - - public boolean isNone(int idx) - { - return (_isNone(luaState, idx)!=0); + + public boolean isNone(int idx) { + return (_isNone(luaState, idx) != 0); } - - public boolean isNoneOrNil(int idx) - { - return (_isNoneOrNil(luaState, idx)!=0); + + public boolean isNoneOrNil(int idx) { + return (_isNoneOrNil(luaState, idx) != 0); } - public int type(int idx) - { + public int type(int idx) { return _type(luaState, idx); } - public String typeName(int tp) - { - return _typeName(luaState, tp); + public String typeName(int tp) { + return _typeName(luaState, tp); } - public int equal(int idx1, int idx2) - { + public int equal(int idx1, int idx2) { return _equal(luaState, idx1, idx2); } - public int rawequal(int idx1, int idx2) - { + public int rawequal(int idx1, int idx2) { return _rawequal(luaState, idx1, idx2); } - public int lessthan(int idx1, int idx2) - { + public int lessthan(int idx1, int idx2) { return _lessthan(luaState, idx1, idx2); } - public double toNumber(int idx) - { + public double toNumber(int idx) { return _toNumber(luaState, idx); } - public int toInteger(int idx) - { - return _toInteger(luaState, idx); + public int toInteger(int idx) { + return _toInteger(luaState, idx); } - - public boolean toBoolean(int idx) - { - return (_toBoolean(luaState, idx)!=0); + + public boolean toBoolean(int idx) { + return (_toBoolean(luaState, idx) != 0); } - public String toString(int idx) - { + public String toString(int idx) { return _toString(luaState, idx); } - - public int strLen(int idx) - { + + public int strLen(int idx) { return _strlen(luaState, idx); } - - public int objLen(int idx) - { - return _objlen(luaState, idx); + + public int objLen(int idx) { + return _objlen(luaState, idx); } - public LuaState toThread(int idx) - { - return new LuaState(_toThread(luaState, idx)); + public LuaState toThread(int idx) { + return new LuaState((CPtr)_toThread(luaState, idx)); } - + //PUSH FUNCTIONS - - public void pushNil() - { + + public void pushNil() { _pushNil(luaState); } - public void pushNumber(double db) - { + public void pushNumber(double db) { _pushNumber(luaState, db); } - - public void pushInteger(int integer) - { - _pushInteger(luaState, integer); + + public void pushInteger(int integer) { + _pushInteger(luaState, integer); } - public void pushString(String str) - { + public void pushString(String str) { if (str == null) _pushNil(luaState); else _pushString(luaState, str); } - public void pushString(byte[] bytes) - { + public void pushString(byte[] bytes) { if (bytes == null) _pushNil(luaState); else - _pushString(luaState, bytes, bytes.length); + _pushString2(luaState, bytes, bytes.length); } - - public void pushBoolean(boolean bool) - { + + public void pushBoolean(boolean bool) { _pushBoolean(luaState, bool ? 1 : 0); } // GET FUNCTIONS - public void getTable(int idx) - { + public void getTable(int idx) { _getTable(luaState, idx); } - - public void getField(int idx, String k) - { - _getField(luaState, idx, k); + + public void getField(int idx, String k) { + _getField(luaState, idx, k); } - public void rawGet(int idx) - { + public void rawGet(int idx) { _rawGet(luaState, idx); } - public void rawGetI(int idx, int n) - { + public void rawGetI(int idx, int n) { _rawGetI(luaState, idx, n); } - - public void createTable(int narr, int nrec) - { - _createTable(luaState, narr, nrec); + + public void createTable(int narr, int nrec) { + _createTable(luaState, narr, nrec); } - public void newTable() - { + public void newTable() { _newTable(luaState); } // if returns 0, there is no metatable - public int getMetaTable(int idx) - { + public int getMetaTable(int idx) { return _getMetaTable(luaState, idx); } - public void getFEnv(int idx) - { - _getFEnv(luaState, idx); - } - // SET FUNCTIONS - - public void setTable(int idx) - { + + public void setTable(int idx) { _setTable(luaState, idx); } - - public void setField(int idx, String k) - { - _setField(luaState, idx, k); + + public void setField(int idx, String k) { + _setField(luaState, idx, k); } - public void rawSet(int idx) - { + public void rawSet(int idx) { _rawSet(luaState, idx); } - public void rawSetI(int idx, int n) - { + public void rawSetI(int idx, int n) { _rawSetI(luaState, idx, n); } // if returns 0, cannot set the metatable to the given object - public int setMetaTable(int idx) - { + public int setMetaTable(int idx) { return _setMetaTable(luaState, idx); } - // if object is not a function returns 0 - public int setFEnv(int idx) - { - return _setFEnv(luaState, idx); - } - - public void call(int nArgs, int nResults) - { + public void call(int nArgs, int nResults) { _call(luaState, nArgs, nResults); } // returns 0 if ok of one of the error codes defined - public int pcall(int nArgs, int nResults, int errFunc) - { + public int pcall(int nArgs, int nResults, int errFunc) { return _pcall(luaState, nArgs, nResults, errFunc); } - public int yield(int nResults) - { - return _yield(luaState, nResults); + public int yield(int nResults) { + return _yield(luaState, nResults); } - public int resume(int nArgs) - { - return _resume(luaState, nArgs); + public int resume(CPtr from, int nArgs) { + return _resume(luaState, from, nArgs); } - - public int status() - { - return _status(luaState); + + public int status() { + return _status(luaState); } - - public int gc(int what, int data) - { + + public int gc(int what, int data) { return _gc(luaState, what, data); } - - public int getGcCount() - { - return _getGcCount(luaState); - } - - public int next(int idx) - { - return _next(luaState, idx); + + public int next(int idx) { + return _next(luaState, idx); } - public int error() - { - return _error(luaState); + public int error() { + return _error(luaState); } - public void concat(int n) - { - _concat(luaState, n); + public void concat(int n) { + _concat(luaState, n); } // FUNCTION FROM lauxlib // returns 0 if ok - public int LdoFile(String fileName) - { + public int LdoFile(String fileName) { return _LdoFile(luaState, fileName); } // returns 0 if ok - public int LdoString(String str) - { + public int LdoString(String str) { return _LdoString(luaState, str); } - - public int LgetMetaField(int obj, String e) - { + + public int LgetMetaField(int obj, String e) { return _LgetMetaField(luaState, obj, e); } - - public int LcallMeta(int obj, String e) - { + + public int LcallMeta(int obj, String e) { return _LcallMeta(luaState, obj, e); } - - public int Ltyperror(int nArg, String tName) - { - return _Ltyperror(luaState, nArg, tName); - } - - public int LargError(int numArg, String extraMsg) - { + + public int LargError(int numArg, String extraMsg) { return _LargError(luaState, numArg, extraMsg); } - - public String LcheckString(int numArg) - { + + public String LcheckString(int numArg) { return _LcheckString(luaState, numArg); } - - public String LoptString(int numArg, String def) - { + + public String LoptString(int numArg, String def) { return _LoptString(luaState, numArg, def); } - - public double LcheckNumber(int numArg) - { + + public double LcheckNumber(int numArg) { return _LcheckNumber(luaState, numArg); } - - public double LoptNumber(int numArg, double def) - { + + public double LoptNumber(int numArg, double def) { return _LoptNumber(luaState, numArg, def); } - - public int LcheckInteger(int numArg) - { - return _LcheckInteger(luaState, numArg); + + public int LcheckInteger(int numArg) { + return _LcheckInteger(luaState, numArg); } - - public int LoptInteger(int numArg, int def) - { - return _LoptInteger(luaState, numArg, def); + + public int LoptInteger(int numArg, int def) { + return _LoptInteger(luaState, numArg, def); } - - public void LcheckStack(int sz, String msg) - { + + public void LcheckStack(int sz, String msg) { _LcheckStack(luaState, sz, msg); } - - public void LcheckType(int nArg, int t) - { + + public void LcheckType(int nArg, int t) { _LcheckType(luaState, nArg, t); } - - public void LcheckAny(int nArg) - { + + public void LcheckAny(int nArg) { _LcheckAny(luaState, nArg); } - - public int LnewMetatable(String tName) - { + + public int LnewMetatable(String tName) { return _LnewMetatable(luaState, tName); } - - public void LgetMetatable(String tName) - { + + public void LgetMetatable(String tName) { _LgetMetatable(luaState, tName); } - - public void Lwhere(int lvl) - { + + public void Lwhere(int lvl) { _Lwhere(luaState, lvl); } - - public int Lref(int t) - { + + public int Lref(int t) { return _Lref(luaState, t); } - - public void LunRef(int t, int ref) - { + + public void LunRef(int t, int ref) { _LunRef(luaState, t, ref); } - - public int LgetN(int t) - { - return _LgetN(luaState, t); - } - - public void LsetN(int t, int n) - { - _LsetN(luaState, t, n); - } - - public int LloadFile(String fileName) - { + + public int LloadFile(String fileName) { return _LloadFile(luaState, fileName); } - - public int LloadString(String s) - { + + public int LloadString(String s) { return _LloadString(luaState, s); } - - public int LloadBuffer(byte[] buff, String name) - { + + public int LloadBuffer(byte[] buff, String name) { return _LloadBuffer(luaState, buff, buff.length, name); } - - public String Lgsub(String s, String p, String r) - { - return _Lgsub(luaState, s, p, r); - } - - public String LfindTable(int idx, String fname, int szhint) - { - return _LfindTable(luaState, idx, fname, szhint); + + public String Lgsub(String s, String p, String r) { + return _Lgsub(luaState, s, p, r); } - + //IMPLEMENTED C MACROS - public void pop(int n) - { + public void pop(int n) { //setTop(- (n) - 1); - _pop(luaState, n); + _pop(luaState, n); } - public synchronized void getGlobal(String global) - { + public synchronized void getGlobal(String global) { // pushString(global); // getTable(LUA_GLOBALSINDEX.intValue()); _getGlobal(luaState, global); } - public synchronized void setGlobal(String name) - { + public synchronized void setGlobal(String name) { //pushString(name); //insert(-2); //setTable(LUA_GLOBALSINDEX.intValue()); - _setGlobal(luaState, name); + _setGlobal(luaState, name); } - + // Functions to open lua libraries - public void openBase() - { + public void openBase() { _openBase(luaState); } - public void openTable() - { + + public void openTable() { _openTable(luaState); } - public void openIo() - { + + public void openIo() { _openIo(luaState); } - public void openOs() - { - _openOs(luaState); + + public void openOs() { + _openOs(luaState); } - public void openString() - { + + public void openString() { _openString(luaState); } - public void openMath() - { + + public void openMath() { _openMath(luaState); } - public void openDebug() - { + + public void openDebug() { _openDebug(luaState); } - public void openPackage() - { - _openPackage(luaState); + + public void openPackage() { + _openPackage(luaState); } - public void openLibs() - { + + public void openLibs() { _openLibs(luaState); } @@ -838,12 +756,15 @@ public void openLibs() /** * Initializes lua State to be used by luajava + * * @param cptr * @param stateId */ - private synchronized native void luajava_open(CPtr cptr, int stateId); + private synchronized native void _luajavaOpen(CPtr cptr, int stateId); + /** * Gets a Object from a userdata + * * @param L * @param idx index of the lua stack * @return Object @@ -852,6 +773,7 @@ public void openLibs() /** * Returns whether a userdata contains a Java Object + * * @param L * @param idx index of the lua stack * @return boolean @@ -860,6 +782,7 @@ public void openLibs() /** * Pushes a Java Object into the state stack + * * @param L * @param obj */ @@ -867,13 +790,15 @@ public void openLibs() /** * Pushes a JavaFunction into the state stack + * * @param L * @param func */ - private synchronized native void _pushJavaFunction(CPtr L, JavaFunction func) throws LuaException; + private synchronized native void _pushJavaFunction(CPtr L, Object func) throws LuaException; /** * Returns whether a userdata contains a Java Function + * * @param L * @param idx index of the lua stack * @return boolean @@ -882,22 +807,22 @@ public void openLibs() /** * Gets a Object from Lua + * * @param idx index of the lua stack * @return Object * @throws LuaException if the lua object does not represent a java object. */ - public Object getObjectFromUserdata(int idx) throws LuaException - { + public Object getObjectFromUserdata(int idx) throws LuaException { return _getObjectFromUserdata(luaState, idx); } /** * Tells whether a lua index contains a java Object + * * @param idx index of the lua stack * @return boolean */ - public boolean isObject(int idx) - { + public boolean isObject(int idx) { return _isObject(luaState, idx); } @@ -905,29 +830,29 @@ public boolean isObject(int idx) * Pushes a Java Object into the lua stack.
* This function does not check if the object is from a class that could * be represented by a lua type. Eg: java.lang.String could be a lua string. + * * @param obj Object to be pushed into lua */ - public void pushJavaObject(Object obj) - { + public void pushJavaObject(Object obj) { _pushJavaObject(luaState, obj); } /** * Pushes a JavaFunction into the state stack + * * @param func */ - public void pushJavaFunction(JavaFunction func) throws LuaException - { + public void pushJavaFunction(JavaFunction func) throws LuaException { _pushJavaFunction(luaState, func); } /** * Returns whether a userdata contains a Java Function + * * @param idx index of the lua stack * @return boolean */ - public boolean isJavaFunction(int idx) - { + public boolean isJavaFunction(int idx) { return _isJavaFunction(luaState, idx); } @@ -935,43 +860,28 @@ public boolean isJavaFunction(int idx) * Pushes into the stack any object value.
* This function checks if the object could be pushed as a lua type, if not * pushes the java object. + * * @param obj */ - public void pushObjectValue(Object obj) throws LuaException - { - if (obj == null) - { + public void pushObjectValue(Object obj) throws LuaException { + if (obj == null) { pushNil(); - } - else if (obj instanceof Boolean) - { + } else if (obj instanceof Boolean) { Boolean bool = (Boolean) obj; pushBoolean(bool.booleanValue()); - } - else if (obj instanceof Number) - { + } else if (obj instanceof Number) { pushNumber(((Number) obj).doubleValue()); - } - else if (obj instanceof String) - { + } else if (obj instanceof String) { pushString((String) obj); - } - else if (obj instanceof JavaFunction) - { + } else if (obj instanceof JavaFunction) { JavaFunction func = (JavaFunction) obj; pushJavaFunction(func); - } - else if (obj instanceof LuaObject) - { + } else if (obj instanceof LuaObject) { LuaObject ref = (LuaObject) obj; ref.push(); - } - else if (obj instanceof byte[]) - { + } else if (obj instanceof byte[]) { pushString((byte[]) obj); - } - else - { + } else { pushJavaObject(obj); } } @@ -979,206 +889,165 @@ else if (obj instanceof byte[]) /** * Function that returns a Java Object equivalent to the one in the given * position of the Lua Stack. + * * @param idx Index in the Lua Stack * @return Java object equivalent to the Lua one */ - public synchronized Object toJavaObject( int idx ) throws LuaException - { - Object obj = null; - - if (isBoolean(idx)) - { - obj = new Boolean(toBoolean(idx)); - } - else if (type(idx) == LuaState.LUA_TSTRING.intValue()) - { - obj = toString(idx); - } - else if (isFunction(idx)) - { - obj = getLuaObject(idx); - } - else if (isTable(idx)) - { - obj = getLuaObject(idx); - } - else if (type(idx) == LuaState.LUA_TNUMBER.intValue()) - { - obj = new Double(toNumber(idx)); - } - else if (isUserdata(idx)) - { - if (isObject(idx)) - { - obj = getObjectFromUserdata(idx); - } - else - { - obj = getLuaObject(idx); - } - } - else if (isNil(idx)) - { - obj = null; - } - - return obj; - } - - /** - * Creates a reference to an object in the variable globalName - * @param globalName - * @return LuaObject - */ - public LuaObject getLuaObject(String globalName) - { - return new LuaObject(this, globalName); - } - - /** - * Creates a reference to an object inside another object - * @param parent The Lua Table or Userdata that contains the Field. - * @param name The name that index the field - * @return LuaObject - * @throws LuaException if parent is not a table or userdata - */ - public LuaObject getLuaObject(LuaObject parent, String name) - throws LuaException - { - if (parent.L.getCPtrPeer() != luaState.getPeer()) - throw new LuaException("Object must have the same LuaState as the parent!"); - - return new LuaObject(parent, name); - } - - /** - * This constructor creates a LuaObject from a table that is indexed by a number. - * @param parent The Lua Table or Userdata that contains the Field. - * @param name The name (number) that index the field - * @return LuaObject - * @throws LuaException When the parent object isn't a Table or Userdata - */ - public LuaObject getLuaObject(LuaObject parent, Number name) - throws LuaException - { - if (parent.L.getCPtrPeer() != luaState.getPeer()) - throw new LuaException("Object must have the same LuaState as the parent!"); - - return new LuaObject(parent, name); - } - - /** - * This constructor creates a LuaObject from a table that is indexed by any LuaObject. - * @param parent The Lua Table or Userdata that contains the Field. - * @param name The name (LuaObject) that index the field - * @return LuaObject - * @throws LuaException When the parent object isn't a Table or Userdata - */ - public LuaObject getLuaObject(LuaObject parent, LuaObject name) - throws LuaException - { - if (parent.getLuaState().getCPtrPeer() != luaState.getPeer() || - parent.getLuaState().getCPtrPeer() != name.getLuaState().getCPtrPeer()) - throw new LuaException("Object must have the same LuaState as the parent!"); - - return new LuaObject(parent, name); - } - - /** - * Creates a reference to an object in the index position - * of the stack - * @param index position on the stack - * @return LuaObject - */ - public LuaObject getLuaObject(int index) - { - return new LuaObject(this, index); - } - - /** - * When you call a function in lua, it may return a number, and the - * number will be interpreted as a Double.
- * This function converts the number into a type specified by - * retType - * @param db lua number to be converted - * @param retType type to convert to - * @return The converted number - */ - public static Number convertLuaNumber(Double db, Class retType) - { - // checks if retType is a primitive type - if (retType.isPrimitive()) - { - if (retType == Integer.TYPE) - { - return new Integer(db.intValue()); + public synchronized Object toJavaObject(int idx) throws LuaException { + Object obj = null; + + if (isBoolean(idx)) { + obj = new Boolean(toBoolean(idx)); + } else if (type(idx) == LuaState.LUA_TSTRING) { + obj = toString(idx); + } else if (isFunction(idx)) { + obj = getLuaObject(idx); + } else if (isTable(idx)) { + obj = getLuaObject(idx); + } else if (type(idx) == LuaState.LUA_TNUMBER) { + obj = new Double(toNumber(idx)); + } else if (isUserdata(idx)) { + if (isObject(idx)) { + obj = getObjectFromUserdata(idx); + } else { + obj = getLuaObject(idx); } - else if (retType == Long.TYPE) - { + } else if (isNil(idx)) { + obj = null; + } + + return obj; + } + + /** + * Creates a reference to an object in the variable globalName + * + * @param globalName + * @return LuaObject + */ + public LuaObject getLuaObject(String globalName) { + return new LuaObject(this, globalName); + } + + /** + * Creates a reference to an object inside another object + * + * @param parent The Lua Table or Userdata that contains the Field. + * @param name The name that index the field + * @return LuaObject + * @throws LuaException if parent is not a table or userdata + */ + public LuaObject getLuaObject(LuaObject parent, String name) + throws LuaException { + if (parent.L.getCPtrPeer() != luaState.getPeer()) + throw new LuaException("Object must have the same LuaState as the parent!"); + + return new LuaObject(parent, name); + } + + /** + * This constructor creates a LuaObject from a table that is indexed by a number. + * + * @param parent The Lua Table or Userdata that contains the Field. + * @param name The name (number) that index the field + * @return LuaObject + * @throws LuaException When the parent object isn't a Table or Userdata + */ + public LuaObject getLuaObject(LuaObject parent, Number name) + throws LuaException { + if (parent.L.getCPtrPeer() != luaState.getPeer()) + throw new LuaException("Object must have the same LuaState as the parent!"); + + return new LuaObject(parent, name); + } + + /** + * This constructor creates a LuaObject from a table that is indexed by any LuaObject. + * + * @param parent The Lua Table or Userdata that contains the Field. + * @param name The name (LuaObject) that index the field + * @return LuaObject + * @throws LuaException When the parent object isn't a Table or Userdata + */ + public LuaObject getLuaObject(LuaObject parent, LuaObject name) + throws LuaException { + if (parent.getLuaState().getCPtrPeer() != luaState.getPeer() || + parent.getLuaState().getCPtrPeer() != name.getLuaState().getCPtrPeer()) + throw new LuaException("Object must have the same LuaState as the parent!"); + + return new LuaObject(parent, name); + } + + /** + * Creates a reference to an object in the index position + * of the stack + * + * @param index position on the stack + * @return LuaObject + */ + public LuaObject getLuaObject(int index) { + return new LuaObject(this, index); + } + + /** + * When you call a function in lua, it may return a number, and the + * number will be interpreted as a Double.
+ * This function converts the number into a type specified by + * retType + * + * @param db lua number to be converted + * @param retType type to convert to + * @return The converted number + */ + public static Number convertLuaNumber(Double db, Class retType) { + // checks if retType is a primitive type + if (retType.isPrimitive()) { + if (retType == Integer.TYPE) { + return new Integer(db.intValue()); + } else if (retType == Long.TYPE) { return new Long(db.longValue()); - } - else if (retType == Float.TYPE) - { + } else if (retType == Float.TYPE) { return new Float(db.floatValue()); - } - else if (retType == Double.TYPE) - { + } else if (retType == Double.TYPE) { return db; - } - else if (retType == Byte.TYPE) - { + } else if (retType == Byte.TYPE) { return new Byte(db.byteValue()); - } - else if (retType == Short.TYPE) - { + } else if (retType == Short.TYPE) { return new Short(db.shortValue()); } - } - else if (retType.isAssignableFrom(Number.class)) - { + } else if (retType.isAssignableFrom(Number.class)) { // Checks all possibilities of number types - if (retType.isAssignableFrom(Integer.class)) - { + if (retType.isAssignableFrom(Integer.class)) { return new Integer(db.intValue()); - } - else if (retType.isAssignableFrom(Long.class)) - { + } else if (retType.isAssignableFrom(Long.class)) { return new Long(db.longValue()); - } - else if (retType.isAssignableFrom(Float.class)) - { + } else if (retType.isAssignableFrom(Float.class)) { return new Float(db.floatValue()); - } - else if (retType.isAssignableFrom(Double.class)) - { + } else if (retType.isAssignableFrom(Double.class)) { return db; - } - else if (retType.isAssignableFrom(Byte.class)) - { + } else if (retType.isAssignableFrom(Byte.class)) { return new Byte(db.byteValue()); - } - else if (retType.isAssignableFrom(Short.class)) - { + } else if (retType.isAssignableFrom(Short.class)) { return new Short(db.shortValue()); } } - + // if all checks fail, return null - return null; - } - - public String dumpStack() { - int n = getTop(); - StringBuilder sb = new StringBuilder(); - for (int i = 1; i <= n; i++) { - int t = type(i); - sb.append(i).append(": ").append(typeName(t)); - if (t == LUA_TNUMBER) - sb.append(" = ").append(toNumber(i)); - else if (t == LUA_TSTRING) - sb.append(" = '").append(toString(i)).append("'"); - sb.append("\n"); - } - return sb.toString(); - } + return null; + } + + public String dumpStack() { + int n = getTop(); + StringBuilder sb = new StringBuilder(); + for (int i = 1; i <= n; i++) { + int t = type(i); + sb.append(i).append(": ").append(typeName(t)); + if (t == LUA_TNUMBER) + sb.append(" = ").append(toNumber(i)); + else if (t == LUA_TSTRING) + sb.append(" = '").append(toString(i)).append("'"); + sb.append("\n"); + } + return sb.toString(); + } } diff --git a/app/src/main/java/org/keplerproject/luajava/LuaStateFactory.java b/app/src/main/java/org/keplerproject/luajava/LuaStateFactory.java index 92b9617..1975fd0 100644 --- a/app/src/main/java/org/keplerproject/luajava/LuaStateFactory.java +++ b/app/src/main/java/org/keplerproject/luajava/LuaStateFactory.java @@ -33,91 +33,109 @@ * and an index is returned. This index is registred in Lua * and it is used to find the right LuaState when lua calls * a Java Function. - * + * * @author Thiago Ponte */ -public final class LuaStateFactory -{ +public final class LuaStateFactory { + + private final static String LUAJAVA_LIB = "luajava"; + private final static boolean isLuaLibLoaded; + + /** + * Opens the library containing the luajava API + */ + static { + boolean loaded = false; + try { + System.loadLibrary(LUAJAVA_LIB); + loaded = true; + } catch (UnsatisfiedLinkError e) { + e.printStackTrace(); + } + isLuaLibLoaded = loaded; + } + /** * Array with all luaState's instances */ - private static final List states = new ArrayList(); - + private static final List states = new ArrayList<>(); + /** - * Non-public constructor. + * Non-public constructor. */ - private LuaStateFactory() - {} - + private LuaStateFactory() { + } + /** * Method that creates a new instance of LuaState + * * @return LuaState */ - public synchronized static LuaState newLuaState() - { + public synchronized static LuaState newLuaState() { + if(!isLuaLibLoaded) { + return null; + } int i = getNextStateIndex(); LuaState L = new LuaState(i); - + states.add(i, L); - + return L; } - + /** * Returns a existing instance of LuaState + * * @param index * @return LuaState */ - public synchronized static LuaState getExistingState(int index) - { + public synchronized static LuaState getExistingState(int index) { return (LuaState) states.get(index); } - + /** * Receives a existing LuaState and checks if it exists in the states list. * If it doesn't exist adds it to the list. + * * @param L * @return int */ - public synchronized static int insertLuaState(LuaState L) - { + public synchronized static int insertLuaState(LuaState L) { int i; - for (i = 0 ; i < states.size() ; i++) - { + for (i = 0; i < states.size(); i++) { LuaState state = (LuaState) states.get(i); - - if (state != null) - { + + if (state != null) { if (state.getCPtrPeer() == L.getCPtrPeer()) return i; } } i = getNextStateIndex(); - + states.set(i, L); - + return i; } - + /** * removes the luaState from the states list + * * @param idx */ - public synchronized static void removeLuaState(int idx) - { + public synchronized static void removeLuaState(int idx) { states.add(idx, null); } - + /** * Get next available index + * * @return int */ - private synchronized static int getNextStateIndex() - { + private synchronized static int getNextStateIndex() { int i; - for ( i=0 ; i < states.size() && states.get(i) != null ; i++ ); - + for (i = 0; i < states.size() && states.get(i) != null; i++) ; + return i; } } \ No newline at end of file diff --git a/app/src/main/java/sk/kottman/androlua/Main.java b/app/src/main/java/sk/kottman/androlua/Main.java index f6de2b1..3fb657e 100644 --- a/app/src/main/java/sk/kottman/androlua/Main.java +++ b/app/src/main/java/sk/kottman/androlua/Main.java @@ -12,7 +12,6 @@ import android.app.Activity; import android.content.res.AssetManager; import android.os.Bundle; -import android.util.*; import android.os.Handler; import android.text.method.ScrollingMovementMethod; import android.view.View; @@ -24,252 +23,266 @@ import android.widget.Toast; public class Main extends Activity implements OnClickListener, - OnLongClickListener { - private final static int LISTEN_PORT = 3333; - - Button execute; - - // public so we can play with these from Lua - public EditText source; - public TextView status; - public LuaState L; - - final StringBuilder output = new StringBuilder(); - - Handler handler; - ServerThread serverThread; - - private static byte[] readAll(InputStream input) throws Exception { - ByteArrayOutputStream output = new ByteArrayOutputStream(4096); - byte[] buffer = new byte[4096]; - int n = 0; - while (-1 != (n = input.read(buffer))) { - output.write(buffer, 0, n); - } - return output.toByteArray(); - } - - /** Called when the activity is first created. */ - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.main); - - execute = (Button) findViewById(R.id.executeBtn); - execute.setOnClickListener(this); - - source = (EditText) findViewById(R.id.source); - source.setOnLongClickListener(this); - source.setText("require 'import'\nprint(Math:sin(2.3))\n"); - - status = (TextView) findViewById(R.id.statusText); - status.setMovementMethod(ScrollingMovementMethod.getInstance()); - - handler = new Handler(); - - L = LuaStateFactory.newLuaState(); - L.openLibs(); - - try { - L.pushJavaObject(this); - L.setGlobal("activity"); - - JavaFunction print = new JavaFunction(L) { - @Override - public int execute() throws LuaException { - for (int i = 2; i <= L.getTop(); i++) { - int type = L.type(i); - String stype = L.typeName(type); - String val = null; - if (stype.equals("userdata")) { - Object obj = L.toJavaObject(i); - if (obj != null) - val = obj.toString(); - } else if (stype.equals("boolean")) { - val = L.toBoolean(i) ? "true" : "false"; - } else { - val = L.toString(i); - } - if (val == null) - val = stype; - output.append(val); - output.append("\t"); - } - output.append("\n"); - return 0; - } - }; - print.register("print"); - - JavaFunction assetLoader = new JavaFunction(L) { - @Override - public int execute() throws LuaException { - String name = L.toString(-1); - - AssetManager am = getAssets(); - try { - InputStream is = am.open(name + ".lua"); - byte[] bytes = readAll(is); - L.LloadBuffer(bytes, name); - return 1; - } catch (Exception e) { - ByteArrayOutputStream os = new ByteArrayOutputStream(); - e.printStackTrace(new PrintStream(os)); - L.pushString("Cannot load module "+name+":\n"+os.toString()); - return 1; - } - } - }; - - L.getGlobal("package"); // package - L.getField(-1, "loaders"); // package loaders - int nLoaders = L.objLen(-1); // package loaders - - L.pushJavaFunction(assetLoader); // package loaders loader - L.rawSetI(-2, nLoaders + 1); // package loaders - L.pop(1); // package - - L.getField(-1, "path"); // package path - String customPath = getFilesDir() + "/?.lua"; - L.pushString(";" + customPath); // package path custom - L.concat(2); // package pathCustom - L.setField(-2, "path"); // package - L.pop(1); - } catch (Exception e) { - status.setText("Cannot override print"); - } - } - - @Override - protected void onResume() { - super.onResume(); - serverThread = new ServerThread(); - serverThread.start(); - } - - @Override - protected void onPause() { - super.onPause(); - serverThread.stopped = true; - } - - private class ServerThread extends Thread { - public boolean stopped; - - @Override - public void run() { - stopped = false; - try { - ServerSocket server = new ServerSocket(LISTEN_PORT); - show("Server started on port " + LISTEN_PORT); - while (!stopped) { - Socket client = server.accept(); - BufferedReader in = new BufferedReader( - new InputStreamReader(client.getInputStream())); - final PrintWriter out = new PrintWriter(client.getOutputStream()); - String line = null; - while (!stopped && (line = in.readLine()) != null) { - final String s = line.replace('\001', '\n'); - if (s.startsWith("--mod:")) { - int i1 = s.indexOf(':'), i2 = s.indexOf('\n'); - String mod = s.substring(i1+1,i2); - String file = getFilesDir()+"/"+mod.replace('.', '/')+".lua"; - FileWriter fw = new FileWriter(file); - fw.write(s); - fw.close(); - // package.loaded[mod] = nil - L.getGlobal("package"); - L.getField(-1, "loaded"); - L.pushNil(); - L.setField(-2, mod); - out.println("wrote " + file + "\n"); - out.flush(); - } else { - handler.post(new Runnable() { - public void run() { - String res = safeEvalLua(s); - res = res.replace('\n', '\001'); - out.println(res); - out.flush(); - } - }); - } - } - } - server.close(); - } catch (Exception e) { - show(e.toString()); - } - } - - private void show(final String s) { - handler.post(new Runnable() { - public void run() { - status.setText(s); - } - }); - } - } - - String safeEvalLua(String src) { - String res = null; - try { - res = evalLua(src); - } catch(LuaException e) { - res = e.getMessage()+"\n"; - } - return res; - } - - String evalLua(String src) throws LuaException { - L.setTop(0); - int ok = L.LloadString(src); - if (ok == 0) { - L.getGlobal("debug"); - L.getField(-1, "traceback"); - L.remove(-2); - L.insert(-2); - ok = L.pcall(0, 0, -2); - if (ok == 0) { - String res = output.toString(); - output.setLength(0); - return res; - } - } - throw new LuaException(errorReason(ok) + ": " + L.toString(-1)); - //return null; - - } - - public void onClick(View view) { - String src = source.getText().toString(); - status.setText(""); - try { - String res = evalLua(src); - status.append(res); - status.append("Finished succesfully"); - } catch(LuaException e) { - Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show(); - } - - } - - private String errorReason(int error) { - switch (error) { - case 4: - return "Out of memory"; - case 3: - return "Syntax error"; - case 2: - return "Runtime error"; - case 1: - return "Yield error"; - } - return "Unknown error " + error; - } - - public boolean onLongClick(View view) { - source.setText(""); - return true; - } + OnLongClickListener { + private final static int LISTEN_PORT = 3333; + + Button execute; + + // public so we can play with these from Lua + public EditText source; + public TextView status; + public LuaState L; + + final StringBuilder output = new StringBuilder(); + + Handler handler; + ServerThread serverThread; + + private static byte[] readAll(InputStream input) throws Exception { + ByteArrayOutputStream output = new ByteArrayOutputStream(4096); + byte[] buffer = new byte[4096]; + int n = 0; + while (-1 != (n = input.read(buffer))) { + output.write(buffer, 0, n); + } + return output.toByteArray(); + } + + /** + * Called when the activity is first created. + */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + + execute = (Button) findViewById(R.id.executeBtn); + execute.setOnClickListener(this); + + source = (EditText) findViewById(R.id.source); + source.setOnLongClickListener(this); + source.setText("require 'import'\nprint(Math:sin(2.3))\n"); + + status = (TextView) findViewById(R.id.statusText); + status.setMovementMethod(ScrollingMovementMethod.getInstance()); + + handler = new Handler(); + + initLua(); + } + + private void initLua() { + L = LuaStateFactory.newLuaState(); + if (L == null) { + Toast.makeText(this, "init lua fail", Toast.LENGTH_LONG).show(); + return; + } + L.openLibs(); + + try { + L.pushJavaObject(this); + L.setGlobal("activity"); + + JavaFunction print = new JavaFunction(L) { + @Override + public int execute() throws LuaException { + for (int i = 2; i <= L.getTop(); i++) { + int type = L.type(i); + String stype = L.typeName(type); + String val = null; + if (stype.equals("userdata")) { + Object obj = L.toJavaObject(i); + if (obj != null) + val = obj.toString(); + } else if (stype.equals("boolean")) { + val = L.toBoolean(i) ? "true" : "false"; + } else { + val = L.toString(i); + } + if (val == null) + val = stype; + output.append(val); + output.append("\t"); + } + output.append("\n"); + return 0; + } + }; + print.register("print"); + + JavaFunction assetLoader = new JavaFunction(L) { + @Override + public int execute() throws LuaException { + String name = L.toString(-1); + + AssetManager am = getAssets(); + try { + InputStream is = am.open(name + ".lua"); + byte[] bytes = readAll(is); + L.LloadBuffer(bytes, name); + return 1; + } catch (Exception e) { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + e.printStackTrace(new PrintStream(os)); + L.pushString("Cannot load module " + name + ":\n" + os.toString()); + return 1; + } + } + }; + + L.getGlobal("package"); // package + L.getField(-1, "loaders"); // package loaders + int nLoaders = L.objLen(-1); // package loaders + + L.pushJavaFunction(assetLoader); // package loaders loader + L.rawSetI(-2, nLoaders + 1); // package loaders + L.pop(1); // package + + L.getField(-1, "path"); // package path + String customPath = getFilesDir() + "/?.lua"; + L.pushString(";" + customPath); // package path custom + L.concat(2); // package pathCustom + L.setField(-2, "path"); // package + L.pop(1); + } catch (Exception e) { + status.setText("Cannot override print"); + } + } + + @Override + protected void onResume() { + super.onResume(); + if (L != null) { + serverThread = new ServerThread(); + serverThread.start(); + } + } + + @Override + protected void onPause() { + super.onPause(); + if (serverThread != null) { + serverThread.stopped = true; + } + } + + private class ServerThread extends Thread { + public boolean stopped; + + @Override + public void run() { + stopped = false; + try { + ServerSocket server = new ServerSocket(LISTEN_PORT); + show("Server started on port " + LISTEN_PORT); + while (!stopped) { + Socket client = server.accept(); + BufferedReader in = new BufferedReader( + new InputStreamReader(client.getInputStream())); + final PrintWriter out = new PrintWriter(client.getOutputStream()); + String line = null; + while (!stopped && (line = in.readLine()) != null) { + final String s = line.replace('\001', '\n'); + if (s.startsWith("--mod:")) { + int i1 = s.indexOf(':'), i2 = s.indexOf('\n'); + String mod = s.substring(i1 + 1, i2); + String file = getFilesDir() + "/" + mod.replace('.', '/') + ".lua"; + FileWriter fw = new FileWriter(file); + fw.write(s); + fw.close(); + // package.loaded[mod] = nil + L.getGlobal("package"); + L.getField(-1, "loaded"); + L.pushNil(); + L.setField(-2, mod); + out.println("wrote " + file + "\n"); + out.flush(); + } else { + handler.post(new Runnable() { + public void run() { + String res = safeEvalLua(s); + res = res.replace('\n', '\001'); + out.println(res); + out.flush(); + } + }); + } + } + } + server.close(); + } catch (Exception e) { + show(e.toString()); + } + } + + private void show(final String s) { + handler.post(new Runnable() { + public void run() { + status.setText(s); + } + }); + } + } + + String safeEvalLua(String src) { + String res = null; + try { + res = evalLua(src); + } catch (LuaException e) { + res = e.getMessage() + "\n"; + } + return res; + } + + String evalLua(String src) throws LuaException { + L.setTop(0); + int ok = L.LloadString(src); + if (ok == 0) { + L.getGlobal("debug"); + L.getField(-1, "traceback"); + L.remove(-2); + L.insert(-2); + ok = L.pcall(0, 0, -2); + if (ok == 0) { + String res = output.toString(); + output.setLength(0); + return res; + } + } + throw new LuaException(errorReason(ok) + ": " + L.toString(-1)); + //return null; + + } + + public void onClick(View view) { + String src = source.getText().toString(); + status.setText(""); + try { + String res = evalLua(src); + status.append(res); + status.append("Finished succesfully"); + } catch (LuaException e) { + Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show(); + } + + } + + private String errorReason(int error) { + switch (error) { + case 4: + return "Out of memory"; + case 3: + return "Syntax error"; + case 2: + return "Runtime error"; + case 1: + return "Yield error"; + } + return "Unknown error " + error; + } + + public boolean onLongClick(View view) { + source.setText(""); + return true; + } } \ No newline at end of file diff --git a/app/src/main/jni/Application.mk b/app/src/main/jni/Application.mk new file mode 100644 index 0000000..9850e31 --- /dev/null +++ b/app/src/main/jni/Application.mk @@ -0,0 +1,28 @@ +#APP_ABI := all +APP_ABI := armeabi-v7a + +APP_CPPFLAGS += \ + -D__STDC_CONSTANT_MACROS \ + -D__STDC_LIMIT_MACROS \ + -D__STDC_FORMAT_MACROS \ + -D__DEBUG__ \ + -std=gnu99 \ + -Wno-pmf-conversions \ + -fno-rtti \ + -fno-exceptions \ + -Dtypeof=decltype \ + +APP_CPPFLAGS += -O2 -Wall -Wextra -flto=3 -fvisibility=hidden + +APP_LDFLAGS += \ + -Wl,--exclude-libs=ALL \ + -flto=3 \ + +APP_STL := gnustl_static + +APP_OPTIM := release + +APP_MODULES := liblua luajava + +NDK_TOOLCHAIN_VERSION := 4.9 +APP_PLATFORM := android-14 \ No newline at end of file diff --git a/app/src/main/jni/lua/Android.mk b/app/src/main/jni/lua/Android.mk index 98d74bc..5550415 100644 --- a/app/src/main/jni/lua/Android.mk +++ b/app/src/main/jni/lua/Android.mk @@ -3,7 +3,14 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := lua -LOCAL_SRC_FILES := lapi.c lauxlib.c lbaselib.c lcode.c ldblib.c ldebug.c ldo.c ldump.c lfunc.c lgc.c linit.c liolib.c llex.c lmathlib.c lmem.c loadlib.c lobject.c lopcodes.c loslib.c lparser.c lstate.c lstring.c lstrlib.c ltable.c ltablib.c ltm.c lundump.c lvm.c lzio.c +LOCAL_SRC_FILES := lapi.c lauxlib.c lbaselib.c lbitlib.c lcode.c lcorolib.c lctype.c ldblib.c ldebug.c ldo.c ldump.c lfunc.c lgc.c linit.c liolib.c llex.c lmathlib.c lmem.c loadlib.c lobject.c lopcodes.c loslib.c lparser.c lstate.c lstring.c lstrlib.c ltable.c ltablib.c ltm.c lundump.c lutf8lib.c lvm.c lzio.c + +LOCAL_CFLAGS += -DLUA_DL_DLOPEN -DLUA_USE_C89 -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 -DLUA_USE_LINUX + +LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog -ldl +LOCAL_CFLAGS += -pie -fPIE +LOCAL_LDFLAGS += -pie -fPIE + LOCAL_LDLIBS := -ld -lm include $(BUILD_STATIC_LIBRARY) diff --git a/app/src/main/jni/lua/Makefile b/app/src/main/jni/lua/Makefile new file mode 100644 index 0000000..d71c75c --- /dev/null +++ b/app/src/main/jni/lua/Makefile @@ -0,0 +1,197 @@ +# Makefile for building Lua +# See ../doc/readme.html for installation and customization instructions. + +# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= + +# Your platform. See PLATS for possible values. +PLAT= none + +CC= gcc -std=gnu99 +CFLAGS= -O2 -Wall -Wextra -DLUA_COMPAT_5_2 $(SYSCFLAGS) $(MYCFLAGS) +LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS) +LIBS= -lm $(SYSLIBS) $(MYLIBS) + +AR= ar rcu +RANLIB= ranlib +RM= rm -f + +SYSCFLAGS= +SYSLDFLAGS= +SYSLIBS= + +MYCFLAGS= +MYLDFLAGS= +MYLIBS= +MYOBJS= + +# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE ======= + +PLATS= aix bsd c89 freebsd generic linux macosx mingw posix solaris + +LUA_A= liblua.a +CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o \ + lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o \ + ltm.o lundump.o lvm.o lzio.o +LIB_O= lauxlib.o lbaselib.o lbitlib.o lcorolib.o ldblib.o liolib.o \ + lmathlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o loadlib.o linit.o +BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS) + +LUA_T= lua +LUA_O= lua.o + +LUAC_T= luac +LUAC_O= luac.o + +ALL_O= $(BASE_O) $(LUA_O) $(LUAC_O) +ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T) +ALL_A= $(LUA_A) + +# Targets start here. +default: $(PLAT) + +all: $(ALL_T) + +o: $(ALL_O) + +a: $(ALL_A) + +$(LUA_A): $(BASE_O) + $(AR) $@ $(BASE_O) + $(RANLIB) $@ + +$(LUA_T): $(LUA_O) $(LUA_A) + $(CC) -o $@ $(LDFLAGS) $(LUA_O) $(LUA_A) $(LIBS) + +$(LUAC_T): $(LUAC_O) $(LUA_A) + $(CC) -o $@ $(LDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS) + +clean: + $(RM) $(ALL_T) $(ALL_O) + +depend: + @$(CC) $(CFLAGS) -MM l*.c + +echo: + @echo "PLAT= $(PLAT)" + @echo "CC= $(CC)" + @echo "CFLAGS= $(CFLAGS)" + @echo "LDFLAGS= $(SYSLDFLAGS)" + @echo "LIBS= $(LIBS)" + @echo "AR= $(AR)" + @echo "RANLIB= $(RANLIB)" + @echo "RM= $(RM)" + +# Convenience targets for popular platforms +ALL= all + +none: + @echo "Please do 'make PLATFORM' where PLATFORM is one of these:" + @echo " $(PLATS)" + +aix: + $(MAKE) $(ALL) CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl" SYSLDFLAGS="-brtl -bexpall" + +bsd: + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-Wl,-E" + +c89: + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_C89" CC="gcc -std=c89" + @echo '' + @echo '*** C89 does not guarantee 64-bit integers for Lua.' + @echo '' + + +freebsd: + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -lreadline" + +generic: $(ALL) + +linux: + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline" + +macosx: + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" SYSLIBS="-lreadline" CC=cc + +mingw: + $(MAKE) "LUA_A=lua53.dll" "LUA_T=lua.exe" \ + "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \ + "SYSCFLAGS=-DLUA_BUILD_AS_DLL" "SYSLIBS=" "SYSLDFLAGS=-s" lua.exe + $(MAKE) "LUAC_T=luac.exe" luac.exe + +posix: + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX" + +solaris: + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN -D_REENTRANT" SYSLIBS="-ldl" + +# list targets that do not create files (but not all makes understand .PHONY) +.PHONY: all $(PLATS) default o a clean depend echo none + +# DO NOT DELETE + +lapi.o: lapi.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \ + lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h \ + ltable.h lundump.h lvm.h +lauxlib.o: lauxlib.c lprefix.h lua.h luaconf.h lauxlib.h +lbaselib.o: lbaselib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +lbitlib.o: lbitlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +lcode.o: lcode.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \ + llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \ + ldo.h lgc.h lstring.h ltable.h lvm.h +lcorolib.o: lcorolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +lctype.o: lctype.c lprefix.h lctype.h lua.h luaconf.h llimits.h +ldblib.o: ldblib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +ldebug.o: ldebug.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \ + lobject.h ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h \ + ldebug.h ldo.h lfunc.h lstring.h lgc.h ltable.h lvm.h +ldo.o: ldo.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \ + lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lopcodes.h \ + lparser.h lstring.h ltable.h lundump.h lvm.h +ldump.o: ldump.c lprefix.h lua.h luaconf.h lobject.h llimits.h lstate.h \ + ltm.h lzio.h lmem.h lundump.h +lfunc.o: lfunc.c lprefix.h lua.h luaconf.h lfunc.h lobject.h llimits.h \ + lgc.h lstate.h ltm.h lzio.h lmem.h +lgc.o: lgc.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ + llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h +linit.o: linit.c lprefix.h lua.h luaconf.h lualib.h lauxlib.h +liolib.o: liolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +llex.o: llex.c lprefix.h lua.h luaconf.h lctype.h llimits.h ldebug.h \ + lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lgc.h llex.h lparser.h \ + lstring.h ltable.h +lmathlib.o: lmathlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +lmem.o: lmem.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ + llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h +loadlib.o: loadlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +lobject.o: lobject.c lprefix.h lua.h luaconf.h lctype.h llimits.h \ + ldebug.h lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h \ + lvm.h +lopcodes.o: lopcodes.c lprefix.h lopcodes.h llimits.h lua.h luaconf.h +loslib.o: loslib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +lparser.o: lparser.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \ + llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \ + ldo.h lfunc.h lstring.h lgc.h ltable.h +lstate.o: lstate.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \ + lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h \ + lstring.h ltable.h +lstring.o: lstring.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \ + lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h +lstrlib.o: lstrlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +ltable.o: ltable.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ + llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h +ltablib.o: ltablib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +ltm.o: ltm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ + llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h ltable.h lvm.h +lua.o: lua.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +luac.o: luac.c lprefix.h lua.h luaconf.h lauxlib.h lobject.h llimits.h \ + lstate.h ltm.h lzio.h lmem.h lundump.h ldebug.h lopcodes.h +lundump.o: lundump.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \ + lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h \ + lundump.h +lutf8lib.o: lutf8lib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h +lvm.o: lvm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ + llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h \ + ltable.h lvm.h +lzio.o: lzio.c lprefix.h lua.h luaconf.h llimits.h lmem.h lstate.h \ + lobject.h ltm.h lzio.h + +# (end of Makefile) diff --git a/app/src/main/jni/lua/lapi.c b/app/src/main/jni/lua/lapi.c index 5d5145d..c9455a5 100644 --- a/app/src/main/jni/lua/lapi.c +++ b/app/src/main/jni/lua/lapi.c @@ -1,18 +1,18 @@ /* -** $Id: lapi.c,v 2.55.1.5 2008/07/04 18:41:18 roberto Exp $ +** $Id: lapi.c,v 2.259 2016/02/29 14:27:14 roberto Exp $ ** Lua API ** See Copyright Notice in lua.h */ +#define lapi_c +#define LUA_CORE + +#include "lprefix.h" + -#include -#include #include #include -#define lapi_c -#define LUA_CORE - #include "lua.h" #include "lapi.h" @@ -32,76 +32,84 @@ const char lua_ident[] = - "$Lua: " LUA_RELEASE " " LUA_COPYRIGHT " $\n" - "$Authors: " LUA_AUTHORS " $\n" - "$URL: www.lua.org $\n"; + "$LuaVersion: " LUA_COPYRIGHT " $" + "$LuaAuthors: " LUA_AUTHORS " $"; + +/* value at a non-valid index */ +#define NONVALIDVALUE cast(TValue *, luaO_nilobject) +/* corresponding test */ +#define isvalid(o) ((o) != luaO_nilobject) -#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) +/* test for pseudo index */ +#define ispseudo(i) ((i) <= LUA_REGISTRYINDEX) -#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject) +/* test for upvalue */ +#define isupvalue(i) ((i) < LUA_REGISTRYINDEX) -#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} +/* test for valid but not pseudo index */ +#define isstackindex(i, o) (isvalid(o) && !ispseudo(i)) +#define api_checkvalidindex(l,o) api_check(l, isvalid(o), "invalid index") +#define api_checkstackindex(l, i, o) \ + api_check(l, isstackindex(i, o), "index not in the stack") -static TValue *index2adr (lua_State *L, int idx) { + +static TValue *index2addr (lua_State *L, int idx) { + CallInfo *ci = L->ci; if (idx > 0) { - TValue *o = L->base + (idx - 1); - api_check(L, idx <= L->ci->top - L->base); - if (o >= L->top) return cast(TValue *, luaO_nilobject); + TValue *o = ci->func + idx; + api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index"); + if (o >= L->top) return NONVALIDVALUE; else return o; } - else if (idx > LUA_REGISTRYINDEX) { - api_check(L, idx != 0 && -idx <= L->top - L->base); + else if (!ispseudo(idx)) { /* negative index */ + api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); return L->top + idx; } - else switch (idx) { /* pseudo-indices */ - case LUA_REGISTRYINDEX: return registry(L); - case LUA_ENVIRONINDEX: { - Closure *func = curr_func(L); - sethvalue(L, &L->env, func->c.env); - return &L->env; - } - case LUA_GLOBALSINDEX: return gt(L); - default: { - Closure *func = curr_func(L); - idx = LUA_GLOBALSINDEX - idx; - return (idx <= func->c.nupvalues) - ? &func->c.upvalue[idx-1] - : cast(TValue *, luaO_nilobject); + else if (idx == LUA_REGISTRYINDEX) + return &G(L)->l_registry; + else { /* upvalues */ + idx = LUA_REGISTRYINDEX - idx; + api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); + if (ttislcf(ci->func)) /* light C function? */ + return NONVALIDVALUE; /* it has no upvalues */ + else { + CClosure *func = clCvalue(ci->func); + return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : NONVALIDVALUE; } } } -static Table *getcurrenv (lua_State *L) { - if (L->ci == L->base_ci) /* no enclosing function? */ - return hvalue(gt(L)); /* use global table as environment */ - else { - Closure *func = curr_func(L); - return func->c.env; - } -} - - -void luaA_pushobject (lua_State *L, const TValue *o) { - setobj2s(L, L->top, o); - api_incr_top(L); +/* +** to be called by 'lua_checkstack' in protected mode, to grow stack +** capturing memory errors +*/ +static void growstack (lua_State *L, void *ud) { + int size = *(int *)ud; + luaD_growstack(L, size); } -LUA_API int lua_checkstack (lua_State *L, int size) { - int res = 1; +LUA_API int lua_checkstack (lua_State *L, int n) { + int res; + CallInfo *ci = L->ci; lua_lock(L); - if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) - res = 0; /* stack overflow */ - else if (size > 0) { - luaD_checkstack(L, size); - if (L->ci->top < L->top + size) - L->ci->top = L->top + size; + api_check(L, n >= 0, "negative 'n'"); + if (L->stack_last - L->top > n) /* stack large enough? */ + res = 1; /* yes; check is OK */ + else { /* no; need to grow stack */ + int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; + if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */ + res = 0; /* no */ + else /* try to grow stack */ + res = (luaD_rawrunprotected(L, &growstack, &n) == LUA_OK); } + if (res && ci->top < L->top + n) + ci->top = L->top + n; /* adjust frame top */ lua_unlock(L); return res; } @@ -112,21 +120,17 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { if (from == to) return; lua_lock(to); api_checknelems(from, n); - api_check(from, G(from) == G(to)); - api_check(from, to->ci->top - to->top >= n); + api_check(from, G(from) == G(to), "moving among independent states"); + api_check(from, to->ci->top - to->top >= n, "stack overflow"); from->top -= n; for (i = 0; i < n; i++) { - setobj2s(to, to->top++, from->top + i); + setobj2s(to, to->top, from->top + i); + to->top++; /* stack already checked by previous 'api_check' */ } lua_unlock(to); } -LUA_API void lua_setlevel (lua_State *from, lua_State *to) { - to->nCcalls = from->nCcalls; -} - - LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { lua_CFunction old; lua_lock(L); @@ -137,16 +141,10 @@ LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { } -LUA_API lua_State *lua_newthread (lua_State *L) { - lua_State *L1; - lua_lock(L); - luaC_checkGC(L); - L1 = luaE_newthread(L); - setthvalue(L, L->top, L1); - api_incr_top(L); - lua_unlock(L); - luai_userstatethread(L, L1); - return L1; +LUA_API const lua_Number *lua_version (lua_State *L) { + static const lua_Number version = LUA_VERSION_NUM; + if (L == NULL) return &version; + else return G(L)->version; } @@ -156,78 +154,89 @@ LUA_API lua_State *lua_newthread (lua_State *L) { */ +/* +** convert an acceptable stack index into an absolute index +*/ +LUA_API int lua_absindex (lua_State *L, int idx) { + return (idx > 0 || ispseudo(idx)) + ? idx + : cast_int(L->top - L->ci->func) + idx; +} + + LUA_API int lua_gettop (lua_State *L) { - return cast_int(L->top - L->base); + return cast_int(L->top - (L->ci->func + 1)); } LUA_API void lua_settop (lua_State *L, int idx) { + StkId func = L->ci->func; lua_lock(L); if (idx >= 0) { - api_check(L, idx <= L->stack_last - L->base); - while (L->top < L->base + idx) + api_check(L, idx <= L->stack_last - (func + 1), "new top too large"); + while (L->top < (func + 1) + idx) setnilvalue(L->top++); - L->top = L->base + idx; + L->top = (func + 1) + idx; } else { - api_check(L, -(idx+1) <= (L->top - L->base)); - L->top += idx+1; /* `subtract' index (index is negative) */ + api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); + L->top += idx+1; /* 'subtract' index (index is negative) */ } lua_unlock(L); } -LUA_API void lua_remove (lua_State *L, int idx) { - StkId p; - lua_lock(L); - p = index2adr(L, idx); - api_checkvalidindex(L, p); - while (++p < L->top) setobjs2s(L, p-1, p); - L->top--; - lua_unlock(L); +/* +** Reverse the stack segment from 'from' to 'to' +** (auxiliary to 'lua_rotate') +*/ +static void reverse (lua_State *L, StkId from, StkId to) { + for (; from < to; from++, to--) { + TValue temp; + setobj(L, &temp, from); + setobjs2s(L, from, to); + setobj2s(L, to, &temp); + } } -LUA_API void lua_insert (lua_State *L, int idx) { - StkId p; - StkId q; +/* +** Let x = AB, where A is a prefix of length 'n'. Then, +** rotate x n == BA. But BA == (A^r . B^r)^r. +*/ +LUA_API void lua_rotate (lua_State *L, int idx, int n) { + StkId p, t, m; lua_lock(L); - p = index2adr(L, idx); - api_checkvalidindex(L, p); - for (q = L->top; q>p; q--) setobjs2s(L, q, q-1); - setobjs2s(L, p, L->top); + t = L->top - 1; /* end of stack segment being rotated */ + p = index2addr(L, idx); /* start of segment */ + api_checkstackindex(L, idx, p); + api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'"); + m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */ + reverse(L, p, m); /* reverse the prefix with length 'n' */ + reverse(L, m + 1, t); /* reverse the suffix */ + reverse(L, p, t); /* reverse the entire segment */ lua_unlock(L); } -LUA_API void lua_replace (lua_State *L, int idx) { - StkId o; +LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { + TValue *fr, *to; lua_lock(L); - /* explicit test for incompatible code */ - if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci) - luaG_runerror(L, "no calling environment"); - api_checknelems(L, 1); - o = index2adr(L, idx); - api_checkvalidindex(L, o); - if (idx == LUA_ENVIRONINDEX) { - Closure *func = curr_func(L); - api_check(L, ttistable(L->top - 1)); - func->c.env = hvalue(L->top - 1); - luaC_barrier(L, func, L->top - 1); - } - else { - setobj(L, o, L->top - 1); - if (idx < LUA_GLOBALSINDEX) /* function upvalue? */ - luaC_barrier(L, curr_func(L), L->top - 1); - } - L->top--; + fr = index2addr(L, fromidx); + to = index2addr(L, toidx); + api_checkvalidindex(L, to); + setobj(L, to, fr); + if (isupvalue(toidx)) /* function upvalue? */ + luaC_barrier(L, clCvalue(L->ci->func), fr); + /* LUA_REGISTRYINDEX does not need gc barrier + (collector revisits it before finishing collection) */ lua_unlock(L); } LUA_API void lua_pushvalue (lua_State *L, int idx) { lua_lock(L); - setobj2s(L, L->top, index2adr(L, idx)); + setobj2s(L, L->top, index2addr(L, idx)); api_incr_top(L); lua_unlock(L); } @@ -240,152 +249,171 @@ LUA_API void lua_pushvalue (lua_State *L, int idx) { LUA_API int lua_type (lua_State *L, int idx) { - StkId o = index2adr(L, idx); - return (o == luaO_nilobject) ? LUA_TNONE : ttype(o); + StkId o = index2addr(L, idx); + return (isvalid(o) ? ttnov(o) : LUA_TNONE); } LUA_API const char *lua_typename (lua_State *L, int t) { UNUSED(L); - return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; + api_check(L, LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag"); + return ttypename(t); } LUA_API int lua_iscfunction (lua_State *L, int idx) { - StkId o = index2adr(L, idx); - return iscfunction(o); + StkId o = index2addr(L, idx); + return (ttislcf(o) || (ttisCclosure(o))); +} + + +LUA_API int lua_isinteger (lua_State *L, int idx) { + StkId o = index2addr(L, idx); + return ttisinteger(o); } LUA_API int lua_isnumber (lua_State *L, int idx) { - TValue n; - const TValue *o = index2adr(L, idx); + lua_Number n; + const TValue *o = index2addr(L, idx); return tonumber(o, &n); } LUA_API int lua_isstring (lua_State *L, int idx) { - int t = lua_type(L, idx); - return (t == LUA_TSTRING || t == LUA_TNUMBER); + const TValue *o = index2addr(L, idx); + return (ttisstring(o) || cvt2str(o)); } LUA_API int lua_isuserdata (lua_State *L, int idx) { - const TValue *o = index2adr(L, idx); - return (ttisuserdata(o) || ttislightuserdata(o)); + const TValue *o = index2addr(L, idx); + return (ttisfulluserdata(o) || ttislightuserdata(o)); } LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { - StkId o1 = index2adr(L, index1); - StkId o2 = index2adr(L, index2); - return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 - : luaO_rawequalObj(o1, o2); + StkId o1 = index2addr(L, index1); + StkId o2 = index2addr(L, index2); + return (isvalid(o1) && isvalid(o2)) ? luaV_rawequalobj(o1, o2) : 0; } -LUA_API int lua_equal (lua_State *L, int index1, int index2) { - StkId o1, o2; - int i; - lua_lock(L); /* may call tag method */ - o1 = index2adr(L, index1); - o2 = index2adr(L, index2); - i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2); +LUA_API void lua_arith (lua_State *L, int op) { + lua_lock(L); + if (op != LUA_OPUNM && op != LUA_OPBNOT) + api_checknelems(L, 2); /* all other operations expect two operands */ + else { /* for unary operations, add fake 2nd operand */ + api_checknelems(L, 1); + setobjs2s(L, L->top, L->top - 1); + api_incr_top(L); + } + /* first operand at top - 2, second at top - 1; result go to top - 2 */ + luaO_arith(L, op, L->top - 2, L->top - 1, L->top - 2); + L->top--; /* remove second operand */ lua_unlock(L); - return i; } -LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { +LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { StkId o1, o2; - int i; + int i = 0; lua_lock(L); /* may call tag method */ - o1 = index2adr(L, index1); - o2 = index2adr(L, index2); - i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 - : luaV_lessthan(L, o1, o2); + o1 = index2addr(L, index1); + o2 = index2addr(L, index2); + if (isvalid(o1) && isvalid(o2)) { + switch (op) { + case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break; + case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; + case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; + default: api_check(L, 0, "invalid option"); + } + } lua_unlock(L); return i; } +LUA_API size_t lua_stringtonumber (lua_State *L, const char *s) { + size_t sz = luaO_str2num(s, L->top); + if (sz != 0) + api_incr_top(L); + return sz; +} -LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { - TValue n; - const TValue *o = index2adr(L, idx); - if (tonumber(o, &n)) - return nvalue(o); - else - return 0; + +LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *pisnum) { + lua_Number n; + const TValue *o = index2addr(L, idx); + int isnum = tonumber(o, &n); + if (!isnum) + n = 0; /* call to 'tonumber' may change 'n' even if it fails */ + if (pisnum) *pisnum = isnum; + return n; } -LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { - TValue n; - const TValue *o = index2adr(L, idx); - if (tonumber(o, &n)) { - lua_Integer res; - lua_Number num = nvalue(o); - lua_number2integer(res, num); - return res; - } - else - return 0; +LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *pisnum) { + lua_Integer res; + const TValue *o = index2addr(L, idx); + int isnum = tointeger(o, &res); + if (!isnum) + res = 0; /* call to 'tointeger' may change 'n' even if it fails */ + if (pisnum) *pisnum = isnum; + return res; } LUA_API int lua_toboolean (lua_State *L, int idx) { - const TValue *o = index2adr(L, idx); + const TValue *o = index2addr(L, idx); return !l_isfalse(o); } LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { - StkId o = index2adr(L, idx); + StkId o = index2addr(L, idx); if (!ttisstring(o)) { - lua_lock(L); /* `luaV_tostring' may create a new string */ - if (!luaV_tostring(L, o)) { /* conversion failed? */ + if (!cvt2str(o)) { /* not convertible? */ if (len != NULL) *len = 0; - lua_unlock(L); return NULL; } + lua_lock(L); /* 'luaO_tostring' may create a new string */ + luaO_tostring(L, o); luaC_checkGC(L); - o = index2adr(L, idx); /* previous call may reallocate the stack */ + o = index2addr(L, idx); /* previous call may reallocate the stack */ lua_unlock(L); } - if (len != NULL) *len = tsvalue(o)->len; + if (len != NULL) + *len = vslen(o); return svalue(o); } -LUA_API size_t lua_objlen (lua_State *L, int idx) { - StkId o = index2adr(L, idx); +LUA_API size_t lua_rawlen (lua_State *L, int idx) { + StkId o = index2addr(L, idx); switch (ttype(o)) { - case LUA_TSTRING: return tsvalue(o)->len; + case LUA_TSHRSTR: return tsvalue(o)->shrlen; + case LUA_TLNGSTR: return tsvalue(o)->u.lnglen; case LUA_TUSERDATA: return uvalue(o)->len; case LUA_TTABLE: return luaH_getn(hvalue(o)); - case LUA_TNUMBER: { - size_t l; - lua_lock(L); /* `luaV_tostring' may create a new string */ - l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0); - lua_unlock(L); - return l; - } default: return 0; } } LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { - StkId o = index2adr(L, idx); - return (!iscfunction(o)) ? NULL : clvalue(o)->c.f; + StkId o = index2addr(L, idx); + if (ttislcf(o)) return fvalue(o); + else if (ttisCclosure(o)) + return clCvalue(o)->f; + else return NULL; /* not a C function */ } LUA_API void *lua_touserdata (lua_State *L, int idx) { - StkId o = index2adr(L, idx); - switch (ttype(o)) { - case LUA_TUSERDATA: return (rawuvalue(o) + 1); + StkId o = index2addr(L, idx); + switch (ttnov(o)) { + case LUA_TUSERDATA: return getudatamem(uvalue(o)); case LUA_TLIGHTUSERDATA: return pvalue(o); default: return NULL; } @@ -393,20 +421,21 @@ LUA_API void *lua_touserdata (lua_State *L, int idx) { LUA_API lua_State *lua_tothread (lua_State *L, int idx) { - StkId o = index2adr(L, idx); + StkId o = index2addr(L, idx); return (!ttisthread(o)) ? NULL : thvalue(o); } LUA_API const void *lua_topointer (lua_State *L, int idx) { - StkId o = index2adr(L, idx); + StkId o = index2addr(L, idx); switch (ttype(o)) { case LUA_TTABLE: return hvalue(o); - case LUA_TFUNCTION: return clvalue(o); + case LUA_TLCL: return clLvalue(o); + case LUA_TCCL: return clCvalue(o); + case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o))); case LUA_TTHREAD: return thvalue(o); - case LUA_TUSERDATA: - case LUA_TLIGHTUSERDATA: - return lua_touserdata(L, idx); + case LUA_TUSERDATA: return getudatamem(uvalue(o)); + case LUA_TLIGHTUSERDATA: return pvalue(o); default: return NULL; } } @@ -428,7 +457,7 @@ LUA_API void lua_pushnil (lua_State *L) { LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { lua_lock(L); - setnvalue(L->top, n); + setfltvalue(L->top, n); api_incr_top(L); lua_unlock(L); } @@ -436,26 +465,43 @@ LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { lua_lock(L); - setnvalue(L->top, cast_num(n)); + setivalue(L->top, n); api_incr_top(L); lua_unlock(L); } -LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { +/* +** Pushes on the stack a string with given length. Avoid using 's' when +** 'len' == 0 (as 's' can be NULL in that case), due to later use of +** 'memcmp' and 'memcpy'. +*/ +LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { + TString *ts; lua_lock(L); - luaC_checkGC(L); - setsvalue2s(L, L->top, luaS_newlstr(L, s, len)); + ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len); + setsvalue2s(L, L->top, ts); api_incr_top(L); + luaC_checkGC(L); lua_unlock(L); + return getstr(ts); } -LUA_API void lua_pushstring (lua_State *L, const char *s) { +LUA_API const char *lua_pushstring (lua_State *L, const char *s) { + lua_lock(L); if (s == NULL) - lua_pushnil(L); - else - lua_pushlstring(L, s, strlen(s)); + setnilvalue(L->top); + else { + TString *ts; + ts = luaS_new(L, s); + setsvalue2s(L, L->top, ts); + s = getstr(ts); /* internal copy's address */ + } + api_incr_top(L); + luaC_checkGC(L); + lua_unlock(L); + return s; } @@ -463,8 +509,8 @@ LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, va_list argp) { const char *ret; lua_lock(L); - luaC_checkGC(L); ret = luaO_pushvfstring(L, fmt, argp); + luaC_checkGC(L); lua_unlock(L); return ret; } @@ -474,28 +520,35 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { const char *ret; va_list argp; lua_lock(L); - luaC_checkGC(L); va_start(argp, fmt); ret = luaO_pushvfstring(L, fmt, argp); va_end(argp); + luaC_checkGC(L); lua_unlock(L); return ret; } LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { - Closure *cl; lua_lock(L); - luaC_checkGC(L); - api_checknelems(L, n); - cl = luaF_newCclosure(L, n, getcurrenv(L)); - cl->c.f = fn; - L->top -= n; - while (n--) - setobj2n(L, &cl->c.upvalue[n], L->top+n); - setclvalue(L, L->top, cl); - lua_assert(iswhite(obj2gco(cl))); + if (n == 0) { + setfvalue(L->top, fn); + } + else { + CClosure *cl; + api_checknelems(L, n); + api_check(L, n <= MAXUPVAL, "upvalue index too large"); + cl = luaF_newCclosure(L, n); + cl->f = fn; + L->top -= n; + while (n--) { + setobj2n(L, &cl->upvalue[n], L->top + n); + /* does not need barrier because closure is white */ + } + setclCvalue(L, L->top, cl); + } api_incr_top(L); + luaC_checkGC(L); lua_unlock(L); } @@ -531,66 +584,122 @@ LUA_API int lua_pushthread (lua_State *L) { */ -LUA_API void lua_gettable (lua_State *L, int idx) { +static int auxgetstr (lua_State *L, const TValue *t, const char *k) { + const TValue *slot; + TString *str = luaS_new(L, k); + if (luaV_fastget(L, t, str, slot, luaH_getstr)) { + setobj2s(L, L->top, slot); + api_incr_top(L); + } + else { + setsvalue2s(L, L->top, str); + api_incr_top(L); + luaV_finishget(L, t, L->top - 1, L->top - 1, slot); + } + lua_unlock(L); + return ttnov(L->top - 1); +} + + +LUA_API int lua_getglobal (lua_State *L, const char *name) { + Table *reg = hvalue(&G(L)->l_registry); + lua_lock(L); + return auxgetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); +} + + +LUA_API int lua_gettable (lua_State *L, int idx) { StkId t; lua_lock(L); - t = index2adr(L, idx); - api_checkvalidindex(L, t); + t = index2addr(L, idx); luaV_gettable(L, t, L->top - 1, L->top - 1); lua_unlock(L); + return ttnov(L->top - 1); } -LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { +LUA_API int lua_getfield (lua_State *L, int idx, const char *k) { + lua_lock(L); + return auxgetstr(L, index2addr(L, idx), k); +} + + +LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { StkId t; - TValue key; + const TValue *slot; lua_lock(L); - t = index2adr(L, idx); - api_checkvalidindex(L, t); - setsvalue(L, &key, luaS_new(L, k)); - luaV_gettable(L, t, &key, L->top); - api_incr_top(L); + t = index2addr(L, idx); + if (luaV_fastget(L, t, n, slot, luaH_getint)) { + setobj2s(L, L->top, slot); + api_incr_top(L); + } + else { + setivalue(L->top, n); + api_incr_top(L); + luaV_finishget(L, t, L->top - 1, L->top - 1, slot); + } lua_unlock(L); + return ttnov(L->top - 1); } -LUA_API void lua_rawget (lua_State *L, int idx) { +LUA_API int lua_rawget (lua_State *L, int idx) { StkId t; lua_lock(L); - t = index2adr(L, idx); - api_check(L, ttistable(t)); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); lua_unlock(L); + return ttnov(L->top - 1); } -LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { - StkId o; +LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) { + StkId t; lua_lock(L); - o = index2adr(L, idx); - api_check(L, ttistable(o)); - setobj2s(L, L->top, luaH_getnum(hvalue(o), n)); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + setobj2s(L, L->top, luaH_getint(hvalue(t), n)); api_incr_top(L); lua_unlock(L); + return ttnov(L->top - 1); +} + + +LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) { + StkId t; + TValue k; + lua_lock(L); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + setpvalue(&k, cast(void *, p)); + setobj2s(L, L->top, luaH_get(hvalue(t), &k)); + api_incr_top(L); + lua_unlock(L); + return ttnov(L->top - 1); } LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { + Table *t; lua_lock(L); - luaC_checkGC(L); - sethvalue(L, L->top, luaH_new(L, narray, nrec)); + t = luaH_new(L); + sethvalue(L, L->top, t); api_incr_top(L); + if (narray > 0 || nrec > 0) + luaH_resize(L, t, narray, nrec); + luaC_checkGC(L); lua_unlock(L); } LUA_API int lua_getmetatable (lua_State *L, int objindex) { const TValue *obj; - Table *mt = NULL; - int res; + Table *mt; + int res = 0; lua_lock(L); - obj = index2adr(L, objindex); - switch (ttype(obj)) { + obj = index2addr(L, objindex); + switch (ttnov(obj)) { case LUA_TTABLE: mt = hvalue(obj)->metatable; break; @@ -598,12 +707,10 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { mt = uvalue(obj)->metatable; break; default: - mt = G(L)->mt[ttype(obj)]; + mt = G(L)->mt[ttnov(obj)]; break; } - if (mt == NULL) - res = 0; - else { + if (mt != NULL) { sethvalue(L, L->top, mt); api_incr_top(L); res = 1; @@ -613,27 +720,15 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { } -LUA_API void lua_getfenv (lua_State *L, int idx) { +LUA_API int lua_getuservalue (lua_State *L, int idx) { StkId o; lua_lock(L); - o = index2adr(L, idx); - api_checkvalidindex(L, o); - switch (ttype(o)) { - case LUA_TFUNCTION: - sethvalue(L, L->top, clvalue(o)->c.env); - break; - case LUA_TUSERDATA: - sethvalue(L, L->top, uvalue(o)->env); - break; - case LUA_TTHREAD: - setobj2s(L, L->top, gt(thvalue(o))); - break; - default: - setnilvalue(L->top); - break; - } + o = index2addr(L, idx); + api_check(L, ttisfulluserdata(o), "full userdata expected"); + getuservalue(L, uvalue(o), L->top); api_incr_top(L); lua_unlock(L); + return ttnov(L->top - 1); } @@ -641,13 +736,37 @@ LUA_API void lua_getfenv (lua_State *L, int idx) { ** set functions (stack -> Lua) */ +/* +** t[k] = value at the top of the stack (where 'k' is a string) +*/ +static void auxsetstr (lua_State *L, const TValue *t, const char *k) { + const TValue *slot; + TString *str = luaS_new(L, k); + api_checknelems(L, 1); + if (luaV_fastset(L, t, str, slot, luaH_getstr, L->top - 1)) + L->top--; /* pop value */ + else { + setsvalue2s(L, L->top, str); /* push 'str' (to make it a TValue) */ + api_incr_top(L); + luaV_finishset(L, t, L->top - 1, L->top - 2, slot); + L->top -= 2; /* pop value and key */ + } + lua_unlock(L); /* lock done by caller */ +} + + +LUA_API void lua_setglobal (lua_State *L, const char *name) { + Table *reg = hvalue(&G(L)->l_registry); + lua_lock(L); /* unlock done in 'auxsetstr' */ + auxsetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); +} + LUA_API void lua_settable (lua_State *L, int idx) { StkId t; lua_lock(L); api_checknelems(L, 2); - t = index2adr(L, idx); - api_checkvalidindex(L, t); + t = index2addr(L, idx); luaV_settable(L, t, L->top - 2, L->top - 1); L->top -= 2; /* pop index and value */ lua_unlock(L); @@ -655,40 +774,69 @@ LUA_API void lua_settable (lua_State *L, int idx) { LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { + lua_lock(L); /* unlock done in 'auxsetstr' */ + auxsetstr(L, index2addr(L, idx), k); +} + + +LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { StkId t; - TValue key; + const TValue *slot; lua_lock(L); api_checknelems(L, 1); - t = index2adr(L, idx); - api_checkvalidindex(L, t); - setsvalue(L, &key, luaS_new(L, k)); - luaV_settable(L, t, &key, L->top - 1); - L->top--; /* pop value */ + t = index2addr(L, idx); + if (luaV_fastset(L, t, n, slot, luaH_getint, L->top - 1)) + L->top--; /* pop value */ + else { + setivalue(L->top, n); + api_incr_top(L); + luaV_finishset(L, t, L->top - 1, L->top - 2, slot); + L->top -= 2; /* pop value and key */ + } lua_unlock(L); } LUA_API void lua_rawset (lua_State *L, int idx) { - StkId t; + StkId o; + TValue *slot; lua_lock(L); api_checknelems(L, 2); - t = index2adr(L, idx); - api_check(L, ttistable(t)); - setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); - luaC_barriert(L, hvalue(t), L->top-1); + o = index2addr(L, idx); + api_check(L, ttistable(o), "table expected"); + slot = luaH_set(L, hvalue(o), L->top - 2); + setobj2t(L, slot, L->top - 1); + invalidateTMcache(hvalue(o)); + luaC_barrierback(L, hvalue(o), L->top-1); L->top -= 2; lua_unlock(L); } -LUA_API void lua_rawseti (lua_State *L, int idx, int n) { +LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { StkId o; lua_lock(L); api_checknelems(L, 1); - o = index2adr(L, idx); - api_check(L, ttistable(o)); - setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); - luaC_barriert(L, hvalue(o), L->top-1); + o = index2addr(L, idx); + api_check(L, ttistable(o), "table expected"); + luaH_setint(L, hvalue(o), n, L->top - 1); + luaC_barrierback(L, hvalue(o), L->top-1); + L->top--; + lua_unlock(L); +} + + +LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { + StkId o; + TValue k, *slot; + lua_lock(L); + api_checknelems(L, 1); + o = index2addr(L, idx); + api_check(L, ttistable(o), "table expected"); + setpvalue(&k, cast(void *, p)); + slot = luaH_set(L, hvalue(o), &k); + setobj2t(L, slot, L->top - 1); + luaC_barrierback(L, hvalue(o), L->top - 1); L->top--; lua_unlock(L); } @@ -699,29 +847,32 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { Table *mt; lua_lock(L); api_checknelems(L, 1); - obj = index2adr(L, objindex); - api_checkvalidindex(L, obj); + obj = index2addr(L, objindex); if (ttisnil(L->top - 1)) mt = NULL; else { - api_check(L, ttistable(L->top - 1)); + api_check(L, ttistable(L->top - 1), "table expected"); mt = hvalue(L->top - 1); } - switch (ttype(obj)) { + switch (ttnov(obj)) { case LUA_TTABLE: { hvalue(obj)->metatable = mt; - if (mt) - luaC_objbarriert(L, hvalue(obj), mt); + if (mt) { + luaC_objbarrier(L, gcvalue(obj), mt); + luaC_checkfinalizer(L, gcvalue(obj), mt); + } break; } case LUA_TUSERDATA: { uvalue(obj)->metatable = mt; - if (mt) - luaC_objbarrier(L, rawuvalue(obj), mt); + if (mt) { + luaC_objbarrier(L, uvalue(obj), mt); + luaC_checkfinalizer(L, gcvalue(obj), mt); + } break; } default: { - G(L)->mt[ttype(obj)] = mt; + G(L)->mt[ttnov(obj)] = mt; break; } } @@ -731,55 +882,46 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { } -LUA_API int lua_setfenv (lua_State *L, int idx) { +LUA_API void lua_setuservalue (lua_State *L, int idx) { StkId o; - int res = 1; lua_lock(L); api_checknelems(L, 1); - o = index2adr(L, idx); - api_checkvalidindex(L, o); - api_check(L, ttistable(L->top - 1)); - switch (ttype(o)) { - case LUA_TFUNCTION: - clvalue(o)->c.env = hvalue(L->top - 1); - break; - case LUA_TUSERDATA: - uvalue(o)->env = hvalue(L->top - 1); - break; - case LUA_TTHREAD: - sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1)); - break; - default: - res = 0; - break; - } - if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); + o = index2addr(L, idx); + api_check(L, ttisfulluserdata(o), "full userdata expected"); + setuservalue(L, uvalue(o), L->top - 1); + luaC_barrier(L, gcvalue(o), L->top - 1); L->top--; lua_unlock(L); - return res; } /* -** `load' and `call' functions (run Lua code) +** 'load' and 'call' functions (run Lua code) */ -#define adjustresults(L,nres) \ - { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; } - - #define checkresults(L,na,nr) \ - api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na))) - + api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ + "results from function overflow current stack size") -LUA_API void lua_call (lua_State *L, int nargs, int nresults) { + +LUA_API void lua_callk (lua_State *L, int nargs, int nresults, + lua_KContext ctx, lua_KFunction k) { StkId func; lua_lock(L); + api_check(L, k == NULL || !isLua(L->ci), + "cannot use continuations inside hooks"); api_checknelems(L, nargs+1); + api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); checkresults(L, nargs, nresults); func = L->top - (nargs+1); - luaD_call(L, func, nresults); + if (k != NULL && L->nny == 0) { /* need to prepare continuation? */ + L->ci->u.c.k = k; /* save continuation */ + L->ci->u.c.ctx = ctx; /* save context */ + luaD_call(L, func, nresults); /* do the call */ + } + else /* no continuation or no yieldable */ + luaD_callnoyield(L, func, nresults); /* just do the call */ adjustresults(L, nresults); lua_unlock(L); } @@ -789,7 +931,7 @@ LUA_API void lua_call (lua_State *L, int nargs, int nresults) { /* ** Execute a protected call. */ -struct CallS { /* data to `f_call' */ +struct CallS { /* data to 'f_call' */ StkId func; int nresults; }; @@ -797,89 +939,87 @@ struct CallS { /* data to `f_call' */ static void f_call (lua_State *L, void *ud) { struct CallS *c = cast(struct CallS *, ud); - luaD_call(L, c->func, c->nresults); + luaD_callnoyield(L, c->func, c->nresults); } -LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) { +LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, + lua_KContext ctx, lua_KFunction k) { struct CallS c; int status; ptrdiff_t func; lua_lock(L); + api_check(L, k == NULL || !isLua(L->ci), + "cannot use continuations inside hooks"); api_checknelems(L, nargs+1); + api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); checkresults(L, nargs, nresults); if (errfunc == 0) func = 0; else { - StkId o = index2adr(L, errfunc); - api_checkvalidindex(L, o); + StkId o = index2addr(L, errfunc); + api_checkstackindex(L, errfunc, o); func = savestack(L, o); } c.func = L->top - (nargs+1); /* function to be called */ - c.nresults = nresults; - status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); + if (k == NULL || L->nny > 0) { /* no continuation or no yieldable? */ + c.nresults = nresults; /* do a 'conventional' protected call */ + status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); + } + else { /* prepare continuation (call is already protected by 'resume') */ + CallInfo *ci = L->ci; + ci->u.c.k = k; /* save continuation */ + ci->u.c.ctx = ctx; /* save context */ + /* save information for error recovery */ + ci->extra = savestack(L, c.func); + ci->u.c.old_errfunc = L->errfunc; + L->errfunc = func; + setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */ + ci->callstatus |= CIST_YPCALL; /* function can do error recovery */ + luaD_call(L, c.func, nresults); /* do the call */ + ci->callstatus &= ~CIST_YPCALL; + L->errfunc = ci->u.c.old_errfunc; + status = LUA_OK; /* if it is here, there were no errors */ + } adjustresults(L, nresults); lua_unlock(L); return status; } -/* -** Execute a protected C call. -*/ -struct CCallS { /* data to `f_Ccall' */ - lua_CFunction func; - void *ud; -}; - - -static void f_Ccall (lua_State *L, void *ud) { - struct CCallS *c = cast(struct CCallS *, ud); - Closure *cl; - cl = luaF_newCclosure(L, 0, getcurrenv(L)); - cl->c.f = c->func; - setclvalue(L, L->top, cl); /* push function */ - api_incr_top(L); - setpvalue(L->top, c->ud); /* push only argument */ - api_incr_top(L); - luaD_call(L, L->top - 2, 0); -} - - -LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) { - struct CCallS c; - int status; - lua_lock(L); - c.func = func; - c.ud = ud; - status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0); - lua_unlock(L); - return status; -} - - LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, - const char *chunkname) { + const char *chunkname, const char *mode) { ZIO z; int status; lua_lock(L); if (!chunkname) chunkname = "?"; luaZ_init(L, &z, reader, data); - status = luaD_protectedparser(L, &z, chunkname); + status = luaD_protectedparser(L, &z, chunkname, mode); + if (status == LUA_OK) { /* no errors? */ + LClosure *f = clLvalue(L->top - 1); /* get newly created function */ + if (f->nupvalues >= 1) { /* does it have an upvalue? */ + /* get global table from registry */ + Table *reg = hvalue(&G(L)->l_registry); + const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS); + /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ + setobj(L, f->upvals[0]->v, gt); + luaC_upvalbarrier(L, f->upvals[0]); + } + } lua_unlock(L); return status; } -LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { +LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { int status; TValue *o; lua_lock(L); api_checknelems(L, 1); o = L->top - 1; if (isLfunction(o)) - status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0); + status = luaU_dump(L, getproto(o), writer, data, strip); else status = 1; lua_unlock(L); @@ -887,7 +1027,7 @@ LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { } -LUA_API int lua_status (lua_State *L) { +LUA_API int lua_status (lua_State *L) { return L->status; } @@ -903,39 +1043,43 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { g = G(L); switch (what) { case LUA_GCSTOP: { - g->GCthreshold = MAX_LUMEM; + g->gcrunning = 0; break; } case LUA_GCRESTART: { - g->GCthreshold = g->totalbytes; + luaE_setdebt(g, 0); + g->gcrunning = 1; break; } case LUA_GCCOLLECT: { - luaC_fullgc(L); + luaC_fullgc(L, 0); break; } case LUA_GCCOUNT: { /* GC values are expressed in Kbytes: #bytes/2^10 */ - res = cast_int(g->totalbytes >> 10); + res = cast_int(gettotalbytes(g) >> 10); break; } case LUA_GCCOUNTB: { - res = cast_int(g->totalbytes & 0x3ff); + res = cast_int(gettotalbytes(g) & 0x3ff); break; } case LUA_GCSTEP: { - lu_mem a = (cast(lu_mem, data) << 10); - if (a <= g->totalbytes) - g->GCthreshold = g->totalbytes - a; - else - g->GCthreshold = 0; - while (g->GCthreshold <= g->totalbytes) { + l_mem debt = 1; /* =1 to signal that it did an actual step */ + lu_byte oldrunning = g->gcrunning; + g->gcrunning = 1; /* allow GC to run */ + if (data == 0) { + luaE_setdebt(g, -GCSTEPSIZE); /* to do a "small" step */ luaC_step(L); - if (g->gcstate == GCSpause) { /* end of cycle? */ - res = 1; /* signal it */ - break; - } } + else { /* add 'data' to total debt */ + debt = cast(l_mem, data) * 1024 + g->GCdebt; + luaE_setdebt(g, debt); + luaC_checkGC(L); + } + g->gcrunning = oldrunning; /* restore previous state */ + if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */ + res = 1; /* signal it */ break; } case LUA_GCSETPAUSE: { @@ -945,9 +1089,14 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { } case LUA_GCSETSTEPMUL: { res = g->gcstepmul; + if (data < 40) data = 40; /* avoid ridiculous low values (and 0) */ g->gcstepmul = data; break; } + case LUA_GCISRUNNING: { + res = g->gcrunning; + break; + } default: res = -1; /* invalid option */ } lua_unlock(L); @@ -965,7 +1114,7 @@ LUA_API int lua_error (lua_State *L) { lua_lock(L); api_checknelems(L, 1); luaG_errormsg(L); - lua_unlock(L); + /* code unreachable; will unlock when control actually leaves the kernel */ return 0; /* to avoid warnings */ } @@ -974,8 +1123,8 @@ LUA_API int lua_next (lua_State *L, int idx) { StkId t; int more; lua_lock(L); - t = index2adr(L, idx); - api_check(L, ttistable(t)); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); more = luaH_next(L, hvalue(t), L->top - 1); if (more) { api_incr_top(L); @@ -991,15 +1140,24 @@ LUA_API void lua_concat (lua_State *L, int n) { lua_lock(L); api_checknelems(L, n); if (n >= 2) { - luaC_checkGC(L); - luaV_concat(L, n, cast_int(L->top - L->base) - 1); - L->top -= (n-1); + luaV_concat(L, n); } else if (n == 0) { /* push empty string */ setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); api_incr_top(L); } /* else n == 1; nothing to do */ + luaC_checkGC(L); + lua_unlock(L); +} + + +LUA_API void lua_len (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = index2addr(L, idx); + luaV_objlen(L, L->top, t); + api_incr_top(L); lua_unlock(L); } @@ -1025,40 +1183,46 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { LUA_API void *lua_newuserdata (lua_State *L, size_t size) { Udata *u; lua_lock(L); - luaC_checkGC(L); - u = luaS_newudata(L, size, getcurrenv(L)); + u = luaS_newudata(L, size); setuvalue(L, L->top, u); api_incr_top(L); + luaC_checkGC(L); lua_unlock(L); - return u + 1; + return getudatamem(u); } - -static const char *aux_upvalue (StkId fi, int n, TValue **val) { - Closure *f; - if (!ttisfunction(fi)) return NULL; - f = clvalue(fi); - if (f->c.isC) { - if (!(1 <= n && n <= f->c.nupvalues)) return NULL; - *val = &f->c.upvalue[n-1]; - return ""; - } - else { - Proto *p = f->l.p; - if (!(1 <= n && n <= p->sizeupvalues)) return NULL; - *val = f->l.upvals[n-1]->v; - return getstr(p->upvalues[n-1]); +static const char *aux_upvalue (StkId fi, int n, TValue **val, + CClosure **owner, UpVal **uv) { + switch (ttype(fi)) { + case LUA_TCCL: { /* C closure */ + CClosure *f = clCvalue(fi); + if (!(1 <= n && n <= f->nupvalues)) return NULL; + *val = &f->upvalue[n-1]; + if (owner) *owner = f; + return ""; + } + case LUA_TLCL: { /* Lua closure */ + LClosure *f = clLvalue(fi); + TString *name; + Proto *p = f->p; + if (!(1 <= n && n <= p->sizeupvalues)) return NULL; + *val = f->upvals[n-1]->v; + if (uv) *uv = f->upvals[n - 1]; + name = p->upvalues[n-1].name; + return (name == NULL) ? "(*no name)" : getstr(name); + } + default: return NULL; /* not a closure */ } } LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { const char *name; - TValue *val; + TValue *val = NULL; /* to avoid warnings */ lua_lock(L); - name = aux_upvalue(index2adr(L, funcindex), n, &val); + name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL, NULL); if (name) { setobj2s(L, L->top, val); api_incr_top(L); @@ -1070,18 +1234,65 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { const char *name; - TValue *val; + TValue *val = NULL; /* to avoid warnings */ + CClosure *owner = NULL; + UpVal *uv = NULL; StkId fi; lua_lock(L); - fi = index2adr(L, funcindex); + fi = index2addr(L, funcindex); api_checknelems(L, 1); - name = aux_upvalue(fi, n, &val); + name = aux_upvalue(fi, n, &val, &owner, &uv); if (name) { L->top--; setobj(L, val, L->top); - luaC_barrier(L, clvalue(fi), L->top); + if (owner) { luaC_barrier(L, owner, L->top); } + else if (uv) { luaC_upvalbarrier(L, uv); } } lua_unlock(L); return name; } + +static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { + LClosure *f; + StkId fi = index2addr(L, fidx); + api_check(L, ttisLclosure(fi), "Lua function expected"); + f = clLvalue(fi); + api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); + if (pf) *pf = f; + return &f->upvals[n - 1]; /* get its upvalue pointer */ +} + + +LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { + StkId fi = index2addr(L, fidx); + switch (ttype(fi)) { + case LUA_TLCL: { /* lua closure */ + return *getupvalref(L, fidx, n, NULL); + } + case LUA_TCCL: { /* C closure */ + CClosure *f = clCvalue(fi); + api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index"); + return &f->upvalue[n - 1]; + } + default: { + api_check(L, 0, "closure expected"); + return NULL; + } + } +} + + +LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, + int fidx2, int n2) { + LClosure *f1; + UpVal **up1 = getupvalref(L, fidx1, n1, &f1); + UpVal **up2 = getupvalref(L, fidx2, n2, NULL); + luaC_upvdeccount(L, *up1); + *up1 = *up2; + (*up1)->refcount++; + if (upisopen(*up1)) (*up1)->u.open.touched = 1; + luaC_upvalbarrier(L, *up1); +} + + diff --git a/app/src/main/jni/lua/lapi.h b/app/src/main/jni/lua/lapi.h index 2c3fab2..6d36dee 100644 --- a/app/src/main/jni/lua/lapi.h +++ b/app/src/main/jni/lua/lapi.h @@ -1,5 +1,5 @@ /* -** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lapi.h,v 2.9 2015/03/06 19:49:50 roberto Exp $ ** Auxiliary functions from Lua API ** See Copyright Notice in lua.h */ @@ -8,9 +8,17 @@ #define lapi_h -#include "lobject.h" +#include "llimits.h" +#include "lstate.h" +#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \ + "stack overflow");} + +#define adjustresults(L,nres) \ + { if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; } + +#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \ + "not enough elements in the stack") -LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o); #endif diff --git a/app/src/main/jni/lua/lauxlib.c b/app/src/main/jni/lua/lauxlib.c index 10f14e2..bacf43b 100644 --- a/app/src/main/jni/lua/lauxlib.c +++ b/app/src/main/jni/lua/lauxlib.c @@ -1,11 +1,15 @@ /* -** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $ +** $Id: lauxlib.c,v 1.286 2016/01/08 15:33:09 roberto Exp $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ +#define lauxlib_c +#define LUA_LIB + +#include "lprefix.h" + -#include #include #include #include @@ -13,24 +17,143 @@ #include -/* This file uses only the official API of Lua. +/* +** This file uses only the official API of Lua. ** Any function declared here could be written as an application function. */ -#define lauxlib_c -#define LUA_LIB - #include "lua.h" #include "lauxlib.h" -#define FREELIST_REF 0 /* free list of references */ +/* +** {====================================================== +** Traceback +** ======================================================= +*/ + + +#define LEVELS1 10 /* size of the first part of the stack */ +#define LEVELS2 11 /* size of the second part of the stack */ + -/* convert a stack index to positive */ -#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ - lua_gettop(L) + (i) + 1) +/* +** search for 'objidx' in table at index -1. +** return 1 + string at top if find a good name. +*/ +static int findfield (lua_State *L, int objidx, int level) { + if (level == 0 || !lua_istable(L, -1)) + return 0; /* not found */ + lua_pushnil(L); /* start 'next' loop */ + while (lua_next(L, -2)) { /* for each pair in table */ + if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ + if (lua_rawequal(L, objidx, -1)) { /* found object? */ + lua_pop(L, 1); /* remove value (but keep name) */ + return 1; + } + else if (findfield(L, objidx, level - 1)) { /* try recursively */ + lua_remove(L, -2); /* remove table (but keep name) */ + lua_pushliteral(L, "."); + lua_insert(L, -2); /* place '.' between the two names */ + lua_concat(L, 3); + return 1; + } + } + lua_pop(L, 1); /* remove value */ + } + return 0; /* not found */ +} + + +/* +** Search for a name for a function in all loaded modules +** (registry._LOADED). +*/ +static int pushglobalfuncname (lua_State *L, lua_Debug *ar) { + int top = lua_gettop(L); + lua_getinfo(L, "f", ar); /* push function */ + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); + if (findfield(L, top + 1, 2)) { + const char *name = lua_tostring(L, -1); + if (strncmp(name, "_G.", 3) == 0) { /* name start with '_G.'? */ + lua_pushstring(L, name + 3); /* push name without prefix */ + lua_remove(L, -2); /* remove original name */ + } + lua_copy(L, -1, top + 1); /* move name to proper place */ + lua_pop(L, 2); /* remove pushed values */ + return 1; + } + else { + lua_settop(L, top); /* remove function and global table */ + return 0; + } +} + + +static void pushfuncname (lua_State *L, lua_Debug *ar) { + if (pushglobalfuncname(L, ar)) { /* try first a global name */ + lua_pushfstring(L, "function '%s'", lua_tostring(L, -1)); + lua_remove(L, -2); /* remove name */ + } + else if (*ar->namewhat != '\0') /* is there a name from code? */ + lua_pushfstring(L, "%s '%s'", ar->namewhat, ar->name); /* use it */ + else if (*ar->what == 'm') /* main? */ + lua_pushliteral(L, "main chunk"); + else if (*ar->what != 'C') /* for Lua functions, use */ + lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); + else /* nothing left... */ + lua_pushliteral(L, "?"); +} + + +static int lastlevel (lua_State *L) { + lua_Debug ar; + int li = 1, le = 1; + /* find an upper bound */ + while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } + /* do a binary search */ + while (li < le) { + int m = (li + le)/2; + if (lua_getstack(L, m, &ar)) li = m + 1; + else le = m; + } + return le - 1; +} + + +LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, + const char *msg, int level) { + lua_Debug ar; + int top = lua_gettop(L); + int last = lastlevel(L1); + int n1 = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1; + if (msg) + lua_pushfstring(L, "%s\n", msg); + luaL_checkstack(L, 10, NULL); + lua_pushliteral(L, "stack traceback:"); + while (lua_getstack(L1, level++, &ar)) { + if (n1-- == 0) { /* too many levels? */ + lua_pushliteral(L, "\n\t..."); /* add a '...' */ + level = last - LEVELS2 + 1; /* and skip to last ones */ + } + else { + lua_getinfo(L1, "Slnt", &ar); + lua_pushfstring(L, "\n\t%s:", ar.short_src); + if (ar.currentline > 0) + lua_pushfstring(L, "%d:", ar.currentline); + lua_pushliteral(L, " in "); + pushfuncname(L, &ar); + if (ar.istailcall) + lua_pushliteral(L, "\n\t(...tail calls...)"); + lua_concat(L, lua_gettop(L) - top); + } + } + lua_concat(L, lua_gettop(L) - top); +} + +/* }====================================================== */ /* @@ -39,37 +162,47 @@ ** ======================================================= */ - -LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { +LUALIB_API int luaL_argerror (lua_State *L, int arg, const char *extramsg) { lua_Debug ar; if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ - return luaL_error(L, "bad argument #%d (%s)", narg, extramsg); + return luaL_error(L, "bad argument #%d (%s)", arg, extramsg); lua_getinfo(L, "n", &ar); if (strcmp(ar.namewhat, "method") == 0) { - narg--; /* do not count `self' */ - if (narg == 0) /* error is in the self argument itself? */ - return luaL_error(L, "calling " LUA_QS " on bad self (%s)", + arg--; /* do not count 'self' */ + if (arg == 0) /* error is in the self argument itself? */ + return luaL_error(L, "calling '%s' on bad self (%s)", ar.name, extramsg); } if (ar.name == NULL) - ar.name = "?"; - return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", - narg, ar.name, extramsg); + ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?"; + return luaL_error(L, "bad argument #%d to '%s' (%s)", + arg, ar.name, extramsg); } -LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { - const char *msg = lua_pushfstring(L, "%s expected, got %s", - tname, luaL_typename(L, narg)); - return luaL_argerror(L, narg, msg); +static int typeerror (lua_State *L, int arg, const char *tname) { + const char *msg; + const char *typearg; /* name for the type of the actual argument */ + if (luaL_getmetafield(L, arg, "__name") == LUA_TSTRING) + typearg = lua_tostring(L, -1); /* use the given type name */ + else if (lua_type(L, arg) == LUA_TLIGHTUSERDATA) + typearg = "light userdata"; /* special name for messages */ + else + typearg = luaL_typename(L, arg); /* standard name */ + msg = lua_pushfstring(L, "%s expected, got %s", tname, typearg); + return luaL_argerror(L, arg, msg); } -static void tag_error (lua_State *L, int narg, int tag) { - luaL_typerror(L, narg, lua_typename(L, tag)); +static void tag_error (lua_State *L, int arg, int tag) { + typeerror(L, arg, lua_typename(L, tag)); } +/* +** The use of 'lua_pushfstring' ensures this function does not +** need reserved stack space when called. +*/ LUALIB_API void luaL_where (lua_State *L, int level) { lua_Debug ar; if (lua_getstack(L, level, &ar)) { /* check function at level */ @@ -79,10 +212,15 @@ LUALIB_API void luaL_where (lua_State *L, int level) { return; } } - lua_pushliteral(L, ""); /* else, no information available... */ + lua_pushfstring(L, ""); /* else, no information available... */ } +/* +** Again, the use of 'lua_pushvfstring' ensures this function does +** not need reserved stack space when called. (At worst, it generates +** an error with "stack overflow" instead of the given message.) +*/ LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { va_list argp; va_start(argp, fmt); @@ -93,293 +231,219 @@ LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { return lua_error(L); } -/* }====================================================== */ - - -LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, - const char *const lst[]) { - const char *name = (def) ? luaL_optstring(L, narg, def) : - luaL_checkstring(L, narg); - int i; - for (i=0; lst[i]; i++) - if (strcmp(lst[i], name) == 0) - return i; - return luaL_argerror(L, narg, - lua_pushfstring(L, "invalid option " LUA_QS, name)); -} - -LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { - lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */ - if (!lua_isnil(L, -1)) /* name already in use? */ - return 0; /* leave previous value on top, but return 0 */ - lua_pop(L, 1); - lua_newtable(L); /* create metatable */ - lua_pushvalue(L, -1); - lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ - return 1; -} - - -LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { - void *p = lua_touserdata(L, ud); - if (p != NULL) { /* value is a userdata? */ - if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ - lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ - if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ - lua_pop(L, 2); /* remove both metatables */ - return p; - } - } +LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { + int en = errno; /* calls to Lua API may change this value */ + if (stat) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushnil(L); + if (fname) + lua_pushfstring(L, "%s: %s", fname, strerror(en)); + else + lua_pushstring(L, strerror(en)); + lua_pushinteger(L, en); + return 3; } - luaL_typerror(L, ud, tname); /* else error */ - return NULL; /* to avoid warnings */ } -LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { - if (!lua_checkstack(L, space)) - luaL_error(L, "stack overflow (%s)", mes); -} - +#if !defined(l_inspectstat) /* { */ -LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { - if (lua_type(L, narg) != t) - tag_error(L, narg, t); -} +#if defined(LUA_USE_POSIX) +#include -LUALIB_API void luaL_checkany (lua_State *L, int narg) { - if (lua_type(L, narg) == LUA_TNONE) - luaL_argerror(L, narg, "value expected"); -} +/* +** use appropriate macros to interpret 'pclose' return status +*/ +#define l_inspectstat(stat,what) \ + if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \ + else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; } +#else -LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { - const char *s = lua_tolstring(L, narg, len); - if (!s) tag_error(L, narg, LUA_TSTRING); - return s; -} +#define l_inspectstat(stat,what) /* no op */ +#endif -LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, - const char *def, size_t *len) { - if (lua_isnoneornil(L, narg)) { - if (len) - *len = (def ? strlen(def) : 0); - return def; - } - else return luaL_checklstring(L, narg, len); -} +#endif /* } */ -LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { - lua_Number d = lua_tonumber(L, narg); - if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ - tag_error(L, narg, LUA_TNUMBER); - return d; +LUALIB_API int luaL_execresult (lua_State *L, int stat) { + const char *what = "exit"; /* type of termination */ + if (stat == -1) /* error? */ + return luaL_fileresult(L, 0, NULL); + else { + l_inspectstat(stat, what); /* interpret result */ + if (*what == 'e' && stat == 0) /* successful termination? */ + lua_pushboolean(L, 1); + else + lua_pushnil(L); + lua_pushstring(L, what); + lua_pushinteger(L, stat); + return 3; /* return true/nil,what,code */ + } } +/* }====================================================== */ -LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { - return luaL_opt(L, luaL_checknumber, narg, def); -} +/* +** {====================================================== +** Userdata's metatable manipulation +** ======================================================= +*/ -LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { - lua_Integer d = lua_tointeger(L, narg); - if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ - tag_error(L, narg, LUA_TNUMBER); - return d; +LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { + if (luaL_getmetatable(L, tname) != LUA_TNIL) /* name already in use? */ + return 0; /* leave previous value on top, but return 0 */ + lua_pop(L, 1); + lua_createtable(L, 0, 2); /* create metatable */ + lua_pushstring(L, tname); + lua_setfield(L, -2, "__name"); /* metatable.__name = tname */ + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ + return 1; } -LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, - lua_Integer def) { - return luaL_opt(L, luaL_checkinteger, narg, def); +LUALIB_API void luaL_setmetatable (lua_State *L, const char *tname) { + luaL_getmetatable(L, tname); + lua_setmetatable(L, -2); } -LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { - if (!lua_getmetatable(L, obj)) /* no metatable? */ - return 0; - lua_pushstring(L, event); - lua_rawget(L, -2); - if (lua_isnil(L, -1)) { - lua_pop(L, 2); /* remove metatable and metafield */ - return 0; - } - else { - lua_remove(L, -2); /* remove only metatable */ - return 1; +LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) { + void *p = lua_touserdata(L, ud); + if (p != NULL) { /* value is a userdata? */ + if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ + luaL_getmetatable(L, tname); /* get correct metatable */ + if (!lua_rawequal(L, -1, -2)) /* not the same? */ + p = NULL; /* value is a userdata with wrong metatable */ + lua_pop(L, 2); /* remove both metatables */ + return p; + } } + return NULL; /* value is not a userdata with a metatable */ } -LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { - obj = abs_index(L, obj); - if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ - return 0; - lua_pushvalue(L, obj); - lua_call(L, 1, 1); - return 1; +LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { + void *p = luaL_testudata(L, ud, tname); + if (p == NULL) typeerror(L, ud, tname); + return p; } +/* }====================================================== */ -LUALIB_API void (luaL_register) (lua_State *L, const char *libname, - const luaL_Reg *l) { - luaI_openlib(L, libname, l, 0); -} +/* +** {====================================================== +** Argument check functions +** ======================================================= +*/ -static int libsize (const luaL_Reg *l) { - int size = 0; - for (; l->name; l++) size++; - return size; +LUALIB_API int luaL_checkoption (lua_State *L, int arg, const char *def, + const char *const lst[]) { + const char *name = (def) ? luaL_optstring(L, arg, def) : + luaL_checkstring(L, arg); + int i; + for (i=0; lst[i]; i++) + if (strcmp(lst[i], name) == 0) + return i; + return luaL_argerror(L, arg, + lua_pushfstring(L, "invalid option '%s'", name)); } -LUALIB_API void luaI_openlib (lua_State *L, const char *libname, - const luaL_Reg *l, int nup) { - if (libname) { - int size = libsize(l); - /* check whether lib already exists */ - luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); - lua_getfield(L, -1, libname); /* get _LOADED[libname] */ - if (!lua_istable(L, -1)) { /* not found? */ - lua_pop(L, 1); /* remove previous result */ - /* try global variable (and create one if it does not exist) */ - if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL) - luaL_error(L, "name conflict for module " LUA_QS, libname); - lua_pushvalue(L, -1); - lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */ - } - lua_remove(L, -2); /* remove _LOADED table */ - lua_insert(L, -(nup+1)); /* move library table to below upvalues */ - } - for (; l->name; l++) { - int i; - for (i=0; ifunc, nup); - lua_setfield(L, -(nup+2), l->name); +/* +** Ensures the stack has at least 'space' extra slots, raising an error +** if it cannot fulfill the request. (The error handling needs a few +** extra slots to format the error message. In case of an error without +** this extra space, Lua will generate the same 'stack overflow' error, +** but without 'msg'.) +*/ +LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) { + if (!lua_checkstack(L, space)) { + if (msg) + luaL_error(L, "stack overflow (%s)", msg); + else + luaL_error(L, "stack overflow"); } - lua_pop(L, nup); /* remove upvalues */ } +LUALIB_API void luaL_checktype (lua_State *L, int arg, int t) { + if (lua_type(L, arg) != t) + tag_error(L, arg, t); +} -/* -** {====================================================== -** getn-setn: size for arrays -** ======================================================= -*/ - -#if defined(LUA_COMPAT_GETN) -static int checkint (lua_State *L, int topop) { - int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1; - lua_pop(L, topop); - return n; +LUALIB_API void luaL_checkany (lua_State *L, int arg) { + if (lua_type(L, arg) == LUA_TNONE) + luaL_argerror(L, arg, "value expected"); } -static void getsizes (lua_State *L) { - lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); - if (lua_isnil(L, -1)) { /* no `size' table? */ - lua_pop(L, 1); /* remove nil */ - lua_newtable(L); /* create it */ - lua_pushvalue(L, -1); /* `size' will be its own metatable */ - lua_setmetatable(L, -2); - lua_pushliteral(L, "kv"); - lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */ - lua_pushvalue(L, -1); - lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */ - } +LUALIB_API const char *luaL_checklstring (lua_State *L, int arg, size_t *len) { + const char *s = lua_tolstring(L, arg, len); + if (!s) tag_error(L, arg, LUA_TSTRING); + return s; } -LUALIB_API void luaL_setn (lua_State *L, int t, int n) { - t = abs_index(L, t); - lua_pushliteral(L, "n"); - lua_rawget(L, t); - if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */ - lua_pushliteral(L, "n"); /* use it */ - lua_pushinteger(L, n); - lua_rawset(L, t); - } - else { /* use `sizes' */ - getsizes(L); - lua_pushvalue(L, t); - lua_pushinteger(L, n); - lua_rawset(L, -3); /* sizes[t] = n */ - lua_pop(L, 1); /* remove `sizes' */ +LUALIB_API const char *luaL_optlstring (lua_State *L, int arg, + const char *def, size_t *len) { + if (lua_isnoneornil(L, arg)) { + if (len) + *len = (def ? strlen(def) : 0); + return def; } + else return luaL_checklstring(L, arg, len); } -LUALIB_API int luaL_getn (lua_State *L, int t) { - int n; - t = abs_index(L, t); - lua_pushliteral(L, "n"); /* try t.n */ - lua_rawget(L, t); - if ((n = checkint(L, 1)) >= 0) return n; - getsizes(L); /* else try sizes[t] */ - lua_pushvalue(L, t); - lua_rawget(L, -2); - if ((n = checkint(L, 2)) >= 0) return n; - return (int)lua_objlen(L, t); +LUALIB_API lua_Number luaL_checknumber (lua_State *L, int arg) { + int isnum; + lua_Number d = lua_tonumberx(L, arg, &isnum); + if (!isnum) + tag_error(L, arg, LUA_TNUMBER); + return d; } -#endif -/* }====================================================== */ +LUALIB_API lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number def) { + return luaL_opt(L, luaL_checknumber, arg, def); +} +static void interror (lua_State *L, int arg) { + if (lua_isnumber(L, arg)) + luaL_argerror(L, arg, "number has no integer representation"); + else + tag_error(L, arg, LUA_TNUMBER); +} -LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, - const char *r) { - const char *wild; - size_t l = strlen(p); - luaL_Buffer b; - luaL_buffinit(L, &b); - while ((wild = strstr(s, p)) != NULL) { - luaL_addlstring(&b, s, wild - s); /* push prefix */ - luaL_addstring(&b, r); /* push replacement in place of pattern */ - s = wild + l; /* continue after `p' */ + +LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int arg) { + int isnum; + lua_Integer d = lua_tointegerx(L, arg, &isnum); + if (!isnum) { + interror(L, arg); } - luaL_addstring(&b, s); /* push last suffix */ - luaL_pushresult(&b); - return lua_tostring(L, -1); + return d; } -LUALIB_API const char *luaL_findtable (lua_State *L, int idx, - const char *fname, int szhint) { - const char *e; - lua_pushvalue(L, idx); - do { - e = strchr(fname, '.'); - if (e == NULL) e = fname + strlen(fname); - lua_pushlstring(L, fname, e - fname); - lua_rawget(L, -2); - if (lua_isnil(L, -1)) { /* no such field? */ - lua_pop(L, 1); /* remove this nil */ - lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ - lua_pushlstring(L, fname, e - fname); - lua_pushvalue(L, -2); - lua_settable(L, -4); /* set new table into field */ - } - else if (!lua_istable(L, -1)) { /* field has a non-table value? */ - lua_pop(L, 2); /* remove table and value */ - return fname; /* return problematic part of the name */ - } - lua_remove(L, -2); /* remove previous table */ - fname = e + 1; - } while (*e == '.'); - return NULL; +LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int arg, + lua_Integer def) { + return luaL_opt(L, luaL_checkinteger, arg, def); } +/* }====================================================== */ /* @@ -388,54 +452,86 @@ LUALIB_API const char *luaL_findtable (lua_State *L, int idx, ** ======================================================= */ +/* userdata to box arbitrary data */ +typedef struct UBox { + void *box; + size_t bsize; +} UBox; + + +static void *resizebox (lua_State *L, int idx, size_t newsize) { + void *ud; + lua_Alloc allocf = lua_getallocf(L, &ud); + UBox *box = (UBox *)lua_touserdata(L, idx); + void *temp = allocf(ud, box->box, box->bsize, newsize); + if (temp == NULL && newsize > 0) { /* allocation error? */ + resizebox(L, idx, 0); /* free buffer */ + luaL_error(L, "not enough memory for buffer allocation"); + } + box->box = temp; + box->bsize = newsize; + return temp; +} -#define bufflen(B) ((B)->p - (B)->buffer) -#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) -#define LIMIT (LUA_MINSTACK/2) +static int boxgc (lua_State *L) { + resizebox(L, 1, 0); + return 0; +} -static int emptybuffer (luaL_Buffer *B) { - size_t l = bufflen(B); - if (l == 0) return 0; /* put nothing on stack */ - else { - lua_pushlstring(B->L, B->buffer, l); - B->p = B->buffer; - B->lvl++; - return 1; +static void *newbox (lua_State *L, size_t newsize) { + UBox *box = (UBox *)lua_newuserdata(L, sizeof(UBox)); + box->box = NULL; + box->bsize = 0; + if (luaL_newmetatable(L, "LUABOX")) { /* creating metatable? */ + lua_pushcfunction(L, boxgc); + lua_setfield(L, -2, "__gc"); /* metatable.__gc = boxgc */ } + lua_setmetatable(L, -2); + return resizebox(L, -1, newsize); } -static void adjuststack (luaL_Buffer *B) { - if (B->lvl > 1) { - lua_State *L = B->L; - int toget = 1; /* number of levels to concat */ - size_t toplen = lua_strlen(L, -1); - do { - size_t l = lua_strlen(L, -(toget+1)); - if (B->lvl - toget + 1 >= LIMIT || toplen > l) { - toplen += l; - toget++; - } - else break; - } while (toget < B->lvl); - lua_concat(L, toget); - B->lvl = B->lvl - toget + 1; - } -} +/* +** check whether buffer is using a userdata on the stack as a temporary +** buffer +*/ +#define buffonstack(B) ((B)->b != (B)->initb) -LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { - if (emptybuffer(B)) - adjuststack(B); - return B->buffer; +/* +** returns a pointer to a free area with at least 'sz' bytes +*/ +LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) { + lua_State *L = B->L; + if (B->size - B->n < sz) { /* not enough space? */ + char *newbuff; + size_t newsize = B->size * 2; /* double buffer size */ + if (newsize - B->n < sz) /* not big enough? */ + newsize = B->n + sz; + if (newsize < B->n || newsize - B->n < sz) + luaL_error(L, "buffer too large"); + /* create larger buffer */ + if (buffonstack(B)) + newbuff = (char *)resizebox(L, -1, newsize); + else { /* no buffer yet */ + newbuff = (char *)newbox(L, newsize); + memcpy(newbuff, B->b, B->n * sizeof(char)); /* copy original content */ + } + B->b = newbuff; + B->size = newsize; + } + return &B->b[B->n]; } LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { - while (l--) - luaL_addchar(B, *s++); + if (l > 0) { /* avoid 'memcpy' when 's' can be NULL */ + char *b = luaL_prepbuffsize(B, l); + memcpy(b, s, l * sizeof(char)); + luaL_addsize(B, l); + } } @@ -445,57 +541,74 @@ LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { LUALIB_API void luaL_pushresult (luaL_Buffer *B) { - emptybuffer(B); - lua_concat(B->L, B->lvl); - B->lvl = 1; + lua_State *L = B->L; + lua_pushlstring(L, B->b, B->n); + if (buffonstack(B)) { + resizebox(L, -2, 0); /* delete old buffer */ + lua_remove(L, -2); /* remove its header from the stack */ + } +} + + +LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) { + luaL_addsize(B, sz); + luaL_pushresult(B); } LUALIB_API void luaL_addvalue (luaL_Buffer *B) { lua_State *L = B->L; - size_t vl; - const char *s = lua_tolstring(L, -1, &vl); - if (vl <= bufffree(B)) { /* fit into buffer? */ - memcpy(B->p, s, vl); /* put it there */ - B->p += vl; - lua_pop(L, 1); /* remove from stack */ - } - else { - if (emptybuffer(B)) - lua_insert(L, -2); /* put buffer before new value */ - B->lvl++; /* add new value into B stack */ - adjuststack(B); - } + size_t l; + const char *s = lua_tolstring(L, -1, &l); + if (buffonstack(B)) + lua_insert(L, -2); /* put value below buffer */ + luaL_addlstring(B, s, l); + lua_remove(L, (buffonstack(B)) ? -2 : -1); /* remove value */ } LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { B->L = L; - B->p = B->buffer; - B->lvl = 0; + B->b = B->initb; + B->n = 0; + B->size = LUAL_BUFFERSIZE; +} + + +LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) { + luaL_buffinit(L, B); + return luaL_prepbuffsize(B, sz); } /* }====================================================== */ +/* +** {====================================================== +** Reference system +** ======================================================= +*/ + +/* index of free-list header */ +#define freelist 0 + + LUALIB_API int luaL_ref (lua_State *L, int t) { int ref; - t = abs_index(L, t); if (lua_isnil(L, -1)) { lua_pop(L, 1); /* remove from stack */ - return LUA_REFNIL; /* `nil' has a unique fixed reference */ + return LUA_REFNIL; /* 'nil' has a unique fixed reference */ } - lua_rawgeti(L, t, FREELIST_REF); /* get first free element */ - ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */ + t = lua_absindex(L, t); + lua_rawgeti(L, t, freelist); /* get first free element */ + ref = (int)lua_tointeger(L, -1); /* ref = t[freelist] */ lua_pop(L, 1); /* remove it from stack */ if (ref != 0) { /* any free element? */ lua_rawgeti(L, t, ref); /* remove it from list */ - lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */ - } - else { /* no free elements */ - ref = (int)lua_objlen(L, t); - ref++; /* create new reference */ + lua_rawseti(L, t, freelist); /* (t[freelist] = t[ref]) */ } + else /* no free elements */ + ref = (int)lua_rawlen(L, t) + 1; /* get a new reference */ lua_rawseti(L, t, ref); return ref; } @@ -503,14 +616,15 @@ LUALIB_API int luaL_ref (lua_State *L, int t) { LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { if (ref >= 0) { - t = abs_index(L, t); - lua_rawgeti(L, t, FREELIST_REF); - lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */ + t = lua_absindex(L, t); + lua_rawgeti(L, t, freelist); + lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */ lua_pushinteger(L, ref); - lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ + lua_rawseti(L, t, freelist); /* t[freelist] = ref */ } } +/* }====================================================== */ /* @@ -520,23 +634,27 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { */ typedef struct LoadF { - int extraline; - FILE *f; - char buff[LUAL_BUFFERSIZE]; + int n; /* number of pre-read characters */ + FILE *f; /* file being read */ + char buff[BUFSIZ]; /* area for reading file */ } LoadF; static const char *getF (lua_State *L, void *ud, size_t *size) { LoadF *lf = (LoadF *)ud; - (void)L; - if (lf->extraline) { - lf->extraline = 0; - *size = 1; - return "\n"; + (void)L; /* not used */ + if (lf->n > 0) { /* are there pre-read characters to be read? */ + *size = lf->n; /* return them (chars already in buffer) */ + lf->n = 0; /* no more pre-read characters */ } - if (feof(lf->f)) return NULL; - *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); - return (*size > 0) ? lf->buff : NULL; + else { /* read a block from file */ + /* 'fread' can return > 0 *and* set the EOF flag. If next call to + 'getF' called 'fread', it might still wait for user input. + The next check avoids this problem. */ + if (feof(lf->f)) return NULL; + *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */ + } + return lf->buff; } @@ -549,12 +667,46 @@ static int errfile (lua_State *L, const char *what, int fnameindex) { } -LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { +static int skipBOM (LoadF *lf) { + const char *p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */ + int c; + lf->n = 0; + do { + c = getc(lf->f); + if (c == EOF || c != *(const unsigned char *)p++) return c; + lf->buff[lf->n++] = c; /* to be read by the parser */ + } while (*p != '\0'); + lf->n = 0; /* prefix matched; discard it */ + return getc(lf->f); /* return next character */ +} + + +/* +** reads the first character of file 'f' and skips an optional BOM mark +** in its beginning plus its first line if it starts with '#'. Returns +** true if it skipped the first line. In any case, '*cp' has the +** first "valid" character of the file (after the optional BOM and +** a first-line comment). +*/ +static int skipcomment (LoadF *lf, int *cp) { + int c = *cp = skipBOM(lf); + if (c == '#') { /* first line is a comment (Unix exec. file)? */ + do { /* skip first line */ + c = getc(lf->f); + } while (c != EOF && c != '\n'); + *cp = getc(lf->f); /* skip end-of-line, if present */ + return 1; /* there was a comment */ + } + else return 0; /* no comment */ +} + + +LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, + const char *mode) { LoadF lf; int status, readstatus; int c; int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ - lf.extraline = 0; if (filename == NULL) { lua_pushliteral(L, "=stdin"); lf.f = stdin; @@ -564,25 +716,20 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { lf.f = fopen(filename, "r"); if (lf.f == NULL) return errfile(L, "open", fnameindex); } - c = getc(lf.f); - if (c == '#') { /* Unix exec. file? */ - lf.extraline = 1; - while ((c = getc(lf.f)) != EOF && c != '\n') ; /* skip first line */ - if (c == '\n') c = getc(lf.f); - } + if (skipcomment(&lf, &c)) /* read initial portion */ + lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ if (lf.f == NULL) return errfile(L, "reopen", fnameindex); - /* skip eventual `#!...' */ - while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ; - lf.extraline = 0; + skipcomment(&lf, &c); /* re-read initial portion */ } - ungetc(c, lf.f); - status = lua_load(L, getF, &lf, lua_tostring(L, -1)); + if (c != EOF) + lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ + status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode); readstatus = ferror(lf.f); if (filename) fclose(lf.f); /* close file (even in case of errors) */ if (readstatus) { - lua_settop(L, fnameindex); /* ignore results from `lua_load' */ + lua_settop(L, fnameindex); /* ignore results from 'lua_load' */ return errfile(L, "read", fnameindex); } lua_remove(L, fnameindex); @@ -598,7 +745,7 @@ typedef struct LoadS { static const char *getS (lua_State *L, void *ud, size_t *size) { LoadS *ls = (LoadS *)ud; - (void)L; + (void)L; /* not used */ if (ls->size == 0) return NULL; *size = ls->size; ls->size = 0; @@ -606,27 +753,252 @@ static const char *getS (lua_State *L, void *ud, size_t *size) { } -LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, - const char *name) { +LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size, + const char *name, const char *mode) { LoadS ls; ls.s = buff; ls.size = size; - return lua_load(L, getS, &ls, name); + return lua_load(L, getS, &ls, name, mode); } -LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) { +LUALIB_API int luaL_loadstring (lua_State *L, const char *s) { return luaL_loadbuffer(L, s, strlen(s), s); } +/* }====================================================== */ + + + +LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { + if (!lua_getmetatable(L, obj)) /* no metatable? */ + return LUA_TNIL; + else { + int tt; + lua_pushstring(L, event); + tt = lua_rawget(L, -2); + if (tt == LUA_TNIL) /* is metafield nil? */ + lua_pop(L, 2); /* remove metatable and metafield */ + else + lua_remove(L, -2); /* remove only metatable */ + return tt; /* return metafield type */ + } +} +LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { + obj = lua_absindex(L, obj); + if (luaL_getmetafield(L, obj, event) == LUA_TNIL) /* no metafield? */ + return 0; + lua_pushvalue(L, obj); + lua_call(L, 1, 1); + return 1; +} + + +LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) { + lua_Integer l; + int isnum; + lua_len(L, idx); + l = lua_tointegerx(L, -1, &isnum); + if (!isnum) + luaL_error(L, "object length is not an integer"); + lua_pop(L, 1); /* remove object */ + return l; +} + + +LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { + if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */ + switch (lua_type(L, idx)) { + case LUA_TNUMBER: { + if (lua_isinteger(L, idx)) + lua_pushfstring(L, "%I", lua_tointeger(L, idx)); + else + lua_pushfstring(L, "%f", lua_tonumber(L, idx)); + break; + } + case LUA_TSTRING: + lua_pushvalue(L, idx); + break; + case LUA_TBOOLEAN: + lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false")); + break; + case LUA_TNIL: + lua_pushliteral(L, "nil"); + break; + default: + lua_pushfstring(L, "%s: %p", luaL_typename(L, idx), + lua_topointer(L, idx)); + break; + } + } + return lua_tolstring(L, -1, len); +} + + +/* +** {====================================================== +** Compatibility with 5.1 module functions +** ======================================================= +*/ +#if defined(LUA_COMPAT_MODULE) + +static const char *luaL_findtable (lua_State *L, int idx, + const char *fname, int szhint) { + const char *e; + if (idx) lua_pushvalue(L, idx); + do { + e = strchr(fname, '.'); + if (e == NULL) e = fname + strlen(fname); + lua_pushlstring(L, fname, e - fname); + if (lua_rawget(L, -2) == LUA_TNIL) { /* no such field? */ + lua_pop(L, 1); /* remove this nil */ + lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ + lua_pushlstring(L, fname, e - fname); + lua_pushvalue(L, -2); + lua_settable(L, -4); /* set new table into field */ + } + else if (!lua_istable(L, -1)) { /* field has a non-table value? */ + lua_pop(L, 2); /* remove table and value */ + return fname; /* return problematic part of the name */ + } + lua_remove(L, -2); /* remove previous table */ + fname = e + 1; + } while (*e == '.'); + return NULL; +} + + +/* +** Count number of elements in a luaL_Reg list. +*/ +static int libsize (const luaL_Reg *l) { + int size = 0; + for (; l && l->name; l++) size++; + return size; +} + + +/* +** Find or create a module table with a given name. The function +** first looks at the _LOADED table and, if that fails, try a +** global variable with that name. In any case, leaves on the stack +** the module table. +*/ +LUALIB_API void luaL_pushmodule (lua_State *L, const char *modname, + int sizehint) { + luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); /* get _LOADED table */ + if (lua_getfield(L, -1, modname) != LUA_TTABLE) { /* no _LOADED[modname]? */ + lua_pop(L, 1); /* remove previous result */ + /* try global variable (and create one if it does not exist) */ + lua_pushglobaltable(L); + if (luaL_findtable(L, 0, modname, sizehint) != NULL) + luaL_error(L, "name conflict for module '%s'", modname); + lua_pushvalue(L, -1); + lua_setfield(L, -3, modname); /* _LOADED[modname] = new table */ + } + lua_remove(L, -2); /* remove _LOADED table */ +} + + +LUALIB_API void luaL_openlib (lua_State *L, const char *libname, + const luaL_Reg *l, int nup) { + luaL_checkversion(L); + if (libname) { + luaL_pushmodule(L, libname, libsize(l)); /* get/create library table */ + lua_insert(L, -(nup + 1)); /* move library table to below upvalues */ + } + if (l) + luaL_setfuncs(L, l, nup); + else + lua_pop(L, nup); /* remove upvalues */ +} + +#endif /* }====================================================== */ +/* +** set functions from list 'l' into table at top - 'nup'; each +** function gets the 'nup' elements at the top as upvalues. +** Returns with only the table at the stack. +*/ +LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { + luaL_checkstack(L, nup, "too many upvalues"); + for (; l->name != NULL; l++) { /* fill the table with given functions */ + int i; + for (i = 0; i < nup; i++) /* copy upvalues to the top */ + lua_pushvalue(L, -nup); + lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ + lua_setfield(L, -(nup + 2), l->name); + } + lua_pop(L, nup); /* remove upvalues */ +} + + +/* +** ensure that stack[idx][fname] has a table and push that table +** into the stack +*/ +LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) { + if (lua_getfield(L, idx, fname) == LUA_TTABLE) + return 1; /* table already there */ + else { + lua_pop(L, 1); /* remove previous result */ + idx = lua_absindex(L, idx); + lua_newtable(L); + lua_pushvalue(L, -1); /* copy to be left at top */ + lua_setfield(L, idx, fname); /* assign new table to field */ + return 0; /* false, because did not find table there */ + } +} + + +/* +** Stripped-down 'require': After checking "loaded" table, calls 'openf' +** to open a module, registers the result in 'package.loaded' table and, +** if 'glb' is true, also registers the result in the global table. +** Leaves resulting module on the top. +*/ +LUALIB_API void luaL_requiref (lua_State *L, const char *modname, + lua_CFunction openf, int glb) { + luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_getfield(L, -1, modname); /* _LOADED[modname] */ + if (!lua_toboolean(L, -1)) { /* package not already loaded? */ + lua_pop(L, 1); /* remove field */ + lua_pushcfunction(L, openf); + lua_pushstring(L, modname); /* argument to open function */ + lua_call(L, 1, 1); /* call 'openf' to open module */ + lua_pushvalue(L, -1); /* make copy of module (call result) */ + lua_setfield(L, -3, modname); /* _LOADED[modname] = module */ + } + lua_remove(L, -2); /* remove _LOADED table */ + if (glb) { + lua_pushvalue(L, -1); /* copy of module */ + lua_setglobal(L, modname); /* _G[modname] = module */ + } +} + + +LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, + const char *r) { + const char *wild; + size_t l = strlen(p); + luaL_Buffer b; + luaL_buffinit(L, &b); + while ((wild = strstr(s, p)) != NULL) { + luaL_addlstring(&b, s, wild - s); /* push prefix */ + luaL_addstring(&b, r); /* push replacement in place of pattern */ + s = wild + l; /* continue after 'p' */ + } + luaL_addstring(&b, s); /* push last suffix */ + luaL_pushresult(&b); + return lua_tostring(L, -1); +} + static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { - (void)ud; - (void)osize; + (void)ud; (void)osize; /* not used */ if (nsize == 0) { free(ptr); return NULL; @@ -637,10 +1009,9 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { static int panic (lua_State *L) { - (void)L; /* to avoid warnings */ - fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", - lua_tostring(L, -1)); - return 0; + lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n", + lua_tostring(L, -1)); + return 0; /* return to Lua to abort */ } @@ -650,3 +1021,15 @@ LUALIB_API lua_State *luaL_newstate (void) { return L; } + +LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) { + const lua_Number *v = lua_version(L); + if (sz != LUAL_NUMSIZES) /* check numeric types */ + luaL_error(L, "core and library have incompatible numeric types"); + if (v != lua_version(NULL)) + luaL_error(L, "multiple Lua VMs detected"); + else if (*v != ver) + luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", + ver, *v); +} + diff --git a/app/src/main/jni/lua/lauxlib.h b/app/src/main/jni/lua/lauxlib.h index 3425823..ddb7c22 100644 --- a/app/src/main/jni/lua/lauxlib.h +++ b/app/src/main/jni/lua/lauxlib.h @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lauxlib.h,v 1.129 2015/11/23 11:29:43 roberto Exp $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -15,20 +15,8 @@ #include "lua.h" -#if defined(LUA_COMPAT_GETN) -LUALIB_API int (luaL_getn) (lua_State *L, int t); -LUALIB_API void (luaL_setn) (lua_State *L, int t, int n); -#else -#define luaL_getn(L,i) ((int)lua_objlen(L, i)) -#define luaL_setn(L,i,j) ((void)0) /* no op! */ -#endif - -#if defined(LUA_COMPAT_OPENLIB) -#define luaI_openlib luaL_openlib -#endif - -/* extra error code for `luaL_load' */ +/* extra error code for 'luaL_load' */ #define LUA_ERRFILE (LUA_ERRERR+1) @@ -38,58 +26,77 @@ typedef struct luaL_Reg { } luaL_Reg; +#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number)) + +LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz); +#define luaL_checkversion(L) \ + luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES) -LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname, - const luaL_Reg *l, int nup); -LUALIB_API void (luaL_register) (lua_State *L, const char *libname, - const luaL_Reg *l); LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); -LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); -LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); -LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, +LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len); +LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg); +LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg, size_t *l); -LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, +LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg, const char *def, size_t *l); -LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); -LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); +LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int arg); +LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int arg, lua_Number def); -LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); -LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, +LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int arg); +LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg, lua_Integer def); LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); -LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); -LUALIB_API void (luaL_checkany) (lua_State *L, int narg); +LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t); +LUALIB_API void (luaL_checkany) (lua_State *L, int arg); LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); +LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname); +LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname); LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); LUALIB_API void (luaL_where) (lua_State *L, int lvl); LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); -LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, +LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def, const char *const lst[]); +LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname); +LUALIB_API int (luaL_execresult) (lua_State *L, int stat); + +/* predefined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) + LUALIB_API int (luaL_ref) (lua_State *L, int t); LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); -LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); -LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, - const char *name); +LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, + const char *mode); + +#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) + +LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, + const char *name, const char *mode); LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); LUALIB_API lua_State *(luaL_newstate) (void); +LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx); LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, const char *r); -LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, - const char *fname, int szhint); +LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); +LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname); +LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1, + const char *msg, int level); +LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, + lua_CFunction openf, int glb); /* ** =============================================================== @@ -97,14 +104,17 @@ LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, ** =============================================================== */ -#define luaL_argcheck(L, cond,numarg,extramsg) \ - ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) + +#define luaL_newlibtable(L,l) \ + lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) + +#define luaL_newlib(L,l) \ + (luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) + +#define luaL_argcheck(L, cond,arg,extramsg) \ + ((void)((cond) || luaL_argerror(L, (arg), (extramsg)))) #define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) #define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) -#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) -#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) -#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) -#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) #define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) @@ -118,56 +128,128 @@ LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, #define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) +#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) + + /* ** {====================================================== ** Generic Buffer manipulation ** ======================================================= */ - - typedef struct luaL_Buffer { - char *p; /* current position in buffer */ - int lvl; /* number of strings in the stack (level) */ + char *b; /* buffer address */ + size_t size; /* buffer size */ + size_t n; /* number of characters in buffer */ lua_State *L; - char buffer[LUAL_BUFFERSIZE]; + char initb[LUAL_BUFFERSIZE]; /* initial buffer */ } luaL_Buffer; -#define luaL_addchar(B,c) \ - ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ - (*(B)->p++ = (char)(c))) -/* compatibility only */ -#define luaL_putchar(B,c) luaL_addchar(B,c) +#define luaL_addchar(B,c) \ + ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \ + ((B)->b[(B)->n++] = (c))) -#define luaL_addsize(B,n) ((B)->p += (n)) +#define luaL_addsize(B,s) ((B)->n += (s)) LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); -LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); +LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz); +LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); +#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) /* }====================================================== */ -/* compatibility with ref system */ -/* pre-defined references */ -#define LUA_NOREF (-2) -#define LUA_REFNIL (-1) +/* +** {====================================================== +** File handles for IO library +** ======================================================= +*/ + +/* +** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and +** initial structure 'luaL_Stream' (it may contain other fields +** after that initial structure). +*/ -#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \ - (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0)) +#define LUA_FILEHANDLE "FILE*" -#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref)) -#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) +typedef struct luaL_Stream { + FILE *f; /* stream (NULL for incompletely created streams) */ + lua_CFunction closef; /* to close stream (NULL for closed streams) */ +} luaL_Stream; + +/* }====================================================== */ + + + +/* compatibility with old module system */ +#if defined(LUA_COMPAT_MODULE) + +LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname, + int sizehint); +LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname, + const luaL_Reg *l, int nup); + +#define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0)) + +#endif + + +/* +** {================================================================== +** "Abstraction Layer" for basic report of messages and errors +** =================================================================== +*/ + +/* print a string */ +#if !defined(lua_writestring) +#define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) +#endif + +/* print a newline and flush the output */ +#if !defined(lua_writeline) +#define lua_writeline() (lua_writestring("\n", 1), fflush(stdout)) +#endif + +/* print an error message */ +#if !defined(lua_writestringerror) +#define lua_writestringerror(s,p) \ + (fprintf(stderr, (s), (p)), fflush(stderr)) +#endif + +/* }================================================================== */ + + +/* +** {============================================================ +** Compatibility with deprecated conversions +** ============================================================= +*/ +#if defined(LUA_COMPAT_APIINTCASTS) + +#define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a)) +#define luaL_optunsigned(L,a,d) \ + ((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d))) + +#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) +#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) + +#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) +#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) + +#endif +/* }============================================================ */ -#define luaL_reg luaL_Reg #endif diff --git a/app/src/main/jni/lua/lbaselib.c b/app/src/main/jni/lua/lbaselib.c index 2ab550b..d481c4e 100644 --- a/app/src/main/jni/lua/lbaselib.c +++ b/app/src/main/jni/lua/lbaselib.c @@ -1,9 +1,13 @@ /* -** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $ +** $Id: lbaselib.c,v 1.313 2016/04/11 19:18:40 roberto Exp $ ** Basic library ** See Copyright Notice in lua.h */ +#define lbaselib_c +#define LUA_LIB + +#include "lprefix.h" #include @@ -11,78 +15,95 @@ #include #include -#define lbaselib_c -#define LUA_LIB - #include "lua.h" #include "lauxlib.h" #include "lualib.h" - - -/* -** If your system does not support `stdout', you can just remove this function. -** If you need, you can define your own `print' function, following this -** model but changing `fputs' to put the strings at a proper place -** (a console window or a log file, for instance). -*/ static int luaB_print (lua_State *L) { int n = lua_gettop(L); /* number of arguments */ int i; lua_getglobal(L, "tostring"); for (i=1; i<=n; i++) { const char *s; + size_t l; lua_pushvalue(L, -1); /* function to be called */ lua_pushvalue(L, i); /* value to print */ lua_call(L, 1, 1); - s = lua_tostring(L, -1); /* get result */ + s = lua_tolstring(L, -1, &l); /* get result */ if (s == NULL) - return luaL_error(L, LUA_QL("tostring") " must return a string to " - LUA_QL("print")); - if (i>1) fputs("\t", stdout); - fputs(s, stdout); + return luaL_error(L, "'tostring' must return a string to 'print'"); + if (i>1) lua_writestring("\t", 1); + lua_writestring(s, l); lua_pop(L, 1); /* pop result */ } - fputs("\n", stdout); + lua_writeline(); return 0; } +#define SPACECHARS " \f\n\r\t\v" + +static const char *b_str2int (const char *s, int base, lua_Integer *pn) { + lua_Unsigned n = 0; + int neg = 0; + s += strspn(s, SPACECHARS); /* skip initial spaces */ + if (*s == '-') { s++; neg = 1; } /* handle signal */ + else if (*s == '+') s++; + if (!isalnum((unsigned char)*s)) /* no digit? */ + return NULL; + do { + int digit = (isdigit((unsigned char)*s)) ? *s - '0' + : (toupper((unsigned char)*s) - 'A') + 10; + if (digit >= base) return NULL; /* invalid numeral */ + n = n * base + digit; + s++; + } while (isalnum((unsigned char)*s)); + s += strspn(s, SPACECHARS); /* skip trailing spaces */ + *pn = (lua_Integer)((neg) ? (0u - n) : n); + return s; +} + + static int luaB_tonumber (lua_State *L) { - int base = luaL_optint(L, 2, 10); - if (base == 10) { /* standard conversion */ + if (lua_isnoneornil(L, 2)) { /* standard conversion? */ luaL_checkany(L, 1); - if (lua_isnumber(L, 1)) { - lua_pushnumber(L, lua_tonumber(L, 1)); + if (lua_type(L, 1) == LUA_TNUMBER) { /* already a number? */ + lua_settop(L, 1); /* yes; return it */ return 1; } + else { + size_t l; + const char *s = lua_tolstring(L, 1, &l); + if (s != NULL && lua_stringtonumber(L, s) == l + 1) + return 1; /* successful conversion to number */ + /* else not a number */ + } } else { - const char *s1 = luaL_checkstring(L, 1); - char *s2; - unsigned long n; + size_t l; + const char *s; + lua_Integer n = 0; /* to avoid warnings */ + lua_Integer base = luaL_checkinteger(L, 2); + luaL_checktype(L, 1, LUA_TSTRING); /* no numbers as strings */ + s = lua_tolstring(L, 1, &l); luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); - n = strtoul(s1, &s2, base); - if (s1 != s2) { /* at least one valid digit? */ - while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ - if (*s2 == '\0') { /* no invalid trailing characters? */ - lua_pushnumber(L, (lua_Number)n); - return 1; - } - } - } - lua_pushnil(L); /* else not a number */ + if (b_str2int(s, (int)base, &n) == s + l) { + lua_pushinteger(L, n); + return 1; + } /* else not a number */ + } /* else not a number */ + lua_pushnil(L); /* not a number */ return 1; } static int luaB_error (lua_State *L) { - int level = luaL_optint(L, 2, 1); + int level = (int)luaL_optinteger(L, 2, 1); lua_settop(L, 1); - if (lua_isstring(L, 1) && level > 0) { /* add extra information? */ - luaL_where(L, level); + if (lua_type(L, 1) == LUA_TSTRING && level > 0) { + luaL_where(L, level); /* add extra information */ lua_pushvalue(L, 1); lua_concat(L, 2); } @@ -106,58 +127,14 @@ static int luaB_setmetatable (lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table expected"); - if (luaL_getmetafield(L, 1, "__metatable")) - luaL_error(L, "cannot change a protected metatable"); + if (luaL_getmetafield(L, 1, "__metatable") != LUA_TNIL) + return luaL_error(L, "cannot change a protected metatable"); lua_settop(L, 2); lua_setmetatable(L, 1); return 1; } -static void getfunc (lua_State *L, int opt) { - if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); - else { - lua_Debug ar; - int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1); - luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); - if (lua_getstack(L, level, &ar) == 0) - luaL_argerror(L, 1, "invalid level"); - lua_getinfo(L, "f", &ar); - if (lua_isnil(L, -1)) - luaL_error(L, "no function environment for tail call at level %d", - level); - } -} - - -static int luaB_getfenv (lua_State *L) { - getfunc(L, 1); - if (lua_iscfunction(L, -1)) /* is a C function? */ - lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */ - else - lua_getfenv(L, -1); - return 1; -} - - -static int luaB_setfenv (lua_State *L) { - luaL_checktype(L, 2, LUA_TTABLE); - getfunc(L, 0); - lua_pushvalue(L, 2); - if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) { - /* change environment of current thread */ - lua_pushthread(L); - lua_insert(L, -2); - lua_setfenv(L, -2); - return 0; - } - else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0) - luaL_error(L, - LUA_QL("setfenv") " cannot change environment of given object"); - return 1; -} - - static int luaB_rawequal (lua_State *L) { luaL_checkany(L, 1); luaL_checkany(L, 2); @@ -166,6 +143,15 @@ static int luaB_rawequal (lua_State *L) { } +static int luaB_rawlen (lua_State *L) { + int t = lua_type(L, 1); + luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1, + "table or string expected"); + lua_pushinteger(L, lua_rawlen(L, 1)); + return 1; +} + + static int luaB_rawget (lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); luaL_checkany(L, 2); @@ -184,32 +170,28 @@ static int luaB_rawset (lua_State *L) { } -static int luaB_gcinfo (lua_State *L) { - lua_pushinteger(L, lua_getgccount(L)); - return 1; -} - - static int luaB_collectgarbage (lua_State *L) { static const char *const opts[] = {"stop", "restart", "collect", - "count", "step", "setpause", "setstepmul", NULL}; + "count", "step", "setpause", "setstepmul", + "isrunning", NULL}; static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, - LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL}; - int o = luaL_checkoption(L, 1, "collect", opts); - int ex = luaL_optint(L, 2, 0); - int res = lua_gc(L, optsnum[o], ex); - switch (optsnum[o]) { + LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, + LUA_GCISRUNNING}; + int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; + int ex = (int)luaL_optinteger(L, 2, 0); + int res = lua_gc(L, o, ex); + switch (o) { case LUA_GCCOUNT: { int b = lua_gc(L, LUA_GCCOUNTB, 0); - lua_pushnumber(L, res + ((lua_Number)b/1024)); + lua_pushnumber(L, (lua_Number)res + ((lua_Number)b/1024)); return 1; } - case LUA_GCSTEP: { + case LUA_GCSTEP: case LUA_GCISRUNNING: { lua_pushboolean(L, res); return 1; } default: { - lua_pushnumber(L, res); + lua_pushinteger(L, res); return 1; } } @@ -217,12 +199,30 @@ static int luaB_collectgarbage (lua_State *L) { static int luaB_type (lua_State *L) { - luaL_checkany(L, 1); - lua_pushstring(L, luaL_typename(L, 1)); + int t = lua_type(L, 1); + luaL_argcheck(L, t != LUA_TNONE, 1, "value expected"); + lua_pushstring(L, lua_typename(L, t)); return 1; } +static int pairsmeta (lua_State *L, const char *method, int iszero, + lua_CFunction iter) { + if (luaL_getmetafield(L, 1, method) == LUA_TNIL) { /* no metamethod? */ + luaL_checktype(L, 1, LUA_TTABLE); /* argument must be a table */ + lua_pushcfunction(L, iter); /* will return generator, */ + lua_pushvalue(L, 1); /* state, */ + if (iszero) lua_pushinteger(L, 0); /* and initial value */ + else lua_pushnil(L); + } + else { + lua_pushvalue(L, 1); /* argument 'self' to metamethod */ + lua_call(L, 1, 3); /* get 3 values from metamethod */ + } + return 3; +} + + static int luaB_next (lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); lua_settop(L, 2); /* create a 2nd argument if there isn't one */ @@ -236,37 +236,47 @@ static int luaB_next (lua_State *L) { static int luaB_pairs (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ - lua_pushvalue(L, 1); /* state, */ - lua_pushnil(L); /* and initial value */ - return 3; + return pairsmeta(L, "__pairs", 0, luaB_next); } +/* +** Traversal function for 'ipairs' +*/ static int ipairsaux (lua_State *L) { - int i = luaL_checkint(L, 2); - luaL_checktype(L, 1, LUA_TTABLE); - i++; /* next value */ + lua_Integer i = luaL_checkinteger(L, 2) + 1; lua_pushinteger(L, i); - lua_rawgeti(L, 1, i); - return (lua_isnil(L, -1)) ? 0 : 2; + return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2; } +/* +** 'ipairs' function. Returns 'ipairsaux', given "table", 0. +** (The given "table" may not be a table.) +*/ static int luaB_ipairs (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ - lua_pushvalue(L, 1); /* state, */ - lua_pushinteger(L, 0); /* and initial value */ +#if defined(LUA_COMPAT_IPAIRS) + return pairsmeta(L, "__ipairs", 1, ipairsaux); +#else + luaL_checkany(L, 1); + lua_pushcfunction(L, ipairsaux); /* iteration function */ + lua_pushvalue(L, 1); /* state */ + lua_pushinteger(L, 0); /* initial value */ return 3; +#endif } -static int load_aux (lua_State *L, int status) { - if (status == 0) /* OK? */ +static int load_aux (lua_State *L, int status, int envidx) { + if (status == LUA_OK) { + if (envidx != 0) { /* 'env' parameter? */ + lua_pushvalue(L, envidx); /* environment for loaded function */ + if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */ + lua_pop(L, 1); /* remove 'env' if not used by previous call */ + } return 1; - else { + } + else { /* error (message is on top of the stack) */ lua_pushnil(L); lua_insert(L, -2); /* put before error message */ return 2; /* return nil plus error message */ @@ -274,84 +284,101 @@ static int load_aux (lua_State *L, int status) { } -static int luaB_loadstring (lua_State *L) { - size_t l; - const char *s = luaL_checklstring(L, 1, &l); - const char *chunkname = luaL_optstring(L, 2, s); - return load_aux(L, luaL_loadbuffer(L, s, l, chunkname)); -} - - static int luaB_loadfile (lua_State *L) { const char *fname = luaL_optstring(L, 1, NULL); - return load_aux(L, luaL_loadfile(L, fname)); + const char *mode = luaL_optstring(L, 2, NULL); + int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */ + int status = luaL_loadfilex(L, fname, mode); + return load_aux(L, status, env); } /* -** Reader for generic `load' function: `lua_load' uses the +** {====================================================== +** Generic Read function +** ======================================================= +*/ + + +/* +** reserved slot, above all arguments, to hold a copy of the returned +** string to avoid it being collected while parsed. 'load' has four +** optional arguments (chunk, source name, mode, and environment). +*/ +#define RESERVEDSLOT 5 + + +/* +** Reader for generic 'load' function: 'lua_load' uses the ** stack for internal stuff, so the reader cannot change the ** stack top. Instead, it keeps its resulting string in a ** reserved slot inside the stack. */ static const char *generic_reader (lua_State *L, void *ud, size_t *size) { - (void)ud; /* to avoid warnings */ + (void)(ud); /* not used */ luaL_checkstack(L, 2, "too many nested functions"); lua_pushvalue(L, 1); /* get function */ lua_call(L, 0, 1); /* call it */ if (lua_isnil(L, -1)) { + lua_pop(L, 1); /* pop result */ *size = 0; return NULL; } - else if (lua_isstring(L, -1)) { - lua_replace(L, 3); /* save string in a reserved stack slot */ - return lua_tolstring(L, 3, size); - } - else luaL_error(L, "reader function must return a string"); - return NULL; /* to avoid warnings */ + else if (!lua_isstring(L, -1)) + luaL_error(L, "reader function must return a string"); + lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ + return lua_tolstring(L, RESERVEDSLOT, size); } static int luaB_load (lua_State *L) { int status; - const char *cname = luaL_optstring(L, 2, "=(load)"); - luaL_checktype(L, 1, LUA_TFUNCTION); - lua_settop(L, 3); /* function, eventual name, plus one reserved slot */ - status = lua_load(L, generic_reader, NULL, cname); - return load_aux(L, status); + size_t l; + const char *s = lua_tolstring(L, 1, &l); + const char *mode = luaL_optstring(L, 3, "bt"); + int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */ + if (s != NULL) { /* loading a string? */ + const char *chunkname = luaL_optstring(L, 2, s); + status = luaL_loadbufferx(L, s, l, chunkname, mode); + } + else { /* loading from a reader function */ + const char *chunkname = luaL_optstring(L, 2, "=(load)"); + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_settop(L, RESERVEDSLOT); /* create reserved slot */ + status = lua_load(L, generic_reader, NULL, chunkname, mode); + } + return load_aux(L, status, env); } +/* }====================================================== */ -static int luaB_dofile (lua_State *L) { - const char *fname = luaL_optstring(L, 1, NULL); - int n = lua_gettop(L); - if (luaL_loadfile(L, fname) != 0) lua_error(L); - lua_call(L, 0, LUA_MULTRET); - return lua_gettop(L) - n; + +static int dofilecont (lua_State *L, int d1, lua_KContext d2) { + (void)d1; (void)d2; /* only to match 'lua_Kfunction' prototype */ + return lua_gettop(L) - 1; } -static int luaB_assert (lua_State *L) { - luaL_checkany(L, 1); - if (!lua_toboolean(L, 1)) - return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); - return lua_gettop(L); +static int luaB_dofile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + lua_settop(L, 1); + if (luaL_loadfile(L, fname) != LUA_OK) + return lua_error(L); + lua_callk(L, 0, LUA_MULTRET, 0, dofilecont); + return dofilecont(L, 0, 0); } -static int luaB_unpack (lua_State *L) { - int i, e, n; - luaL_checktype(L, 1, LUA_TTABLE); - i = luaL_optint(L, 2, 1); - e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1)); - if (i > e) return 0; /* empty range */ - n = e - i + 1; /* number of elements */ - if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ - return luaL_error(L, "too many results to unpack"); - lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ - while (i++ < e) /* push arg[i + 1...e] */ - lua_rawgeti(L, 1, i); - return n; +static int luaB_assert (lua_State *L) { + if (lua_toboolean(L, 1)) /* condition is true? */ + return lua_gettop(L); /* return all arguments */ + else { /* error */ + luaL_checkany(L, 1); /* there must be a condition */ + lua_remove(L, 1); /* remove it */ + lua_pushliteral(L, "assertion failed!"); /* default message */ + lua_settop(L, 1); /* leave only message (default if no other one) */ + return luaB_error(L); /* call 'error' */ + } } @@ -362,84 +389,63 @@ static int luaB_select (lua_State *L) { return 1; } else { - int i = luaL_checkint(L, 1); + lua_Integer i = luaL_checkinteger(L, 1); if (i < 0) i = n + i; else if (i > n) i = n; luaL_argcheck(L, 1 <= i, 1, "index out of range"); - return n - i; + return n - (int)i; + } +} + + +/* +** Continuation function for 'pcall' and 'xpcall'. Both functions +** already pushed a 'true' before doing the call, so in case of success +** 'finishpcall' only has to return everything in the stack minus +** 'extra' values (where 'extra' is exactly the number of items to be +** ignored). +*/ +static int finishpcall (lua_State *L, int status, lua_KContext extra) { + if (status != LUA_OK && status != LUA_YIELD) { /* error? */ + lua_pushboolean(L, 0); /* first result (false) */ + lua_pushvalue(L, -2); /* error message */ + return 2; /* return false, msg */ } + else + return lua_gettop(L) - (int)extra; /* return all results */ } static int luaB_pcall (lua_State *L) { int status; luaL_checkany(L, 1); - status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); - lua_pushboolean(L, (status == 0)); - lua_insert(L, 1); - return lua_gettop(L); /* return status + all results */ + lua_pushboolean(L, 1); /* first result if no errors */ + lua_insert(L, 1); /* put it in place */ + status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, finishpcall); + return finishpcall(L, status, 0); } +/* +** Do a protected call with error handling. After 'lua_rotate', the +** stack will have ; so, the function passes +** 2 to 'finishpcall' to skip the 2 first values when returning results. +*/ static int luaB_xpcall (lua_State *L) { int status; - luaL_checkany(L, 2); - lua_settop(L, 2); - lua_insert(L, 1); /* put error function under function to be called */ - status = lua_pcall(L, 0, LUA_MULTRET, 1); - lua_pushboolean(L, (status == 0)); - lua_replace(L, 1); - return lua_gettop(L); /* return status + all results */ + int n = lua_gettop(L); + luaL_checktype(L, 2, LUA_TFUNCTION); /* check error function */ + lua_pushboolean(L, 1); /* first result */ + lua_pushvalue(L, 1); /* function */ + lua_rotate(L, 3, 2); /* move them below function's arguments */ + status = lua_pcallk(L, n - 2, LUA_MULTRET, 2, 2, finishpcall); + return finishpcall(L, status, 2); } static int luaB_tostring (lua_State *L) { luaL_checkany(L, 1); - if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ - return 1; /* use its value */ - switch (lua_type(L, 1)) { - case LUA_TNUMBER: - lua_pushstring(L, lua_tostring(L, 1)); - break; - case LUA_TSTRING: - lua_pushvalue(L, 1); - break; - case LUA_TBOOLEAN: - lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); - break; - case LUA_TNIL: - lua_pushliteral(L, "nil"); - break; - default: - lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1)); - break; - } - return 1; -} - - -static int luaB_newproxy (lua_State *L) { - lua_settop(L, 1); - lua_newuserdata(L, 0); /* create proxy */ - if (lua_toboolean(L, 1) == 0) - return 1; /* no metatable */ - else if (lua_isboolean(L, 1)) { - lua_newtable(L); /* create a new metatable `m' ... */ - lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */ - lua_pushboolean(L, 1); - lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */ - } - else { - int validproxy = 0; /* to check if weaktable[metatable(u)] == true */ - if (lua_getmetatable(L, 1)) { - lua_rawget(L, lua_upvalueindex(1)); - validproxy = lua_toboolean(L, -1); - lua_pop(L, 1); /* remove value */ - } - luaL_argcheck(L, validproxy, 1, "boolean or proxy expected"); - lua_getmetatable(L, 1); /* metatable is valid; get it */ - } - lua_setmetatable(L, 2); + luaL_tolstring(L, 1, NULL); return 1; } @@ -449,205 +455,44 @@ static const luaL_Reg base_funcs[] = { {"collectgarbage", luaB_collectgarbage}, {"dofile", luaB_dofile}, {"error", luaB_error}, - {"gcinfo", luaB_gcinfo}, - {"getfenv", luaB_getfenv}, {"getmetatable", luaB_getmetatable}, + {"ipairs", luaB_ipairs}, {"loadfile", luaB_loadfile}, {"load", luaB_load}, - {"loadstring", luaB_loadstring}, +#if defined(LUA_COMPAT_LOADSTRING) + {"loadstring", luaB_load}, +#endif {"next", luaB_next}, + {"pairs", luaB_pairs}, {"pcall", luaB_pcall}, {"print", luaB_print}, {"rawequal", luaB_rawequal}, + {"rawlen", luaB_rawlen}, {"rawget", luaB_rawget}, {"rawset", luaB_rawset}, {"select", luaB_select}, - {"setfenv", luaB_setfenv}, {"setmetatable", luaB_setmetatable}, {"tonumber", luaB_tonumber}, {"tostring", luaB_tostring}, {"type", luaB_type}, - {"unpack", luaB_unpack}, {"xpcall", luaB_xpcall}, + /* placeholders */ + {"_G", NULL}, + {"_VERSION", NULL}, {NULL, NULL} }; -/* -** {====================================================== -** Coroutine library -** ======================================================= -*/ - -#define CO_RUN 0 /* running */ -#define CO_SUS 1 /* suspended */ -#define CO_NOR 2 /* 'normal' (it resumed another coroutine) */ -#define CO_DEAD 3 - -static const char *const statnames[] = - {"running", "suspended", "normal", "dead"}; - -static int costatus (lua_State *L, lua_State *co) { - if (L == co) return CO_RUN; - switch (lua_status(co)) { - case LUA_YIELD: - return CO_SUS; - case 0: { - lua_Debug ar; - if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ - return CO_NOR; /* it is running */ - else if (lua_gettop(co) == 0) - return CO_DEAD; - else - return CO_SUS; /* initial state */ - } - default: /* some error occured */ - return CO_DEAD; - } -} - - -static int luaB_costatus (lua_State *L) { - lua_State *co = lua_tothread(L, 1); - luaL_argcheck(L, co, 1, "coroutine expected"); - lua_pushstring(L, statnames[costatus(L, co)]); - return 1; -} - - -static int auxresume (lua_State *L, lua_State *co, int narg) { - int status = costatus(L, co); - if (!lua_checkstack(co, narg)) - luaL_error(L, "too many arguments to resume"); - if (status != CO_SUS) { - lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]); - return -1; /* error flag */ - } - lua_xmove(L, co, narg); - lua_setlevel(L, co); - status = lua_resume(co, narg); - if (status == 0 || status == LUA_YIELD) { - int nres = lua_gettop(co); - if (!lua_checkstack(L, nres + 1)) - luaL_error(L, "too many results to resume"); - lua_xmove(co, L, nres); /* move yielded values */ - return nres; - } - else { - lua_xmove(co, L, 1); /* move error message */ - return -1; /* error flag */ - } -} - - -static int luaB_coresume (lua_State *L) { - lua_State *co = lua_tothread(L, 1); - int r; - luaL_argcheck(L, co, 1, "coroutine expected"); - r = auxresume(L, co, lua_gettop(L) - 1); - if (r < 0) { - lua_pushboolean(L, 0); - lua_insert(L, -2); - return 2; /* return false + error message */ - } - else { - lua_pushboolean(L, 1); - lua_insert(L, -(r + 1)); - return r + 1; /* return true + `resume' returns */ - } -} - - -static int luaB_auxwrap (lua_State *L) { - lua_State *co = lua_tothread(L, lua_upvalueindex(1)); - int r = auxresume(L, co, lua_gettop(L)); - if (r < 0) { - if (lua_isstring(L, -1)) { /* error object is a string? */ - luaL_where(L, 1); /* add extra info */ - lua_insert(L, -2); - lua_concat(L, 2); - } - lua_error(L); /* propagate error */ - } - return r; -} - - -static int luaB_cocreate (lua_State *L) { - lua_State *NL = lua_newthread(L); - luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, - "Lua function expected"); - lua_pushvalue(L, 1); /* move function to top */ - lua_xmove(L, NL, 1); /* move function from L to NL */ - return 1; -} - - -static int luaB_cowrap (lua_State *L) { - luaB_cocreate(L); - lua_pushcclosure(L, luaB_auxwrap, 1); - return 1; -} - - -static int luaB_yield (lua_State *L) { - return lua_yield(L, lua_gettop(L)); -} - - -static int luaB_corunning (lua_State *L) { - if (lua_pushthread(L)) - lua_pushnil(L); /* main thread is not a coroutine */ - return 1; -} - - -static const luaL_Reg co_funcs[] = { - {"create", luaB_cocreate}, - {"resume", luaB_coresume}, - {"running", luaB_corunning}, - {"status", luaB_costatus}, - {"wrap", luaB_cowrap}, - {"yield", luaB_yield}, - {NULL, NULL} -}; - -/* }====================================================== */ - - -static void auxopen (lua_State *L, const char *name, - lua_CFunction f, lua_CFunction u) { - lua_pushcfunction(L, u); - lua_pushcclosure(L, f, 1); - lua_setfield(L, -2, name); -} - - -static void base_open (lua_State *L) { - /* set global _G */ - lua_pushvalue(L, LUA_GLOBALSINDEX); - lua_setglobal(L, "_G"); +LUAMOD_API int luaopen_base (lua_State *L) { /* open lib into global table */ - luaL_register(L, "_G", base_funcs); + lua_pushglobaltable(L); + luaL_setfuncs(L, base_funcs, 0); + /* set global _G */ + lua_pushvalue(L, -1); + lua_setfield(L, -2, "_G"); + /* set global _VERSION */ lua_pushliteral(L, LUA_VERSION); - lua_setglobal(L, "_VERSION"); /* set global _VERSION */ - /* `ipairs' and `pairs' need auxiliary functions as upvalues */ - auxopen(L, "ipairs", luaB_ipairs, ipairsaux); - auxopen(L, "pairs", luaB_pairs, luaB_next); - /* `newproxy' needs a weaktable as upvalue */ - lua_createtable(L, 0, 1); /* new table `w' */ - lua_pushvalue(L, -1); /* `w' will be its own metatable */ - lua_setmetatable(L, -2); - lua_pushliteral(L, "kv"); - lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */ - lua_pushcclosure(L, luaB_newproxy, 1); - lua_setglobal(L, "newproxy"); /* set global `newproxy' */ -} - - -LUALIB_API int luaopen_base (lua_State *L) { - base_open(L); - luaL_register(L, LUA_COLIBNAME, co_funcs); - return 2; + lua_setfield(L, -2, "_VERSION"); + return 1; } diff --git a/app/src/main/jni/lua/lbitlib.c b/app/src/main/jni/lua/lbitlib.c new file mode 100644 index 0000000..1cb1d5b --- /dev/null +++ b/app/src/main/jni/lua/lbitlib.c @@ -0,0 +1,233 @@ +/* +** $Id: lbitlib.c,v 1.30 2015/11/11 19:08:09 roberto Exp $ +** Standard library for bitwise operations +** See Copyright Notice in lua.h +*/ + +#define lbitlib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#if defined(LUA_COMPAT_BITLIB) /* { */ + + +#define pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n)) +#define checkunsigned(L,i) ((lua_Unsigned)luaL_checkinteger(L,i)) + + +/* number of bits to consider in a number */ +#if !defined(LUA_NBITS) +#define LUA_NBITS 32 +#endif + + +/* +** a lua_Unsigned with its first LUA_NBITS bits equal to 1. (Shift must +** be made in two parts to avoid problems when LUA_NBITS is equal to the +** number of bits in a lua_Unsigned.) +*/ +#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1)) + + +/* macro to trim extra bits */ +#define trim(x) ((x) & ALLONES) + + +/* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */ +#define mask(n) (~((ALLONES << 1) << ((n) - 1))) + + + +static lua_Unsigned andaux (lua_State *L) { + int i, n = lua_gettop(L); + lua_Unsigned r = ~(lua_Unsigned)0; + for (i = 1; i <= n; i++) + r &= checkunsigned(L, i); + return trim(r); +} + + +static int b_and (lua_State *L) { + lua_Unsigned r = andaux(L); + pushunsigned(L, r); + return 1; +} + + +static int b_test (lua_State *L) { + lua_Unsigned r = andaux(L); + lua_pushboolean(L, r != 0); + return 1; +} + + +static int b_or (lua_State *L) { + int i, n = lua_gettop(L); + lua_Unsigned r = 0; + for (i = 1; i <= n; i++) + r |= checkunsigned(L, i); + pushunsigned(L, trim(r)); + return 1; +} + + +static int b_xor (lua_State *L) { + int i, n = lua_gettop(L); + lua_Unsigned r = 0; + for (i = 1; i <= n; i++) + r ^= checkunsigned(L, i); + pushunsigned(L, trim(r)); + return 1; +} + + +static int b_not (lua_State *L) { + lua_Unsigned r = ~checkunsigned(L, 1); + pushunsigned(L, trim(r)); + return 1; +} + + +static int b_shift (lua_State *L, lua_Unsigned r, lua_Integer i) { + if (i < 0) { /* shift right? */ + i = -i; + r = trim(r); + if (i >= LUA_NBITS) r = 0; + else r >>= i; + } + else { /* shift left */ + if (i >= LUA_NBITS) r = 0; + else r <<= i; + r = trim(r); + } + pushunsigned(L, r); + return 1; +} + + +static int b_lshift (lua_State *L) { + return b_shift(L, checkunsigned(L, 1), luaL_checkinteger(L, 2)); +} + + +static int b_rshift (lua_State *L) { + return b_shift(L, checkunsigned(L, 1), -luaL_checkinteger(L, 2)); +} + + +static int b_arshift (lua_State *L) { + lua_Unsigned r = checkunsigned(L, 1); + lua_Integer i = luaL_checkinteger(L, 2); + if (i < 0 || !(r & ((lua_Unsigned)1 << (LUA_NBITS - 1)))) + return b_shift(L, r, -i); + else { /* arithmetic shift for 'negative' number */ + if (i >= LUA_NBITS) r = ALLONES; + else + r = trim((r >> i) | ~(trim(~(lua_Unsigned)0) >> i)); /* add signal bit */ + pushunsigned(L, r); + return 1; + } +} + + +static int b_rot (lua_State *L, lua_Integer d) { + lua_Unsigned r = checkunsigned(L, 1); + int i = d & (LUA_NBITS - 1); /* i = d % NBITS */ + r = trim(r); + if (i != 0) /* avoid undefined shift of LUA_NBITS when i == 0 */ + r = (r << i) | (r >> (LUA_NBITS - i)); + pushunsigned(L, trim(r)); + return 1; +} + + +static int b_lrot (lua_State *L) { + return b_rot(L, luaL_checkinteger(L, 2)); +} + + +static int b_rrot (lua_State *L) { + return b_rot(L, -luaL_checkinteger(L, 2)); +} + + +/* +** get field and width arguments for field-manipulation functions, +** checking whether they are valid. +** ('luaL_error' called without 'return' to avoid later warnings about +** 'width' being used uninitialized.) +*/ +static int fieldargs (lua_State *L, int farg, int *width) { + lua_Integer f = luaL_checkinteger(L, farg); + lua_Integer w = luaL_optinteger(L, farg + 1, 1); + luaL_argcheck(L, 0 <= f, farg, "field cannot be negative"); + luaL_argcheck(L, 0 < w, farg + 1, "width must be positive"); + if (f + w > LUA_NBITS) + luaL_error(L, "trying to access non-existent bits"); + *width = (int)w; + return (int)f; +} + + +static int b_extract (lua_State *L) { + int w; + lua_Unsigned r = trim(checkunsigned(L, 1)); + int f = fieldargs(L, 2, &w); + r = (r >> f) & mask(w); + pushunsigned(L, r); + return 1; +} + + +static int b_replace (lua_State *L) { + int w; + lua_Unsigned r = trim(checkunsigned(L, 1)); + lua_Unsigned v = trim(checkunsigned(L, 2)); + int f = fieldargs(L, 3, &w); + lua_Unsigned m = mask(w); + r = (r & ~(m << f)) | ((v & m) << f); + pushunsigned(L, r); + return 1; +} + + +static const luaL_Reg bitlib[] = { + {"arshift", b_arshift}, + {"band", b_and}, + {"bnot", b_not}, + {"bor", b_or}, + {"bxor", b_xor}, + {"btest", b_test}, + {"extract", b_extract}, + {"lrotate", b_lrot}, + {"lshift", b_lshift}, + {"replace", b_replace}, + {"rrotate", b_rrot}, + {"rshift", b_rshift}, + {NULL, NULL} +}; + + + +LUAMOD_API int luaopen_bit32 (lua_State *L) { + luaL_newlib(L, bitlib); + return 1; +} + + +#else /* }{ */ + + +LUAMOD_API int luaopen_bit32 (lua_State *L) { + return luaL_error(L, "library 'bit32' has been deprecated"); +} + +#endif /* } */ diff --git a/app/src/main/jni/lua/lcode.c b/app/src/main/jni/lua/lcode.c index 679cb9c..2cd0dd2 100644 --- a/app/src/main/jni/lua/lcode.c +++ b/app/src/main/jni/lua/lcode.c @@ -1,15 +1,18 @@ /* -** $Id: lcode.c,v 2.25.1.5 2011/01/31 14:53:16 roberto Exp $ +** $Id: lcode.c,v 2.109 2016/05/13 19:09:21 roberto Exp $ ** Code generator for Lua ** See Copyright Notice in lua.h */ - -#include - #define lcode_c #define LUA_CORE +#include "lprefix.h" + + +#include +#include + #include "lua.h" #include "lcode.h" @@ -21,74 +24,145 @@ #include "lobject.h" #include "lopcodes.h" #include "lparser.h" +#include "lstring.h" #include "ltable.h" +#include "lvm.h" + + +/* Maximum number of registers in a Lua function (must fit in 8 bits) */ +#define MAXREGS 255 #define hasjumps(e) ((e)->t != (e)->f) -static int isnumeral(expdesc *e) { - return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); +/* +** If expression is a numeric constant, fills 'v' with its value +** and returns 1. Otherwise, returns 0. +*/ +static int tonumeral(expdesc *e, TValue *v) { + if (hasjumps(e)) + return 0; /* not a numeral */ + switch (e->k) { + case VKINT: + if (v) setivalue(v, e->u.ival); + return 1; + case VKFLT: + if (v) setfltvalue(v, e->u.nval); + return 1; + default: return 0; + } } +/* +** Create a OP_LOADNIL instruction, but try to optimize: if the previous +** instruction is also OP_LOADNIL and ranges are compatible, adjust +** range of previous instruction instead of emitting a new one. (For +** instance, 'local a; local b' will generate a single opcode.) +*/ void luaK_nil (FuncState *fs, int from, int n) { Instruction *previous; + int l = from + n - 1; /* last register to set nil */ if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ - if (fs->pc == 0) { /* function start? */ - if (from >= fs->nactvar) - return; /* positions are already clean */ - } - else { - previous = &fs->f->code[fs->pc-1]; - if (GET_OPCODE(*previous) == OP_LOADNIL) { - int pfrom = GETARG_A(*previous); - int pto = GETARG_B(*previous); - if (pfrom <= from && from <= pto+1) { /* can connect both? */ - if (from+n-1 > pto) - SETARG_B(*previous, from+n-1); - return; - } + previous = &fs->f->code[fs->pc-1]; + if (GET_OPCODE(*previous) == OP_LOADNIL) { /* previous is LOADNIL? */ + int pfrom = GETARG_A(*previous); /* get previous range */ + int pl = pfrom + GETARG_B(*previous); + if ((pfrom <= from && from <= pl + 1) || + (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ + if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */ + if (pl > l) l = pl; /* l = max(l, pl) */ + SETARG_A(*previous, from); + SETARG_B(*previous, l - from); + return; } - } + } /* else go through */ } - luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ + luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */ } +/* +** Gets the destination address of a jump instruction. Used to traverse +** a list of jumps. +*/ +static int getjump (FuncState *fs, int pc) { + int offset = GETARG_sBx(fs->f->code[pc]); + if (offset == NO_JUMP) /* point to itself represents end of list */ + return NO_JUMP; /* end of list */ + else + return (pc+1)+offset; /* turn offset into absolute position */ +} + + +/* +** Fix jump instruction at position 'pc' to jump to 'dest'. +** (Jump addresses are relative in Lua) +*/ +static void fixjump (FuncState *fs, int pc, int dest) { + Instruction *jmp = &fs->f->code[pc]; + int offset = dest - (pc + 1); + lua_assert(dest != NO_JUMP); + if (abs(offset) > MAXARG_sBx) + luaX_syntaxerror(fs->ls, "control structure too long"); + SETARG_sBx(*jmp, offset); +} + + +/* +** Concatenate jump-list 'l2' into jump-list 'l1' +*/ +void luaK_concat (FuncState *fs, int *l1, int l2) { + if (l2 == NO_JUMP) return; /* nothing to concatenate? */ + else if (*l1 == NO_JUMP) /* no original list? */ + *l1 = l2; /* 'l1' points to 'l2' */ + else { + int list = *l1; + int next; + while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ + list = next; + fixjump(fs, list, l2); /* last element links to 'l2' */ + } +} + + +/* +** Create a jump instruction and return its position, so its destination +** can be fixed later (with 'fixjump'). If there are jumps to +** this position (kept in 'jpc'), link them all together so that +** 'patchlistaux' will fix all them directly to the final destination. +*/ int luaK_jump (FuncState *fs) { int jpc = fs->jpc; /* save list of jumps to here */ int j; - fs->jpc = NO_JUMP; + fs->jpc = NO_JUMP; /* no more jumps to here */ j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); luaK_concat(fs, &j, jpc); /* keep them on hold */ return j; } +/* +** Code a 'return' instruction +*/ void luaK_ret (FuncState *fs, int first, int nret) { luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); } +/* +** Code a "conditional jump", that is, a test or comparison opcode +** followed by a jump. Return jump position. +*/ static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { luaK_codeABC(fs, op, A, B, C); return luaK_jump(fs); } -static void fixjump (FuncState *fs, int pc, int dest) { - Instruction *jmp = &fs->f->code[pc]; - int offset = dest-(pc+1); - lua_assert(dest != NO_JUMP); - if (abs(offset) > MAXARG_sBx) - luaX_syntaxerror(fs->ls, "control structure too long"); - SETARG_sBx(*jmp, offset); -} - - /* -** returns current `pc' and marks it as a jump target (to avoid wrong +** returns current 'pc' and marks it as a jump target (to avoid wrong ** optimizations with consecutive instructions not in the same basic block). */ int luaK_getlabel (FuncState *fs) { @@ -97,15 +171,11 @@ int luaK_getlabel (FuncState *fs) { } -static int getjump (FuncState *fs, int pc) { - int offset = GETARG_sBx(fs->f->code[pc]); - if (offset == NO_JUMP) /* point to itself represents end of list */ - return NO_JUMP; /* end of list */ - else - return (pc+1)+offset; /* turn offset into absolute position */ -} - - +/* +** Returns the position of the instruction "controlling" a given +** jump (that is, its condition), or the jump itself if it is +** unconditional. +*/ static Instruction *getjumpcontrol (FuncState *fs, int pc) { Instruction *pi = &fs->f->code[pc]; if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) @@ -116,37 +186,41 @@ static Instruction *getjumpcontrol (FuncState *fs, int pc) { /* -** check whether list has any jump that do not produce a value -** (or produce an inverted value) +** Patch destination register for a TESTSET instruction. +** If instruction in position 'node' is not a TESTSET, return 0 ("fails"). +** Otherwise, if 'reg' is not 'NO_REG', set it as the destination +** register. Otherwise, change instruction to a simple 'TEST' (produces +** no register value) */ -static int need_value (FuncState *fs, int list) { - for (; list != NO_JUMP; list = getjump(fs, list)) { - Instruction i = *getjumpcontrol(fs, list); - if (GET_OPCODE(i) != OP_TESTSET) return 1; - } - return 0; /* not found */ -} - - static int patchtestreg (FuncState *fs, int node, int reg) { Instruction *i = getjumpcontrol(fs, node); if (GET_OPCODE(*i) != OP_TESTSET) return 0; /* cannot patch other instructions */ if (reg != NO_REG && reg != GETARG_B(*i)) SETARG_A(*i, reg); - else /* no register to put value or register already has the value */ + else { + /* no register to put value or register already has the value; + change instruction to simple test */ *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); - + } return 1; } +/* +** Traverse a list of tests ensuring no one produces a value +*/ static void removevalues (FuncState *fs, int list) { for (; list != NO_JUMP; list = getjump(fs, list)) patchtestreg(fs, list, NO_REG); } +/* +** Traverse a list of tests, patching their destination address and +** registers: tests producing values jump to 'vtarget' (and put their +** values in 'reg'), other tests jump to 'dtarget'. +*/ static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, int dtarget) { while (list != NO_JUMP) { @@ -160,15 +234,35 @@ static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, } +/* +** Ensure all pending jumps to current position are fixed (jumping +** to current position with no values) and reset list of pending +** jumps +*/ static void dischargejpc (FuncState *fs) { patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); fs->jpc = NO_JUMP; } +/* +** Add elements in 'list' to list of pending jumps to "here" +** (current position) +*/ +void luaK_patchtohere (FuncState *fs, int list) { + luaK_getlabel(fs); /* mark "here" as a jump target */ + luaK_concat(fs, &fs->jpc, list); +} + + +/* +** Path all jumps in 'list' to jump to 'target'. +** (The assert means that we cannot fix a jump to a forward address +** because we only know addresses once code is generated.) +*/ void luaK_patchlist (FuncState *fs, int list, int target) { - if (target == fs->pc) - luaK_patchtohere(fs, list); + if (target == fs->pc) /* 'target' is current position? */ + luaK_patchtohere(fs, list); /* add list to pending jumps */ else { lua_assert(target < fs->pc); patchlistaux(fs, list, target, NO_REG, target); @@ -176,42 +270,119 @@ void luaK_patchlist (FuncState *fs, int list, int target) { } -void luaK_patchtohere (FuncState *fs, int list) { - luaK_getlabel(fs); - luaK_concat(fs, &fs->jpc, list); +/* +** Path all jumps in 'list' to close upvalues up to given 'level' +** (The assertion checks that jumps either were closing nothing +** or were closing higher levels, from inner blocks.) +*/ +void luaK_patchclose (FuncState *fs, int list, int level) { + level++; /* argument is +1 to reserve 0 as non-op */ + for (; list != NO_JUMP; list = getjump(fs, list)) { + lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP && + (GETARG_A(fs->f->code[list]) == 0 || + GETARG_A(fs->f->code[list]) >= level)); + SETARG_A(fs->f->code[list], level); + } } -void luaK_concat (FuncState *fs, int *l1, int l2) { - if (l2 == NO_JUMP) return; - else if (*l1 == NO_JUMP) - *l1 = l2; +/* +** Emit instruction 'i', checking for array sizes and saving also its +** line information. Return 'i' position. +*/ +static int luaK_code (FuncState *fs, Instruction i) { + Proto *f = fs->f; + dischargejpc(fs); /* 'pc' will change */ + /* put new instruction in code array */ + luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, + MAX_INT, "opcodes"); + f->code[fs->pc] = i; + /* save corresponding line information */ + luaM_growvector(fs->ls->L, f->lineinfo, fs->pc, f->sizelineinfo, int, + MAX_INT, "opcodes"); + f->lineinfo[fs->pc] = fs->ls->lastline; + return fs->pc++; +} + + +/* +** Format and emit an 'iABC' instruction. (Assertions check consistency +** of parameters versus opcode.) +*/ +int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { + lua_assert(getOpMode(o) == iABC); + lua_assert(getBMode(o) != OpArgN || b == 0); + lua_assert(getCMode(o) != OpArgN || c == 0); + lua_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C); + return luaK_code(fs, CREATE_ABC(o, a, b, c)); +} + + +/* +** Format and emit an 'iABx' instruction. +*/ +int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { + lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); + lua_assert(getCMode(o) == OpArgN); + lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx); + return luaK_code(fs, CREATE_ABx(o, a, bc)); +} + + +/* +** Emit an "extra argument" instruction (format 'iAx') +*/ +static int codeextraarg (FuncState *fs, int a) { + lua_assert(a <= MAXARG_Ax); + return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); +} + + +/* +** Emit a "load constant" instruction, using either 'OP_LOADK' +** (if constant index 'k' fits in 18 bits) or an 'OP_LOADKX' +** instruction with "extra argument". +*/ +int luaK_codek (FuncState *fs, int reg, int k) { + if (k <= MAXARG_Bx) + return luaK_codeABx(fs, OP_LOADK, reg, k); else { - int list = *l1; - int next; - while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ - list = next; - fixjump(fs, list, l2); + int p = luaK_codeABx(fs, OP_LOADKX, reg, 0); + codeextraarg(fs, k); + return p; } } +/* +** Check register-stack level, keeping track of its maximum size +** in field 'maxstacksize' +*/ void luaK_checkstack (FuncState *fs, int n) { int newstack = fs->freereg + n; if (newstack > fs->f->maxstacksize) { - if (newstack >= MAXSTACK) - luaX_syntaxerror(fs->ls, "function or expression too complex"); + if (newstack >= MAXREGS) + luaX_syntaxerror(fs->ls, + "function or expression needs too many registers"); fs->f->maxstacksize = cast_byte(newstack); } } +/* +** Reserve 'n' registers in register stack +*/ void luaK_reserveregs (FuncState *fs, int n) { luaK_checkstack(fs, n); fs->freereg += n; } +/* +** Free register 'reg', if it is neither a constant index nor +** a local variable. +) +*/ static void freereg (FuncState *fs, int reg) { if (!ISK(reg) && reg >= fs->nactvar) { fs->freereg--; @@ -220,112 +391,195 @@ static void freereg (FuncState *fs, int reg) { } +/* +** Free register used by expression 'e' (if any) +*/ static void freeexp (FuncState *fs, expdesc *e) { if (e->k == VNONRELOC) - freereg(fs, e->u.s.info); + freereg(fs, e->u.info); } -static int addk (FuncState *fs, TValue *k, TValue *v) { - lua_State *L = fs->L; - TValue *idx = luaH_set(L, fs->h, k); - Proto *f = fs->f; - int oldsize = f->sizek; - if (ttisnumber(idx)) { - lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); - return cast_int(nvalue(idx)); +/* +** Free registers used by expressions 'e1' and 'e2' (if any) in proper +** order. +*/ +static void freeexps (FuncState *fs, expdesc *e1, expdesc *e2) { + int r1 = (e1->k == VNONRELOC) ? e1->u.info : -1; + int r2 = (e2->k == VNONRELOC) ? e2->u.info : -1; + if (r1 > r2) { + freereg(fs, r1); + freereg(fs, r2); } - else { /* constant not found; create a new entry */ - setnvalue(idx, cast_num(fs->nk)); - luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, - MAXARG_Bx, "constant table overflow"); - while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); - setobj(L, &f->k[fs->nk], v); - luaC_barrier(L, f, v); - return fs->nk++; + else { + freereg(fs, r2); + freereg(fs, r1); + } +} + + +/* +** Add constant 'v' to prototype's list of constants (field 'k'). +** Use scanner's table to cache position of constants in constant list +** and try to reuse constants. Because some values should not be used +** as keys (nil cannot be a key, integer keys can collapse with float +** keys), the caller must provide a useful 'key' for indexing the cache. +*/ +static int addk (FuncState *fs, TValue *key, TValue *v) { + lua_State *L = fs->ls->L; + Proto *f = fs->f; + TValue *idx = luaH_set(L, fs->ls->h, key); /* index scanner table */ + int k, oldsize; + if (ttisinteger(idx)) { /* is there an index there? */ + k = cast_int(ivalue(idx)); + /* correct value? (warning: must distinguish floats from integers!) */ + if (k < fs->nk && ttype(&f->k[k]) == ttype(v) && + luaV_rawequalobj(&f->k[k], v)) + return k; /* reuse index */ } + /* constant not found; create a new entry */ + oldsize = f->sizek; + k = fs->nk; + /* numerical value does not need GC barrier; + table has no metatable, so it does not need to invalidate cache */ + setivalue(idx, k); + luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); + while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); + setobj(L, &f->k[k], v); + fs->nk++; + luaC_barrier(L, f, v); + return k; } +/* +** Add a string to list of constants and return its index. +*/ int luaK_stringK (FuncState *fs, TString *s) { TValue o; - setsvalue(fs->L, &o, s); - return addk(fs, &o, &o); + setsvalue(fs->ls->L, &o, s); + return addk(fs, &o, &o); /* use string itself as key */ } -int luaK_numberK (FuncState *fs, lua_Number r) { +/* +** Add an integer to list of constants and return its index. +** Integers use userdata as keys to avoid collision with floats with +** same value; conversion to 'void*' is used only for hashing, so there +** are no "precision" problems. +*/ +int luaK_intK (FuncState *fs, lua_Integer n) { + TValue k, o; + setpvalue(&k, cast(void*, cast(size_t, n))); + setivalue(&o, n); + return addk(fs, &k, &o); +} + +/* +** Add a float to list of constants and return its index. +*/ +static int luaK_numberK (FuncState *fs, lua_Number r) { TValue o; - setnvalue(&o, r); - return addk(fs, &o, &o); + setfltvalue(&o, r); + return addk(fs, &o, &o); /* use number itself as key */ } +/* +** Add a boolean to list of constants and return its index. +*/ static int boolK (FuncState *fs, int b) { TValue o; setbvalue(&o, b); - return addk(fs, &o, &o); + return addk(fs, &o, &o); /* use boolean itself as key */ } +/* +** Add nil to list of constants and return its index. +*/ static int nilK (FuncState *fs) { TValue k, v; setnilvalue(&v); /* cannot use nil as key; instead use table itself to represent nil */ - sethvalue(fs->L, &k, fs->h); + sethvalue(fs->ls->L, &k, fs->ls->h); return addk(fs, &k, &v); } +/* +** Fix an expression to return the number of results 'nresults'. +** Either 'e' is a multi-ret expression (function call or vararg) +** or 'nresults' is LUA_MULTRET (as any expression can satisfy that). +*/ void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { if (e->k == VCALL) { /* expression is an open function call? */ - SETARG_C(getcode(fs, e), nresults+1); + SETARG_C(getinstruction(fs, e), nresults + 1); } else if (e->k == VVARARG) { - SETARG_B(getcode(fs, e), nresults+1); - SETARG_A(getcode(fs, e), fs->freereg); + Instruction *pc = &getinstruction(fs, e); + SETARG_B(*pc, nresults + 1); + SETARG_A(*pc, fs->freereg); luaK_reserveregs(fs, 1); } + else lua_assert(nresults == LUA_MULTRET); } +/* +** Fix an expression to return one result. +** If expression is not a multi-ret expression (function call or +** vararg), it already returns one result, so nothing needs to be done. +** Function calls become VNONRELOC expressions (as its result comes +** fixed in the base register of the call), while vararg expressions +** become VRELOCABLE (as OP_VARARG puts its results where it wants). +** (Calls are created returning one result, so that does not need +** to be fixed.) +*/ void luaK_setoneret (FuncState *fs, expdesc *e) { if (e->k == VCALL) { /* expression is an open function call? */ - e->k = VNONRELOC; - e->u.s.info = GETARG_A(getcode(fs, e)); + /* already returns 1 value */ + lua_assert(GETARG_C(getinstruction(fs, e)) == 2); + e->k = VNONRELOC; /* result has fixed position */ + e->u.info = GETARG_A(getinstruction(fs, e)); } else if (e->k == VVARARG) { - SETARG_B(getcode(fs, e), 2); + SETARG_B(getinstruction(fs, e), 2); e->k = VRELOCABLE; /* can relocate its simple result */ } } +/* +** Ensure that expression 'e' is not a variable. +*/ void luaK_dischargevars (FuncState *fs, expdesc *e) { switch (e->k) { - case VLOCAL: { - e->k = VNONRELOC; + case VLOCAL: { /* already in a register */ + e->k = VNONRELOC; /* becomes a non-relocatable value */ break; } - case VUPVAL: { - e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0); - e->k = VRELOCABLE; - break; - } - case VGLOBAL: { - e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info); + case VUPVAL: { /* move value to some (pending) register */ + e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); e->k = VRELOCABLE; break; } case VINDEXED: { - freereg(fs, e->u.s.aux); - freereg(fs, e->u.s.info); - e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux); + OpCode op; + freereg(fs, e->u.ind.idx); + if (e->u.ind.vt == VLOCAL) { /* is 't' in a register? */ + freereg(fs, e->u.ind.t); + op = OP_GETTABLE; + } + else { + lua_assert(e->u.ind.vt == VUPVAL); + op = OP_GETTABUP; /* 't' is in an upvalue */ + } + e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); e->k = VRELOCABLE; break; } - case VVARARG: - case VCALL: { + case VVARARG: case VCALL: { luaK_setoneret(fs, e); break; } @@ -334,12 +588,10 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { } -static int code_label (FuncState *fs, int A, int b, int jump) { - luaK_getlabel(fs); /* those instructions may be jump targets */ - return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); -} - - +/* +** Ensures expression value is in register 'reg' (and therefore +** 'e' will become a non-relocatable expression). +*/ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { luaK_dischargevars(fs, e); switch (e->k) { @@ -347,58 +599,91 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { luaK_nil(fs, reg, 1); break; } - case VFALSE: case VTRUE: { + case VFALSE: case VTRUE: { luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); break; } case VK: { - luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info); + luaK_codek(fs, reg, e->u.info); + break; + } + case VKFLT: { + luaK_codek(fs, reg, luaK_numberK(fs, e->u.nval)); break; } - case VKNUM: { - luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); + case VKINT: { + luaK_codek(fs, reg, luaK_intK(fs, e->u.ival)); break; } case VRELOCABLE: { - Instruction *pc = &getcode(fs, e); - SETARG_A(*pc, reg); + Instruction *pc = &getinstruction(fs, e); + SETARG_A(*pc, reg); /* instruction will put result in 'reg' */ break; } case VNONRELOC: { - if (reg != e->u.s.info) - luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0); + if (reg != e->u.info) + luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0); break; } default: { - lua_assert(e->k == VVOID || e->k == VJMP); + lua_assert(e->k == VJMP); return; /* nothing to do... */ } } - e->u.s.info = reg; + e->u.info = reg; e->k = VNONRELOC; } +/* +** Ensures expression value is in any register. +*/ static void discharge2anyreg (FuncState *fs, expdesc *e) { - if (e->k != VNONRELOC) { - luaK_reserveregs(fs, 1); - discharge2reg(fs, e, fs->freereg-1); + if (e->k != VNONRELOC) { /* no fixed register yet? */ + luaK_reserveregs(fs, 1); /* get a register */ + discharge2reg(fs, e, fs->freereg-1); /* put value there */ } } +static int code_loadbool (FuncState *fs, int A, int b, int jump) { + luaK_getlabel(fs); /* those instructions may be jump targets */ + return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); +} + + +/* +** check whether list has any jump that do not produce a value +** or produce an inverted value +*/ +static int need_value (FuncState *fs, int list) { + for (; list != NO_JUMP; list = getjump(fs, list)) { + Instruction i = *getjumpcontrol(fs, list); + if (GET_OPCODE(i) != OP_TESTSET) return 1; + } + return 0; /* not found */ +} + + +/* +** Ensures final expression result (including results from its jump +** lists) is in register 'reg'. +** If expression has jumps, need to patch these jumps either to +** its final position or to "load" instructions (for those tests +** that do not produce values). +*/ static void exp2reg (FuncState *fs, expdesc *e, int reg) { discharge2reg(fs, e, reg); - if (e->k == VJMP) - luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */ + if (e->k == VJMP) /* expression itself is a test? */ + luaK_concat(fs, &e->t, e->u.info); /* put this jump in 't' list */ if (hasjumps(e)) { int final; /* position after whole expression */ int p_f = NO_JUMP; /* position of an eventual LOAD false */ int p_t = NO_JUMP; /* position of an eventual LOAD true */ if (need_value(fs, e->t) || need_value(fs, e->f)) { int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); - p_f = code_label(fs, reg, 0, 1); - p_t = code_label(fs, reg, 1, 0); + p_f = code_loadbool(fs, reg, 0, 1); + p_t = code_loadbool(fs, reg, 1, 0); luaK_patchtohere(fs, fj); } final = luaK_getlabel(fs); @@ -406,11 +691,15 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) { patchlistaux(fs, e->t, final, reg, p_t); } e->f = e->t = NO_JUMP; - e->u.s.info = reg; + e->u.info = reg; e->k = VNONRELOC; } +/* +** Ensures final expression result (including results from its jump +** lists) is in next available register. +*/ void luaK_exp2nextreg (FuncState *fs, expdesc *e) { luaK_dischargevars(fs, e); freeexp(fs, e); @@ -419,20 +708,39 @@ void luaK_exp2nextreg (FuncState *fs, expdesc *e) { } +/* +** Ensures final expression result (including results from its jump +** lists) is in some (any) register and return that register. +*/ int luaK_exp2anyreg (FuncState *fs, expdesc *e) { luaK_dischargevars(fs, e); - if (e->k == VNONRELOC) { - if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */ - if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */ - exp2reg(fs, e, e->u.s.info); /* put value on it */ - return e->u.s.info; + if (e->k == VNONRELOC) { /* expression already has a register? */ + if (!hasjumps(e)) /* no jumps? */ + return e->u.info; /* result is already in a register */ + if (e->u.info >= fs->nactvar) { /* reg. is not a local? */ + exp2reg(fs, e, e->u.info); /* put final result in it */ + return e->u.info; } } - luaK_exp2nextreg(fs, e); /* default */ - return e->u.s.info; + luaK_exp2nextreg(fs, e); /* otherwise, use next available register */ + return e->u.info; +} + + +/* +** Ensures final expression result is either in a register or in an +** upvalue. +*/ +void luaK_exp2anyregup (FuncState *fs, expdesc *e) { + if (e->k != VUPVAL || hasjumps(e)) + luaK_exp2anyreg(fs, e); } +/* +** Ensures final expression result is either in a register or it is +** a constant. +*/ void luaK_exp2val (FuncState *fs, expdesc *e) { if (hasjumps(e)) luaK_exp2anyreg(fs, e); @@ -441,27 +749,26 @@ void luaK_exp2val (FuncState *fs, expdesc *e) { } +/* +** Ensures final expression result is in a valid R/K index +** (that is, it is either in a register or in 'k' with an index +** in the range of R/K indices). +** Returns R/K index. +*/ int luaK_exp2RK (FuncState *fs, expdesc *e) { luaK_exp2val(fs, e); - switch (e->k) { - case VKNUM: - case VTRUE: - case VFALSE: - case VNIL: { - if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ - e->u.s.info = (e->k == VNIL) ? nilK(fs) : - (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) : - boolK(fs, (e->k == VTRUE)); - e->k = VK; - return RKASK(e->u.s.info); - } - else break; - } - case VK: { - if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */ - return RKASK(e->u.s.info); + switch (e->k) { /* move constants to 'k' */ + case VTRUE: e->u.info = boolK(fs, 1); goto vk; + case VFALSE: e->u.info = boolK(fs, 0); goto vk; + case VNIL: e->u.info = nilK(fs); goto vk; + case VKINT: e->u.info = luaK_intK(fs, e->u.ival); goto vk; + case VKFLT: e->u.info = luaK_numberK(fs, e->u.nval); goto vk; + case VK: + vk: + e->k = VK; + if (e->u.info <= MAXINDEXRK) /* constant fits in 'argC'? */ + return RKASK(e->u.info); else break; - } default: break; } /* not a constant in the right range: put it in a register */ @@ -469,61 +776,69 @@ int luaK_exp2RK (FuncState *fs, expdesc *e) { } +/* +** Generate code to store result of expression 'ex' into variable 'var'. +*/ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { switch (var->k) { case VLOCAL: { freeexp(fs, ex); - exp2reg(fs, ex, var->u.s.info); + exp2reg(fs, ex, var->u.info); /* compute 'ex' into proper place */ return; } case VUPVAL: { int e = luaK_exp2anyreg(fs, ex); - luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0); - break; - } - case VGLOBAL: { - int e = luaK_exp2anyreg(fs, ex); - luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info); + luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0); break; } case VINDEXED: { + OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP; int e = luaK_exp2RK(fs, ex); - luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e); - break; - } - default: { - lua_assert(0); /* invalid var kind to store */ + luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e); break; } + default: lua_assert(0); /* invalid var kind to store */ } freeexp(fs, ex); } +/* +** Emit SELF instruction (convert expression 'e' into 'e:key(e,'). +*/ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { - int func; + int ereg; luaK_exp2anyreg(fs, e); + ereg = e->u.info; /* register where 'e' was placed */ freeexp(fs, e); - func = fs->freereg; - luaK_reserveregs(fs, 2); - luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key)); + e->u.info = fs->freereg; /* base register for op_self */ + e->k = VNONRELOC; /* self expression has a fixed register */ + luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */ + luaK_codeABC(fs, OP_SELF, e->u.info, ereg, luaK_exp2RK(fs, key)); freeexp(fs, key); - e->u.s.info = func; - e->k = VNONRELOC; } -static void invertjump (FuncState *fs, expdesc *e) { - Instruction *pc = getjumpcontrol(fs, e->u.s.info); +/* +** Negate condition 'e' (where 'e' is a comparison). +*/ +static void negatecondition (FuncState *fs, expdesc *e) { + Instruction *pc = getjumpcontrol(fs, e->u.info); lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && GET_OPCODE(*pc) != OP_TEST); SETARG_A(*pc, !(GETARG_A(*pc))); } +/* +** Emit instruction to jump if 'e' is 'cond' (that is, if 'cond' +** is true, code will jump if 'e' is true.) Return jump position. +** Optimize when 'e' is 'not' something, inverting the condition +** and removing the 'not'. +*/ static int jumponcond (FuncState *fs, expdesc *e, int cond) { if (e->k == VRELOCABLE) { - Instruction ie = getcode(fs, e); + Instruction ie = getinstruction(fs, e); if (GET_OPCODE(ie) == OP_NOT) { fs->pc--; /* remove previous OP_NOT */ return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); @@ -532,198 +847,260 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) { } discharge2anyreg(fs, e); freeexp(fs, e); - return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond); + return condjump(fs, OP_TESTSET, NO_REG, e->u.info, cond); } +/* +** Emit code to go through if 'e' is true, jump otherwise. +*/ void luaK_goiftrue (FuncState *fs, expdesc *e) { - int pc; /* pc of last jump */ + int pc; /* pc of new jump */ luaK_dischargevars(fs, e); switch (e->k) { - case VK: case VKNUM: case VTRUE: { - pc = NO_JUMP; /* always true; do nothing */ + case VJMP: { /* condition? */ + negatecondition(fs, e); /* jump when it is false */ + pc = e->u.info; /* save jump position */ break; } - case VJMP: { - invertjump(fs, e); - pc = e->u.s.info; + case VK: case VKFLT: case VKINT: case VTRUE: { + pc = NO_JUMP; /* always true; do nothing */ break; } default: { - pc = jumponcond(fs, e, 0); + pc = jumponcond(fs, e, 0); /* jump when false */ break; } } - luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ - luaK_patchtohere(fs, e->t); + luaK_concat(fs, &e->f, pc); /* insert new jump in false list */ + luaK_patchtohere(fs, e->t); /* true list jumps to here (to go through) */ e->t = NO_JUMP; } -static void luaK_goiffalse (FuncState *fs, expdesc *e) { - int pc; /* pc of last jump */ +/* +** Emit code to go through if 'e' is false, jump otherwise. +*/ +void luaK_goiffalse (FuncState *fs, expdesc *e) { + int pc; /* pc of new jump */ luaK_dischargevars(fs, e); switch (e->k) { - case VNIL: case VFALSE: { - pc = NO_JUMP; /* always false; do nothing */ + case VJMP: { + pc = e->u.info; /* already jump if true */ break; } - case VJMP: { - pc = e->u.s.info; + case VNIL: case VFALSE: { + pc = NO_JUMP; /* always false; do nothing */ break; } default: { - pc = jumponcond(fs, e, 1); + pc = jumponcond(fs, e, 1); /* jump if true */ break; } } - luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ - luaK_patchtohere(fs, e->f); + luaK_concat(fs, &e->t, pc); /* insert new jump in 't' list */ + luaK_patchtohere(fs, e->f); /* false list jumps to here (to go through) */ e->f = NO_JUMP; } +/* +** Code 'not e', doing constant folding. +*/ static void codenot (FuncState *fs, expdesc *e) { luaK_dischargevars(fs, e); switch (e->k) { case VNIL: case VFALSE: { - e->k = VTRUE; + e->k = VTRUE; /* true == not nil == not false */ break; } - case VK: case VKNUM: case VTRUE: { - e->k = VFALSE; + case VK: case VKFLT: case VKINT: case VTRUE: { + e->k = VFALSE; /* false == not "x" == not 0.5 == not 1 == not true */ break; } case VJMP: { - invertjump(fs, e); + negatecondition(fs, e); break; } case VRELOCABLE: case VNONRELOC: { discharge2anyreg(fs, e); freeexp(fs, e); - e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0); + e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0); e->k = VRELOCABLE; break; } - default: { - lua_assert(0); /* cannot happen */ - break; - } + default: lua_assert(0); /* cannot happen */ } /* interchange true and false lists */ { int temp = e->f; e->f = e->t; e->t = temp; } - removevalues(fs, e->f); + removevalues(fs, e->f); /* values are useless when negated */ removevalues(fs, e->t); } +/* +** Create expression 't[k]'. 't' must have its final result already in a +** register or upvalue. +*/ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { - t->u.s.aux = luaK_exp2RK(fs, k); + lua_assert(!hasjumps(t) && (vkisinreg(t->k) || t->k == VUPVAL)); + t->u.ind.t = t->u.info; /* register or upvalue index */ + t->u.ind.idx = luaK_exp2RK(fs, k); /* R/K index for key */ + t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL : VLOCAL; t->k = VINDEXED; } -static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { - lua_Number v1, v2, r; - if (!isnumeral(e1) || !isnumeral(e2)) return 0; - v1 = e1->u.nval; - v2 = e2->u.nval; +/* +** Return false if folding can raise an error. +** Bitwise operations need operands convertible to integers; division +** operations cannot have 0 as divisor. +*/ +static int validop (int op, TValue *v1, TValue *v2) { switch (op) { - case OP_ADD: r = luai_numadd(v1, v2); break; - case OP_SUB: r = luai_numsub(v1, v2); break; - case OP_MUL: r = luai_nummul(v1, v2); break; - case OP_DIV: - if (v2 == 0) return 0; /* do not attempt to divide by 0 */ - r = luai_numdiv(v1, v2); break; - case OP_MOD: - if (v2 == 0) return 0; /* do not attempt to divide by 0 */ - r = luai_nummod(v1, v2); break; - case OP_POW: r = luai_numpow(v1, v2); break; - case OP_UNM: r = luai_numunm(v1); break; - case OP_LEN: return 0; /* no constant folding for 'len' */ - default: lua_assert(0); r = 0; break; - } - if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */ - e1->u.nval = r; - return 1; + case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: + case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: { /* conversion errors */ + lua_Integer i; + return (tointeger(v1, &i) && tointeger(v2, &i)); + } + case LUA_OPDIV: case LUA_OPIDIV: case LUA_OPMOD: /* division by 0 */ + return (nvalue(v2) != 0); + default: return 1; /* everything else is valid */ + } } -static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { - if (constfolding(op, e1, e2)) - return; - else { - int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; - int o1 = luaK_exp2RK(fs, e1); - if (o1 > o2) { - freeexp(fs, e1); - freeexp(fs, e2); - } - else { - freeexp(fs, e2); - freeexp(fs, e1); - } - e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2); - e1->k = VRELOCABLE; +/* +** Try to "constant-fold" an operation; return 1 iff successful. +** (In this case, 'e1' has the final result.) +*/ +static int constfolding (FuncState *fs, int op, expdesc *e1, expdesc *e2) { + TValue v1, v2, res; + if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2) || !validop(op, &v1, &v2)) + return 0; /* non-numeric operands or not safe to fold */ + luaO_arith(fs->ls->L, op, &v1, &v2, &res); /* does operation */ + if (ttisinteger(&res)) { + e1->k = VKINT; + e1->u.ival = ivalue(&res); } + else { /* folds neither NaN nor 0.0 (to avoid problems with -0.0) */ + lua_Number n = fltvalue(&res); + if (luai_numisnan(n) || n == 0) + return 0; + e1->k = VKFLT; + e1->u.nval = n; + } + return 1; +} + + +/* +** Emit code for unary expressions that "produce values" +** (everything but 'not'). +** Expression to produce final result will be encoded in 'e'. +*/ +static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) { + int r = luaK_exp2anyreg(fs, e); /* opcodes operate only on registers */ + freeexp(fs, e); + e->u.info = luaK_codeABC(fs, op, 0, r, 0); /* generate opcode */ + e->k = VRELOCABLE; /* all those operations are relocatable */ + luaK_fixline(fs, line); } -static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, - expdesc *e2) { - int o1 = luaK_exp2RK(fs, e1); - int o2 = luaK_exp2RK(fs, e2); - freeexp(fs, e2); - freeexp(fs, e1); - if (cond == 0 && op != OP_EQ) { - int temp; /* exchange args to replace by `<' or `<=' */ - temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ - cond = 1; +/* +** Emit code for binary expressions that "produce values" +** (everything but logical operators 'and'/'or' and comparison +** operators). +** Expression to produce final result will be encoded in 'e1'. +*/ +static void codebinexpval (FuncState *fs, OpCode op, + expdesc *e1, expdesc *e2, int line) { + int rk1 = luaK_exp2RK(fs, e1); /* both operands are "RK" */ + int rk2 = luaK_exp2RK(fs, e2); + freeexps(fs, e1, e2); + e1->u.info = luaK_codeABC(fs, op, 0, rk1, rk2); /* generate opcode */ + e1->k = VRELOCABLE; /* all those operations are relocatable */ + luaK_fixline(fs, line); +} + + +/* +** Emit code for comparisons. +** 'e1' was already put in R/K form by 'luaK_infix'. +*/ +static void codecomp (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { + int rk1 = (e1->k == VK) ? RKASK(e1->u.info) + : check_exp(e1->k == VNONRELOC, e1->u.info); + int rk2 = luaK_exp2RK(fs, e2); + freeexps(fs, e1, e2); + switch (opr) { + case OPR_NE: { /* '(a ~= b)' ==> 'not (a == b)' */ + e1->u.info = condjump(fs, OP_EQ, 0, rk1, rk2); + break; + } + case OPR_GT: case OPR_GE: { + /* '(a > b)' ==> '(b < a)'; '(a >= b)' ==> '(b <= a)' */ + OpCode op = cast(OpCode, (opr - OPR_NE) + OP_EQ); + e1->u.info = condjump(fs, op, 1, rk2, rk1); /* invert operands */ + break; + } + default: { /* '==', '<', '<=' use their own opcodes */ + OpCode op = cast(OpCode, (opr - OPR_EQ) + OP_EQ); + e1->u.info = condjump(fs, op, 1, rk1, rk2); + break; + } } - e1->u.s.info = condjump(fs, op, cond, o1, o2); e1->k = VJMP; } -void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { - expdesc e2; - e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; +/* +** Aplly prefix operation 'op' to expression 'e'. +*/ +void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { + static expdesc ef = {VKINT, {0}, NO_JUMP, NO_JUMP}; /* fake 2nd operand */ switch (op) { - case OPR_MINUS: { - if (!isnumeral(e)) - luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ - codearith(fs, OP_UNM, e, &e2); + case OPR_MINUS: case OPR_BNOT: + if (constfolding(fs, op + LUA_OPUNM, e, &ef)) + break; + /* FALLTHROUGH */ + case OPR_LEN: + codeunexpval(fs, cast(OpCode, op + OP_UNM), e, line); break; - } case OPR_NOT: codenot(fs, e); break; - case OPR_LEN: { - luaK_exp2anyreg(fs, e); /* cannot operate on constants */ - codearith(fs, OP_LEN, e, &e2); - break; - } default: lua_assert(0); } } +/* +** Process 1st operand 'v' of binary operation 'op' before reading +** 2nd operand. +*/ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { switch (op) { case OPR_AND: { - luaK_goiftrue(fs, v); + luaK_goiftrue(fs, v); /* go ahead only if 'v' is true */ break; } case OPR_OR: { - luaK_goiffalse(fs, v); + luaK_goiffalse(fs, v); /* go ahead only if 'v' is false */ break; } case OPR_CONCAT: { - luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ + luaK_exp2nextreg(fs, v); /* operand must be on the 'stack' */ break; } - case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: - case OPR_MOD: case OPR_POW: { - if (!isnumeral(v)) luaK_exp2RK(fs, v); + case OPR_ADD: case OPR_SUB: + case OPR_MUL: case OPR_DIV: case OPR_IDIV: + case OPR_MOD: case OPR_POW: + case OPR_BAND: case OPR_BOR: case OPR_BXOR: + case OPR_SHL: case OPR_SHR: { + if (!tonumeral(v, NULL)) + luaK_exp2RK(fs, v); + /* else keep numeral, which may be folded with 2nd operand */ break; } default: { @@ -734,17 +1111,24 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { } -void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { +/* +** Finalize code for binary operation, after reading 2nd operand. +** For '(a .. b .. c)' (which is '(a .. (b .. c))', because +** concatenation is right associative), merge second CONCAT into first +** one. +*/ +void luaK_posfix (FuncState *fs, BinOpr op, + expdesc *e1, expdesc *e2, int line) { switch (op) { case OPR_AND: { - lua_assert(e1->t == NO_JUMP); /* list must be closed */ + lua_assert(e1->t == NO_JUMP); /* list closed by 'luK_infix' */ luaK_dischargevars(fs, e2); luaK_concat(fs, &e2->f, e1->f); *e1 = *e2; break; } case OPR_OR: { - lua_assert(e1->f == NO_JUMP); /* list must be closed */ + lua_assert(e1->f == NO_JUMP); /* list closed by 'luK_infix' */ luaK_dischargevars(fs, e2); luaK_concat(fs, &e2->t, e1->t); *e1 = *e2; @@ -752,80 +1136,64 @@ void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { } case OPR_CONCAT: { luaK_exp2val(fs, e2); - if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { - lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1); + if (e2->k == VRELOCABLE && + GET_OPCODE(getinstruction(fs, e2)) == OP_CONCAT) { + lua_assert(e1->u.info == GETARG_B(getinstruction(fs, e2))-1); freeexp(fs, e1); - SETARG_B(getcode(fs, e2), e1->u.s.info); - e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info; + SETARG_B(getinstruction(fs, e2), e1->u.info); + e1->k = VRELOCABLE; e1->u.info = e2->u.info; } else { luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ - codearith(fs, OP_CONCAT, e1, e2); + codebinexpval(fs, OP_CONCAT, e1, e2, line); } break; } - case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break; - case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break; - case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break; - case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break; - case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break; - case OPR_POW: codearith(fs, OP_POW, e1, e2); break; - case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break; - case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break; - case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break; - case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break; - case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break; - case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break; + case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: + case OPR_IDIV: case OPR_MOD: case OPR_POW: + case OPR_BAND: case OPR_BOR: case OPR_BXOR: + case OPR_SHL: case OPR_SHR: { + if (!constfolding(fs, op + LUA_OPADD, e1, e2)) + codebinexpval(fs, cast(OpCode, op + OP_ADD), e1, e2, line); + break; + } + case OPR_EQ: case OPR_LT: case OPR_LE: + case OPR_NE: case OPR_GT: case OPR_GE: { + codecomp(fs, op, e1, e2); + break; + } default: lua_assert(0); } } +/* +** Change line information associated with current position. +*/ void luaK_fixline (FuncState *fs, int line) { fs->f->lineinfo[fs->pc - 1] = line; } -static int luaK_code (FuncState *fs, Instruction i, int line) { - Proto *f = fs->f; - dischargejpc(fs); /* `pc' will change */ - /* put new instruction in code array */ - luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, - MAX_INT, "code size overflow"); - f->code[fs->pc] = i; - /* save corresponding line information */ - luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int, - MAX_INT, "code size overflow"); - f->lineinfo[fs->pc] = line; - return fs->pc++; -} - - -int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { - lua_assert(getOpMode(o) == iABC); - lua_assert(getBMode(o) != OpArgN || b == 0); - lua_assert(getCMode(o) != OpArgN || c == 0); - return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline); -} - - -int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { - lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); - lua_assert(getCMode(o) == OpArgN); - return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline); -} - - +/* +** Emit a SETLIST instruction. +** 'base' is register that keeps table; +** 'nelems' is #table plus those to be stored now; +** 'tostore' is number of values (in registers 'base + 1',...) to add to +** table (or LUA_MULTRET to add up to stack top). +*/ void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; int b = (tostore == LUA_MULTRET) ? 0 : tostore; - lua_assert(tostore != 0); + lua_assert(tostore != 0 && tostore <= LFIELDS_PER_FLUSH); if (c <= MAXARG_C) luaK_codeABC(fs, OP_SETLIST, base, b, c); - else { + else if (c <= MAXARG_Ax) { luaK_codeABC(fs, OP_SETLIST, base, b, 0); - luaK_code(fs, cast(Instruction, c), fs->ls->lastline); + codeextraarg(fs, c); } + else + luaX_syntaxerror(fs->ls, "constructor too long"); fs->freereg = base + 1; /* free registers with list values */ } diff --git a/app/src/main/jni/lua/lcode.h b/app/src/main/jni/lua/lcode.h index b941c60..cd306d5 100644 --- a/app/src/main/jni/lua/lcode.h +++ b/app/src/main/jni/lua/lcode.h @@ -1,5 +1,5 @@ /* -** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lcode.h,v 1.64 2016/01/05 16:22:37 roberto Exp $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -21,43 +21,53 @@ /* -** grep "ORDER OPR" if you change these enums +** grep "ORDER OPR" if you change these enums (ORDER OP) */ typedef enum BinOpr { - OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, + OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW, + OPR_DIV, + OPR_IDIV, + OPR_BAND, OPR_BOR, OPR_BXOR, + OPR_SHL, OPR_SHR, OPR_CONCAT, - OPR_NE, OPR_EQ, - OPR_LT, OPR_LE, OPR_GT, OPR_GE, + OPR_EQ, OPR_LT, OPR_LE, + OPR_NE, OPR_GT, OPR_GE, OPR_AND, OPR_OR, OPR_NOBINOPR } BinOpr; -typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; +typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; -#define getcode(fs,e) ((fs)->f->code[(e)->u.s.info]) +/* get (pointer to) instruction of given 'expdesc' */ +#define getinstruction(fs,e) ((fs)->f->code[(e)->u.info]) #define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) #define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) +#define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t) + LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); +LUAI_FUNC int luaK_codek (FuncState *fs, int reg, int k); LUAI_FUNC void luaK_fixline (FuncState *fs, int line); LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); -LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); +LUAI_FUNC int luaK_intK (FuncState *fs, lua_Integer n); LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e); LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e); LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); @@ -65,11 +75,13 @@ LUAI_FUNC int luaK_jump (FuncState *fs); LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); +LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level); LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); LUAI_FUNC int luaK_getlabel (FuncState *fs); -LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); +LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line); LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); -LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); +LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, + expdesc *v2, int line); LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); diff --git a/app/src/main/jni/lua/lcorolib.c b/app/src/main/jni/lua/lcorolib.c new file mode 100644 index 0000000..2303429 --- /dev/null +++ b/app/src/main/jni/lua/lcorolib.c @@ -0,0 +1,168 @@ +/* +** $Id: lcorolib.c,v 1.10 2016/04/11 19:19:55 roberto Exp $ +** Coroutine Library +** See Copyright Notice in lua.h +*/ + +#define lcorolib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +static lua_State *getco (lua_State *L) { + lua_State *co = lua_tothread(L, 1); + luaL_argcheck(L, co, 1, "thread expected"); + return co; +} + + +static int auxresume (lua_State *L, lua_State *co, int narg) { + int status; + if (!lua_checkstack(co, narg)) { + lua_pushliteral(L, "too many arguments to resume"); + return -1; /* error flag */ + } + if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) { + lua_pushliteral(L, "cannot resume dead coroutine"); + return -1; /* error flag */ + } + lua_xmove(L, co, narg); + status = lua_resume(co, L, narg); + if (status == LUA_OK || status == LUA_YIELD) { + int nres = lua_gettop(co); + if (!lua_checkstack(L, nres + 1)) { + lua_pop(co, nres); /* remove results anyway */ + lua_pushliteral(L, "too many results to resume"); + return -1; /* error flag */ + } + lua_xmove(co, L, nres); /* move yielded values */ + return nres; + } + else { + lua_xmove(co, L, 1); /* move error message */ + return -1; /* error flag */ + } +} + + +static int luaB_coresume (lua_State *L) { + lua_State *co = getco(L); + int r; + r = auxresume(L, co, lua_gettop(L) - 1); + if (r < 0) { + lua_pushboolean(L, 0); + lua_insert(L, -2); + return 2; /* return false + error message */ + } + else { + lua_pushboolean(L, 1); + lua_insert(L, -(r + 1)); + return r + 1; /* return true + 'resume' returns */ + } +} + + +static int luaB_auxwrap (lua_State *L) { + lua_State *co = lua_tothread(L, lua_upvalueindex(1)); + int r = auxresume(L, co, lua_gettop(L)); + if (r < 0) { + if (lua_type(L, -1) == LUA_TSTRING) { /* error object is a string? */ + luaL_where(L, 1); /* add extra info */ + lua_insert(L, -2); + lua_concat(L, 2); + } + return lua_error(L); /* propagate error */ + } + return r; +} + + +static int luaB_cocreate (lua_State *L) { + lua_State *NL; + luaL_checktype(L, 1, LUA_TFUNCTION); + NL = lua_newthread(L); + lua_pushvalue(L, 1); /* move function to top */ + lua_xmove(L, NL, 1); /* move function from L to NL */ + return 1; +} + + +static int luaB_cowrap (lua_State *L) { + luaB_cocreate(L); + lua_pushcclosure(L, luaB_auxwrap, 1); + return 1; +} + + +static int luaB_yield (lua_State *L) { + return lua_yield(L, lua_gettop(L)); +} + + +static int luaB_costatus (lua_State *L) { + lua_State *co = getco(L); + if (L == co) lua_pushliteral(L, "running"); + else { + switch (lua_status(co)) { + case LUA_YIELD: + lua_pushliteral(L, "suspended"); + break; + case LUA_OK: { + lua_Debug ar; + if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ + lua_pushliteral(L, "normal"); /* it is running */ + else if (lua_gettop(co) == 0) + lua_pushliteral(L, "dead"); + else + lua_pushliteral(L, "suspended"); /* initial state */ + break; + } + default: /* some error occurred */ + lua_pushliteral(L, "dead"); + break; + } + } + return 1; +} + + +static int luaB_yieldable (lua_State *L) { + lua_pushboolean(L, lua_isyieldable(L)); + return 1; +} + + +static int luaB_corunning (lua_State *L) { + int ismain = lua_pushthread(L); + lua_pushboolean(L, ismain); + return 2; +} + + +static const luaL_Reg co_funcs[] = { + {"create", luaB_cocreate}, + {"resume", luaB_coresume}, + {"running", luaB_corunning}, + {"status", luaB_costatus}, + {"wrap", luaB_cowrap}, + {"yield", luaB_yield}, + {"isyieldable", luaB_yieldable}, + {NULL, NULL} +}; + + + +LUAMOD_API int luaopen_coroutine (lua_State *L) { + luaL_newlib(L, co_funcs); + return 1; +} + diff --git a/app/src/main/jni/lua/lctype.c b/app/src/main/jni/lua/lctype.c new file mode 100644 index 0000000..ae9367e --- /dev/null +++ b/app/src/main/jni/lua/lctype.c @@ -0,0 +1,55 @@ +/* +** $Id: lctype.c,v 1.12 2014/11/02 19:19:04 roberto Exp $ +** 'ctype' functions for Lua +** See Copyright Notice in lua.h +*/ + +#define lctype_c +#define LUA_CORE + +#include "lprefix.h" + + +#include "lctype.h" + +#if !LUA_USE_CTYPE /* { */ + +#include + +LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = { + 0x00, /* EOZ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */ + 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */ + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */ + 0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */ + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */ + 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05, + 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */ + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */ + 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* e. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* f. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +#endif /* } */ diff --git a/app/src/main/jni/lua/lctype.h b/app/src/main/jni/lua/lctype.h new file mode 100644 index 0000000..99c7d12 --- /dev/null +++ b/app/src/main/jni/lua/lctype.h @@ -0,0 +1,95 @@ +/* +** $Id: lctype.h,v 1.12 2011/07/15 12:50:29 roberto Exp $ +** 'ctype' functions for Lua +** See Copyright Notice in lua.h +*/ + +#ifndef lctype_h +#define lctype_h + +#include "lua.h" + + +/* +** WARNING: the functions defined here do not necessarily correspond +** to the similar functions in the standard C ctype.h. They are +** optimized for the specific needs of Lua +*/ + +#if !defined(LUA_USE_CTYPE) + +#if 'A' == 65 && '0' == 48 +/* ASCII case: can use its own tables; faster and fixed */ +#define LUA_USE_CTYPE 0 +#else +/* must use standard C ctype */ +#define LUA_USE_CTYPE 1 +#endif + +#endif + + +#if !LUA_USE_CTYPE /* { */ + +#include + +#include "llimits.h" + + +#define ALPHABIT 0 +#define DIGITBIT 1 +#define PRINTBIT 2 +#define SPACEBIT 3 +#define XDIGITBIT 4 + + +#define MASK(B) (1 << (B)) + + +/* +** add 1 to char to allow index -1 (EOZ) +*/ +#define testprop(c,p) (luai_ctype_[(c)+1] & (p)) + +/* +** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_' +*/ +#define lislalpha(c) testprop(c, MASK(ALPHABIT)) +#define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT))) +#define lisdigit(c) testprop(c, MASK(DIGITBIT)) +#define lisspace(c) testprop(c, MASK(SPACEBIT)) +#define lisprint(c) testprop(c, MASK(PRINTBIT)) +#define lisxdigit(c) testprop(c, MASK(XDIGITBIT)) + +/* +** this 'ltolower' only works for alphabetic characters +*/ +#define ltolower(c) ((c) | ('A' ^ 'a')) + + +/* two more entries for 0 and -1 (EOZ) */ +LUAI_DDEC const lu_byte luai_ctype_[UCHAR_MAX + 2]; + + +#else /* }{ */ + +/* +** use standard C ctypes +*/ + +#include + + +#define lislalpha(c) (isalpha(c) || (c) == '_') +#define lislalnum(c) (isalnum(c) || (c) == '_') +#define lisdigit(c) (isdigit(c)) +#define lisspace(c) (isspace(c)) +#define lisprint(c) (isprint(c)) +#define lisxdigit(c) (isxdigit(c)) + +#define ltolower(c) (tolower(c)) + +#endif /* } */ + +#endif + diff --git a/app/src/main/jni/lua/ldblib.c b/app/src/main/jni/lua/ldblib.c index 2027eda..786f6cd 100644 --- a/app/src/main/jni/lua/ldblib.c +++ b/app/src/main/jni/lua/ldblib.c @@ -1,23 +1,42 @@ /* -** $Id: ldblib.c,v 1.104.1.4 2009/08/04 18:50:18 roberto Exp $ +** $Id: ldblib.c,v 1.151 2015/11/23 11:29:43 roberto Exp $ ** Interface from Lua to its debug API ** See Copyright Notice in lua.h */ +#define ldblib_c +#define LUA_LIB + +#include "lprefix.h" + #include #include #include -#define ldblib_c -#define LUA_LIB - #include "lua.h" #include "lauxlib.h" #include "lualib.h" +/* +** The hook table at registry[&HOOKKEY] maps threads to their current +** hook function. (We only need the unique address of 'HOOKKEY'.) +*/ +static const int HOOKKEY = 0; + + +/* +** If L1 != L, L1 can be in any state, and therefore there are no +** guarantees about its stack space; any push in L1 must be +** checked. +*/ +static void checkstack (lua_State *L, lua_State *L1, int n) { + if (L != L1 && !lua_checkstack(L1, n)) + luaL_error(L, "stack overflow"); +} + static int db_getregistry (lua_State *L) { lua_pushvalue(L, LUA_REGISTRYINDEX); @@ -39,40 +58,35 @@ static int db_setmetatable (lua_State *L) { luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table expected"); lua_settop(L, 2); - lua_pushboolean(L, lua_setmetatable(L, 1)); - return 1; + lua_setmetatable(L, 1); + return 1; /* return 1st argument */ } -static int db_getfenv (lua_State *L) { - luaL_checkany(L, 1); - lua_getfenv(L, 1); +static int db_getuservalue (lua_State *L) { + if (lua_type(L, 1) != LUA_TUSERDATA) + lua_pushnil(L); + else + lua_getuservalue(L, 1); return 1; } -static int db_setfenv (lua_State *L) { - luaL_checktype(L, 2, LUA_TTABLE); +static int db_setuservalue (lua_State *L) { + luaL_checktype(L, 1, LUA_TUSERDATA); + luaL_checkany(L, 2); lua_settop(L, 2); - if (lua_setfenv(L, 1) == 0) - luaL_error(L, LUA_QL("setfenv") - " cannot change environment of given object"); + lua_setuservalue(L, 1); return 1; } -static void settabss (lua_State *L, const char *i, const char *v) { - lua_pushstring(L, v); - lua_setfield(L, -2, i); -} - - -static void settabsi (lua_State *L, const char *i, int v) { - lua_pushinteger(L, v); - lua_setfield(L, -2, i); -} - - +/* +** Auxiliary function used by several library functions: check for +** an optional thread as function's first argument and set 'arg' with +** 1 if this argument is present (so that functions can skip it to +** access their other arguments) +*/ static lua_State *getthread (lua_State *L, int *arg) { if (lua_isthread(L, 1)) { *arg = 1; @@ -80,44 +94,74 @@ static lua_State *getthread (lua_State *L, int *arg) { } else { *arg = 0; - return L; + return L; /* function will operate over current thread */ } } +/* +** Variations of 'lua_settable', used by 'db_getinfo' to put results +** from 'lua_getinfo' into result table. Key is always a string; +** value can be a string, an int, or a boolean. +*/ +static void settabss (lua_State *L, const char *k, const char *v) { + lua_pushstring(L, v); + lua_setfield(L, -2, k); +} + +static void settabsi (lua_State *L, const char *k, int v) { + lua_pushinteger(L, v); + lua_setfield(L, -2, k); +} + +static void settabsb (lua_State *L, const char *k, int v) { + lua_pushboolean(L, v); + lua_setfield(L, -2, k); +} + + +/* +** In function 'db_getinfo', the call to 'lua_getinfo' may push +** results on the stack; later it creates the result table to put +** these objects. Function 'treatstackoption' puts the result from +** 'lua_getinfo' on top of the result table so that it can call +** 'lua_setfield'. +*/ static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { - if (L == L1) { - lua_pushvalue(L, -2); - lua_remove(L, -3); - } + if (L == L1) + lua_rotate(L, -2, 1); /* exchange object and table */ else - lua_xmove(L1, L, 1); - lua_setfield(L, -2, fname); + lua_xmove(L1, L, 1); /* move object to the "main" stack */ + lua_setfield(L, -2, fname); /* put object into table */ } +/* +** Calls 'lua_getinfo' and collects all results in a new table. +** L1 needs stack space for an optional input (function) plus +** two optional outputs (function and line table) from function +** 'lua_getinfo'. +*/ static int db_getinfo (lua_State *L) { lua_Debug ar; int arg; lua_State *L1 = getthread(L, &arg); - const char *options = luaL_optstring(L, arg+2, "flnSu"); - if (lua_isnumber(L, arg+1)) { - if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) { + const char *options = luaL_optstring(L, arg+2, "flnStu"); + checkstack(L, L1, 3); + if (lua_isfunction(L, arg + 1)) { /* info about a function? */ + options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */ + lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */ + lua_xmove(L, L1, 1); + } + else { /* stack level */ + if (!lua_getstack(L1, (int)luaL_checkinteger(L, arg + 1), &ar)) { lua_pushnil(L); /* level out of range */ return 1; } } - else if (lua_isfunction(L, arg+1)) { - lua_pushfstring(L, ">%s", options); - options = lua_tostring(L, -1); - lua_pushvalue(L, arg+1); - lua_xmove(L, L1, 1); - } - else - return luaL_argerror(L, arg+1, "function or level expected"); if (!lua_getinfo(L1, options, &ar)) return luaL_argerror(L, arg+2, "invalid option"); - lua_createtable(L, 0, 2); + lua_newtable(L); /* table to collect results */ if (strchr(options, 'S')) { settabss(L, "source", ar.source); settabss(L, "short_src", ar.short_src); @@ -127,64 +171,88 @@ static int db_getinfo (lua_State *L) { } if (strchr(options, 'l')) settabsi(L, "currentline", ar.currentline); - if (strchr(options, 'u')) + if (strchr(options, 'u')) { settabsi(L, "nups", ar.nups); + settabsi(L, "nparams", ar.nparams); + settabsb(L, "isvararg", ar.isvararg); + } if (strchr(options, 'n')) { settabss(L, "name", ar.name); settabss(L, "namewhat", ar.namewhat); } + if (strchr(options, 't')) + settabsb(L, "istailcall", ar.istailcall); if (strchr(options, 'L')) treatstackoption(L, L1, "activelines"); if (strchr(options, 'f')) treatstackoption(L, L1, "func"); return 1; /* return table */ } - + static int db_getlocal (lua_State *L) { int arg; lua_State *L1 = getthread(L, &arg); lua_Debug ar; const char *name; - if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ - return luaL_argerror(L, arg+1, "level out of range"); - name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2)); - if (name) { - lua_xmove(L1, L, 1); - lua_pushstring(L, name); - lua_pushvalue(L, -2); - return 2; + int nvar = (int)luaL_checkinteger(L, arg + 2); /* local-variable index */ + if (lua_isfunction(L, arg + 1)) { /* function argument? */ + lua_pushvalue(L, arg + 1); /* push function */ + lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */ + return 1; /* return only name (there is no value) */ } - else { - lua_pushnil(L); - return 1; + else { /* stack-level argument */ + int level = (int)luaL_checkinteger(L, arg + 1); + if (!lua_getstack(L1, level, &ar)) /* out of range? */ + return luaL_argerror(L, arg+1, "level out of range"); + checkstack(L, L1, 1); + name = lua_getlocal(L1, &ar, nvar); + if (name) { + lua_xmove(L1, L, 1); /* move local value */ + lua_pushstring(L, name); /* push name */ + lua_rotate(L, -2, 1); /* re-order */ + return 2; + } + else { + lua_pushnil(L); /* no name (nor value) */ + return 1; + } } } static int db_setlocal (lua_State *L) { int arg; + const char *name; lua_State *L1 = getthread(L, &arg); lua_Debug ar; - if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ + int level = (int)luaL_checkinteger(L, arg + 1); + int nvar = (int)luaL_checkinteger(L, arg + 2); + if (!lua_getstack(L1, level, &ar)) /* out of range? */ return luaL_argerror(L, arg+1, "level out of range"); luaL_checkany(L, arg+3); lua_settop(L, arg+3); + checkstack(L, L1, 1); lua_xmove(L, L1, 1); - lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2))); + name = lua_setlocal(L1, &ar, nvar); + if (name == NULL) + lua_pop(L1, 1); /* pop value (if not popped by 'lua_setlocal') */ + lua_pushstring(L, name); return 1; } +/* +** get (if 'get' is true) or set an upvalue from a closure +*/ static int auxupvalue (lua_State *L, int get) { const char *name; - int n = luaL_checkint(L, 2); - luaL_checktype(L, 1, LUA_TFUNCTION); - if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */ + int n = (int)luaL_checkinteger(L, 2); /* upvalue index */ + luaL_checktype(L, 1, LUA_TFUNCTION); /* closure */ name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); if (name == NULL) return 0; lua_pushstring(L, name); - lua_insert(L, -(get+1)); + lua_insert(L, -(get+1)); /* no-op if get is false */ return get + 1; } @@ -200,28 +268,59 @@ static int db_setupvalue (lua_State *L) { } +/* +** Check whether a given upvalue from a given closure exists and +** returns its index +*/ +static int checkupval (lua_State *L, int argf, int argnup) { + int nup = (int)luaL_checkinteger(L, argnup); /* upvalue index */ + luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */ + luaL_argcheck(L, (lua_getupvalue(L, argf, nup) != NULL), argnup, + "invalid upvalue index"); + return nup; +} + + +static int db_upvalueid (lua_State *L) { + int n = checkupval(L, 1, 2); + lua_pushlightuserdata(L, lua_upvalueid(L, 1, n)); + return 1; +} -static const char KEY_HOOK = 'h'; +static int db_upvaluejoin (lua_State *L) { + int n1 = checkupval(L, 1, 2); + int n2 = checkupval(L, 3, 4); + luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected"); + luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected"); + lua_upvaluejoin(L, 1, n1, 3, n2); + return 0; +} + +/* +** Call hook function registered at hook table for the current +** thread (if there is one) +*/ static void hookf (lua_State *L, lua_Debug *ar) { static const char *const hooknames[] = - {"call", "return", "line", "count", "tail return"}; - lua_pushlightuserdata(L, (void *)&KEY_HOOK); - lua_rawget(L, LUA_REGISTRYINDEX); - lua_pushlightuserdata(L, L); - lua_rawget(L, -2); - if (lua_isfunction(L, -1)) { - lua_pushstring(L, hooknames[(int)ar->event]); + {"call", "return", "line", "count", "tail call"}; + lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY); + lua_pushthread(L); + if (lua_rawget(L, -2) == LUA_TFUNCTION) { /* is there a hook function? */ + lua_pushstring(L, hooknames[(int)ar->event]); /* push event name */ if (ar->currentline >= 0) - lua_pushinteger(L, ar->currentline); + lua_pushinteger(L, ar->currentline); /* push current line */ else lua_pushnil(L); lua_assert(lua_getinfo(L, "lS", ar)); - lua_call(L, 2, 0); + lua_call(L, 2, 0); /* call hook function */ } } +/* +** Convert a string mask (for 'sethook') into a bit mask +*/ static int makemask (const char *smask, int count) { int mask = 0; if (strchr(smask, 'c')) mask |= LUA_MASKCALL; @@ -232,6 +331,9 @@ static int makemask (const char *smask, int count) { } +/* +** Convert a bit mask (for 'gethook') into a string mask +*/ static char *unmakemask (int mask, char *smask) { int i = 0; if (mask & LUA_MASKCALL) smask[i++] = 'c'; @@ -242,39 +344,34 @@ static char *unmakemask (int mask, char *smask) { } -static void gethooktable (lua_State *L) { - lua_pushlightuserdata(L, (void *)&KEY_HOOK); - lua_rawget(L, LUA_REGISTRYINDEX); - if (!lua_istable(L, -1)) { - lua_pop(L, 1); - lua_createtable(L, 0, 1); - lua_pushlightuserdata(L, (void *)&KEY_HOOK); - lua_pushvalue(L, -2); - lua_rawset(L, LUA_REGISTRYINDEX); - } -} - - static int db_sethook (lua_State *L) { int arg, mask, count; lua_Hook func; lua_State *L1 = getthread(L, &arg); - if (lua_isnoneornil(L, arg+1)) { + if (lua_isnoneornil(L, arg+1)) { /* no hook? */ lua_settop(L, arg+1); func = NULL; mask = 0; count = 0; /* turn off hooks */ } else { const char *smask = luaL_checkstring(L, arg+2); luaL_checktype(L, arg+1, LUA_TFUNCTION); - count = luaL_optint(L, arg+3, 0); + count = (int)luaL_optinteger(L, arg + 3, 0); func = hookf; mask = makemask(smask, count); } - gethooktable(L); - lua_pushlightuserdata(L, L1); - lua_pushvalue(L, arg+1); - lua_rawset(L, -3); /* set new hook */ - lua_pop(L, 1); /* remove hook table */ - lua_sethook(L1, func, mask, count); /* set hooks */ + if (lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY) == LUA_TNIL) { + lua_createtable(L, 0, 2); /* create a hook table */ + lua_pushvalue(L, -1); + lua_rawsetp(L, LUA_REGISTRYINDEX, &HOOKKEY); /* set it in position */ + lua_pushstring(L, "k"); + lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */ + lua_pushvalue(L, -1); + lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */ + } + checkstack(L, L1, 1); + lua_pushthread(L1); lua_xmove(L1, L, 1); /* key (thread) */ + lua_pushvalue(L, arg + 1); /* value (hook function) */ + lua_rawset(L, -3); /* hooktable[L1] = new Lua hook */ + lua_sethook(L1, func, mask, count); return 0; } @@ -285,16 +382,19 @@ static int db_gethook (lua_State *L) { char buff[5]; int mask = lua_gethookmask(L1); lua_Hook hook = lua_gethook(L1); - if (hook != NULL && hook != hookf) /* external hook? */ + if (hook == NULL) /* no hook? */ + lua_pushnil(L); + else if (hook != hookf) /* external hook? */ lua_pushliteral(L, "external hook"); - else { - gethooktable(L); - lua_pushlightuserdata(L, L1); - lua_rawget(L, -2); /* get hook */ + else { /* hook table must exist */ + lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY); + checkstack(L, L1, 1); + lua_pushthread(L1); lua_xmove(L1, L, 1); + lua_rawget(L, -2); /* 1st result = hooktable[L1] */ lua_remove(L, -2); /* remove hook table */ } - lua_pushstring(L, unmakemask(mask, buff)); - lua_pushinteger(L, lua_gethookcount(L1)); + lua_pushstring(L, unmakemask(mask, buff)); /* 2nd result = mask */ + lua_pushinteger(L, lua_gethookcount(L1)); /* 3rd result = count */ return 3; } @@ -302,97 +402,55 @@ static int db_gethook (lua_State *L) { static int db_debug (lua_State *L) { for (;;) { char buffer[250]; - fputs("lua_debug> ", stderr); + lua_writestringerror("%s", "lua_debug> "); if (fgets(buffer, sizeof(buffer), stdin) == 0 || strcmp(buffer, "cont\n") == 0) return 0; if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || - lua_pcall(L, 0, 0, 0)) { - fputs(lua_tostring(L, -1), stderr); - fputs("\n", stderr); - } + lua_pcall(L, 0, 0, 0)) + lua_writestringerror("%s\n", lua_tostring(L, -1)); lua_settop(L, 0); /* remove eventual returns */ } } -#define LEVELS1 12 /* size of the first part of the stack */ -#define LEVELS2 10 /* size of the second part of the stack */ - -static int db_errorfb (lua_State *L) { - int level; - int firstpart = 1; /* still before eventual `...' */ +static int db_traceback (lua_State *L) { int arg; lua_State *L1 = getthread(L, &arg); - lua_Debug ar; - if (lua_isnumber(L, arg+2)) { - level = (int)lua_tointeger(L, arg+2); - lua_pop(L, 1); - } - else - level = (L == L1) ? 1 : 0; /* level 0 may be this own function */ - if (lua_gettop(L) == arg) - lua_pushliteral(L, ""); - else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */ - else lua_pushliteral(L, "\n"); - lua_pushliteral(L, "stack traceback:"); - while (lua_getstack(L1, level++, &ar)) { - if (level > LEVELS1 && firstpart) { - /* no more than `LEVELS2' more levels? */ - if (!lua_getstack(L1, level+LEVELS2, &ar)) - level--; /* keep going */ - else { - lua_pushliteral(L, "\n\t..."); /* too many levels */ - while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */ - level++; - } - firstpart = 0; - continue; - } - lua_pushliteral(L, "\n\t"); - lua_getinfo(L1, "Snl", &ar); - lua_pushfstring(L, "%s:", ar.short_src); - if (ar.currentline > 0) - lua_pushfstring(L, "%d:", ar.currentline); - if (*ar.namewhat != '\0') /* is there a name? */ - lua_pushfstring(L, " in function " LUA_QS, ar.name); - else { - if (*ar.what == 'm') /* main? */ - lua_pushfstring(L, " in main chunk"); - else if (*ar.what == 'C' || *ar.what == 't') - lua_pushliteral(L, " ?"); /* C function or tail call */ - else - lua_pushfstring(L, " in function <%s:%d>", - ar.short_src, ar.linedefined); - } - lua_concat(L, lua_gettop(L) - arg); + const char *msg = lua_tostring(L, arg + 1); + if (msg == NULL && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */ + lua_pushvalue(L, arg + 1); /* return it untouched */ + else { + int level = (int)luaL_optinteger(L, arg + 2, (L == L1) ? 1 : 0); + luaL_traceback(L, L1, msg, level); } - lua_concat(L, lua_gettop(L) - arg); return 1; } static const luaL_Reg dblib[] = { {"debug", db_debug}, - {"getfenv", db_getfenv}, + {"getuservalue", db_getuservalue}, {"gethook", db_gethook}, {"getinfo", db_getinfo}, {"getlocal", db_getlocal}, {"getregistry", db_getregistry}, {"getmetatable", db_getmetatable}, {"getupvalue", db_getupvalue}, - {"setfenv", db_setfenv}, + {"upvaluejoin", db_upvaluejoin}, + {"upvalueid", db_upvalueid}, + {"setuservalue", db_setuservalue}, {"sethook", db_sethook}, {"setlocal", db_setlocal}, {"setmetatable", db_setmetatable}, {"setupvalue", db_setupvalue}, - {"traceback", db_errorfb}, + {"traceback", db_traceback}, {NULL, NULL} }; -LUALIB_API int luaopen_debug (lua_State *L) { - luaL_register(L, LUA_DBLIBNAME, dblib); +LUAMOD_API int luaopen_debug (lua_State *L) { + luaL_newlib(L, dblib); return 1; } diff --git a/app/src/main/jni/lua/ldebug.c b/app/src/main/jni/lua/ldebug.c index 50ad3d3..e499ee3 100644 --- a/app/src/main/jni/lua/ldebug.c +++ b/app/src/main/jni/lua/ldebug.c @@ -1,18 +1,19 @@ /* -** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $ +** $Id: ldebug.c,v 2.120 2016/03/31 19:01:21 roberto Exp $ ** Debug Interface ** See Copyright Notice in lua.h */ +#define ldebug_c +#define LUA_CORE + +#include "lprefix.h" + #include #include #include - -#define ldebug_c -#define LUA_CORE - #include "lua.h" #include "lapi.h" @@ -30,39 +31,63 @@ +#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_TCCL) + + +/* Active Lua function (given call info) */ +#define ci_func(ci) (clLvalue((ci)->func)) + + static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); -static int currentpc (lua_State *L, CallInfo *ci) { - if (!isLua(ci)) return -1; /* function is not a Lua function? */ - if (ci == L->ci) - ci->savedpc = L->savedpc; - return pcRel(ci->savedpc, ci_func(ci)->l.p); +static int currentpc (CallInfo *ci) { + lua_assert(isLua(ci)); + return pcRel(ci->u.l.savedpc, ci_func(ci)->p); } -static int currentline (lua_State *L, CallInfo *ci) { - int pc = currentpc(L, ci); - if (pc < 0) - return -1; /* only active lua functions have current-line information */ - else - return getline(ci_func(ci)->l.p, pc); +static int currentline (CallInfo *ci) { + return getfuncline(ci_func(ci)->p, currentpc(ci)); +} + + +/* +** If function yielded, its 'func' can be in the 'extra' field. The +** next function restores 'func' to its correct value for debugging +** purposes. (It exchanges 'func' and 'extra'; so, when called again, +** after debugging, it also "re-restores" ** 'func' to its altered value. +*/ +static void swapextra (lua_State *L) { + if (L->status == LUA_YIELD) { + CallInfo *ci = L->ci; /* get function that yielded */ + StkId temp = ci->func; /* exchange its 'func' and 'extra' values */ + ci->func = restorestack(L, ci->extra); + ci->extra = savestack(L, temp); + } } /* -** this function can be called asynchronous (e.g. during a signal) +** This function can be called asynchronously (e.g. during a signal). +** Fields 'oldpc', 'basehookcount', and 'hookcount' (set by +** 'resethookcount') are for debug only, and it is no problem if they +** get arbitrary values (causes at most one wrong hook call). 'hookmask' +** is an atomic value. We assume that pointers are atomic too (e.g., gcc +** ensures that for all platforms where it runs). Moreover, 'hook' is +** always checked before being called (see 'luaD_hook'). */ -LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { +LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { if (func == NULL || mask == 0) { /* turn off hooks? */ mask = 0; func = NULL; } + if (isLua(L->ci)) + L->oldpc = L->ci->u.l.savedpc; L->hook = func; L->basehookcount = count; resethookcount(L); L->hookmask = cast_byte(mask); - return 1; } @@ -84,19 +109,13 @@ LUA_API int lua_gethookcount (lua_State *L) { LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { int status; CallInfo *ci; + if (level < 0) return 0; /* invalid (negative) level */ lua_lock(L); - for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { + for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous) level--; - if (f_isLua(ci)) /* Lua function? */ - level -= ci->tailcalls; /* skip lost tail calls */ - } - if (level == 0 && ci > L->base_ci) { /* level found? */ + if (level == 0 && ci != &L->base_ci) { /* level found? */ status = 1; - ar->i_ci = cast_int(ci - L->base_ci); - } - else if (level < 0) { /* level is of a lost tail call? */ - status = 1; - ar->i_ci = 0; + ar->i_ci = ci; } else status = 0; /* no such level */ lua_unlock(L); @@ -104,99 +123,130 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { } -static Proto *getluaproto (CallInfo *ci) { - return (isLua(ci) ? ci_func(ci)->l.p : NULL); +static const char *upvalname (Proto *p, int uv) { + TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name); + if (s == NULL) return "?"; + else return getstr(s); } -static const char *findlocal (lua_State *L, CallInfo *ci, int n) { - const char *name; - Proto *fp = getluaproto(ci); - if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL) - return name; /* is a local variable in a Lua function */ +static const char *findvararg (CallInfo *ci, int n, StkId *pos) { + int nparams = clLvalue(ci->func)->p->numparams; + if (n >= cast_int(ci->u.l.base - ci->func) - nparams) + return NULL; /* no such vararg */ else { - StkId limit = (ci == L->ci) ? L->top : (ci+1)->func; - if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */ - return "(*temporary)"; + *pos = ci->func + nparams + n; + return "(*vararg)"; /* generic name for any vararg */ + } +} + + +static const char *findlocal (lua_State *L, CallInfo *ci, int n, + StkId *pos) { + const char *name = NULL; + StkId base; + if (isLua(ci)) { + if (n < 0) /* access to vararg values? */ + return findvararg(ci, -n, pos); + else { + base = ci->u.l.base; + name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); + } + } + else + base = ci->func + 1; + if (name == NULL) { /* no 'standard' name? */ + StkId limit = (ci == L->ci) ? L->top : ci->next->func; + if (limit - base >= n && n > 0) /* is 'n' inside 'ci' stack? */ + name = "(*temporary)"; /* generic name for any valid slot */ else - return NULL; + return NULL; /* no name */ } + *pos = base + (n - 1); + return name; } LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { - CallInfo *ci = L->base_ci + ar->i_ci; - const char *name = findlocal(L, ci, n); + const char *name; lua_lock(L); - if (name) - luaA_pushobject(L, ci->base + (n - 1)); + swapextra(L); + if (ar == NULL) { /* information about non-active function? */ + if (!isLfunction(L->top - 1)) /* not a Lua function? */ + name = NULL; + else /* consider live variables at function start (parameters) */ + name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0); + } + else { /* active function; get information through 'ar' */ + StkId pos = NULL; /* to avoid warnings */ + name = findlocal(L, ar->i_ci, n, &pos); + if (name) { + setobj2s(L, L->top, pos); + api_incr_top(L); + } + } + swapextra(L); lua_unlock(L); return name; } LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { - CallInfo *ci = L->base_ci + ar->i_ci; - const char *name = findlocal(L, ci, n); + StkId pos = NULL; /* to avoid warnings */ + const char *name; lua_lock(L); - if (name) - setobjs2s(L, ci->base + (n - 1), L->top - 1); - L->top--; /* pop value */ + swapextra(L); + name = findlocal(L, ar->i_ci, n, &pos); + if (name) { + setobjs2s(L, pos, L->top - 1); + L->top--; /* pop value */ + } + swapextra(L); lua_unlock(L); return name; } static void funcinfo (lua_Debug *ar, Closure *cl) { - if (cl->c.isC) { + if (noLuaClosure(cl)) { ar->source = "=[C]"; ar->linedefined = -1; ar->lastlinedefined = -1; ar->what = "C"; } else { - ar->source = getstr(cl->l.p->source); - ar->linedefined = cl->l.p->linedefined; - ar->lastlinedefined = cl->l.p->lastlinedefined; + Proto *p = cl->l.p; + ar->source = p->source ? getstr(p->source) : "=?"; + ar->linedefined = p->linedefined; + ar->lastlinedefined = p->lastlinedefined; ar->what = (ar->linedefined == 0) ? "main" : "Lua"; } luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); } -static void info_tailcall (lua_Debug *ar) { - ar->name = ar->namewhat = ""; - ar->what = "tail"; - ar->lastlinedefined = ar->linedefined = ar->currentline = -1; - ar->source = "=(tail call)"; - luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); - ar->nups = 0; -} - - static void collectvalidlines (lua_State *L, Closure *f) { - if (f == NULL || f->c.isC) { + if (noLuaClosure(f)) { setnilvalue(L->top); + api_incr_top(L); } else { - Table *t = luaH_new(L, 0, 0); - int *lineinfo = f->l.p->lineinfo; int i; - for (i=0; il.p->sizelineinfo; i++) - setbvalue(luaH_setnum(L, t, lineinfo[i]), 1); - sethvalue(L, L->top, t); + TValue v; + int *lineinfo = f->l.p->lineinfo; + Table *t = luaH_new(L); /* new table to store active lines */ + sethvalue(L, L->top, t); /* push it on stack */ + api_incr_top(L); + setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */ + for (i = 0; i < f->l.p->sizelineinfo; i++) /* for all lines with code */ + luaH_setint(L, t, lineinfo[i], &v); /* table[line] = true */ } - incr_top(L); } static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, - Closure *f, CallInfo *ci) { + Closure *f, CallInfo *ci) { int status = 1; - if (f == NULL) { - info_tailcall(ar); - return status; - } for (; *what; what++) { switch (*what) { case 'S': { @@ -204,15 +254,31 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, break; } case 'l': { - ar->currentline = (ci) ? currentline(L, ci) : -1; + ar->currentline = (ci && isLua(ci)) ? currentline(ci) : -1; break; } case 'u': { - ar->nups = f->c.nupvalues; + ar->nups = (f == NULL) ? 0 : f->c.nupvalues; + if (noLuaClosure(f)) { + ar->isvararg = 1; + ar->nparams = 0; + } + else { + ar->isvararg = f->l.p->is_vararg; + ar->nparams = f->l.p->numparams; + } + break; + } + case 't': { + ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0; break; } case 'n': { - ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL; + /* calling function is a known Lua function? */ + if (ci && !(ci->callstatus & CIST_TAIL) && isLua(ci->previous)) + ar->namewhat = getfuncname(L, ci->previous, &ar->name); + else + ar->namewhat = NULL; if (ar->namewhat == NULL) { ar->namewhat = ""; /* not found */ ar->name = NULL; @@ -231,29 +297,32 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { int status; - Closure *f = NULL; - CallInfo *ci = NULL; + Closure *cl; + CallInfo *ci; + StkId func; lua_lock(L); + swapextra(L); if (*what == '>') { - StkId func = L->top - 1; - luai_apicheck(L, ttisfunction(func)); + ci = NULL; + func = L->top - 1; + api_check(L, ttisfunction(func), "function expected"); what++; /* skip the '>' */ - f = clvalue(func); L->top--; /* pop function */ } - else if (ar->i_ci != 0) { /* no tail call? */ - ci = L->base_ci + ar->i_ci; + else { + ci = ar->i_ci; + func = ci->func; lua_assert(ttisfunction(ci->func)); - f = clvalue(ci->func); } - status = auxgetinfo(L, what, ar, f, ci); + cl = ttisclosure(func) ? clvalue(func) : NULL; + status = auxgetinfo(L, what, ar, cl, ci); if (strchr(what, 'f')) { - if (f == NULL) setnilvalue(L->top); - else setclvalue(L, L->top, f); - incr_top(L); + setobjs2s(L, L->top, func); + api_incr_top(L); } + swapextra(L); /* correct before option 'L', which can raise a mem. error */ if (strchr(what, 'L')) - collectvalidlines(L, f); + collectvalidlines(L, cl); lua_unlock(L); return status; } @@ -261,378 +330,350 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { /* ** {====================================================== -** Symbolic Execution and code checker +** Symbolic Execution ** ======================================================= */ -#define check(x) if (!(x)) return 0; +static const char *getobjname (Proto *p, int lastpc, int reg, + const char **name); -#define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode) -#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) - - - -static int precheck (const Proto *pt) { - check(pt->maxstacksize <= MAXSTACK); - check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize); - check(!(pt->is_vararg & VARARG_NEEDSARG) || - (pt->is_vararg & VARARG_HASARG)); - check(pt->sizeupvalues <= pt->nups); - check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0); - check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); - return 1; -} - - -#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1]) - -int luaG_checkopenop (Instruction i) { - switch (GET_OPCODE(i)) { - case OP_CALL: - case OP_TAILCALL: - case OP_RETURN: - case OP_SETLIST: { - check(GETARG_B(i) == 0); - return 1; +/* +** find a "name" for the RK value 'c' +*/ +static void kname (Proto *p, int pc, int c, const char **name) { + if (ISK(c)) { /* is 'c' a constant? */ + TValue *kvalue = &p->k[INDEXK(c)]; + if (ttisstring(kvalue)) { /* literal constant? */ + *name = svalue(kvalue); /* it is its own name */ + return; + } + /* else no reasonable name found */ + } + else { /* 'c' is a register */ + const char *what = getobjname(p, pc, c, name); /* search for 'c' */ + if (what && *what == 'c') { /* found a constant name? */ + return; /* 'name' already filled */ } - default: return 0; /* invalid instruction after an open call */ + /* else no reasonable name found */ } + *name = "?"; /* no reasonable name found */ } -static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) { - switch (mode) { - case OpArgN: check(r == 0); break; - case OpArgU: break; - case OpArgR: checkreg(pt, r); break; - case OpArgK: - check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize); - break; - } - return 1; +static int filterpc (int pc, int jmptarget) { + if (pc < jmptarget) /* is code conditional (inside a jump)? */ + return -1; /* cannot know who sets that register */ + else return pc; /* current position sets that register */ } -static Instruction symbexec (const Proto *pt, int lastpc, int reg) { +/* +** try to find last instruction before 'lastpc' that modified register 'reg' +*/ +static int findsetreg (Proto *p, int lastpc, int reg) { int pc; - int last; /* stores position of last instruction that changed `reg' */ - last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ - check(precheck(pt)); + int setreg = -1; /* keep last instruction that changed 'reg' */ + int jmptarget = 0; /* any code before this address is conditional */ for (pc = 0; pc < lastpc; pc++) { - Instruction i = pt->code[pc]; + Instruction i = p->code[pc]; OpCode op = GET_OPCODE(i); int a = GETARG_A(i); - int b = 0; - int c = 0; - check(op < NUM_OPCODES); - checkreg(pt, a); - switch (getOpMode(op)) { - case iABC: { - b = GETARG_B(i); - c = GETARG_C(i); - check(checkArgMode(pt, b, getBMode(op))); - check(checkArgMode(pt, c, getCMode(op))); - break; - } - case iABx: { - b = GETARG_Bx(i); - if (getBMode(op) == OpArgK) check(b < pt->sizek); - break; - } - case iAsBx: { - b = GETARG_sBx(i); - if (getBMode(op) == OpArgR) { - int dest = pc+1+b; - check(0 <= dest && dest < pt->sizecode); - if (dest > 0) { - int j; - /* check that it does not jump to a setlist count; this - is tricky, because the count from a previous setlist may - have the same value of an invalid setlist; so, we must - go all the way back to the first of them (if any) */ - for (j = 0; j < dest; j++) { - Instruction d = pt->code[dest-1-j]; - if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break; - } - /* if 'j' is even, previous value is not a setlist (even if - it looks like one) */ - check((j&1) == 0); - } - } - break; - } - } - if (testAMode(op)) { - if (a == reg) last = pc; /* change register `a' */ - } - if (testTMode(op)) { - check(pc+2 < pt->sizecode); /* check skip */ - check(GET_OPCODE(pt->code[pc+1]) == OP_JMP); - } switch (op) { - case OP_LOADBOOL: { - if (c == 1) { /* does it jump? */ - check(pc+2 < pt->sizecode); /* check its jump */ - check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST || - GETARG_C(pt->code[pc+1]) != 0); - } - break; - } case OP_LOADNIL: { - if (a <= reg && reg <= b) - last = pc; /* set registers from `a' to `b' */ + int b = GETARG_B(i); + if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */ + setreg = filterpc(pc, jmptarget); break; } - case OP_GETUPVAL: - case OP_SETUPVAL: { - check(b < pt->nups); - break; - } - case OP_GETGLOBAL: - case OP_SETGLOBAL: { - check(ttisstring(&pt->k[b])); - break; - } - case OP_SELF: { - checkreg(pt, a+1); - if (reg == a+1) last = pc; - break; - } - case OP_CONCAT: { - check(b < c); /* at least two operands */ - break; - } - case OP_TFORLOOP: { - check(c >= 1); /* at least one result (control variable) */ - checkreg(pt, a+2+c); /* space for results */ - if (reg >= a+2) last = pc; /* affect all regs above its base */ - break; - } - case OP_FORLOOP: - case OP_FORPREP: - checkreg(pt, a+3); - /* go through */ - case OP_JMP: { - int dest = pc+1+b; - /* not full check and jump is forward and do not skip `lastpc'? */ - if (reg != NO_REG && pc < dest && dest <= lastpc) - pc += b; /* do the jump */ + case OP_TFORCALL: { + if (reg >= a + 2) /* affect all regs above its base */ + setreg = filterpc(pc, jmptarget); break; } case OP_CALL: case OP_TAILCALL: { - if (b != 0) { - checkreg(pt, a+b-1); - } - c--; /* c = num. returns */ - if (c == LUA_MULTRET) { - check(checkopenop(pt, pc)); - } - else if (c != 0) - checkreg(pt, a+c-1); - if (reg >= a) last = pc; /* affect all registers above base */ - break; - } - case OP_RETURN: { - b--; /* b = num. returns */ - if (b > 0) checkreg(pt, a+b-1); + if (reg >= a) /* affect all registers above base */ + setreg = filterpc(pc, jmptarget); break; } - case OP_SETLIST: { - if (b > 0) checkreg(pt, a + b); - if (c == 0) { - pc++; - check(pc < pt->sizecode - 1); - } - break; - } - case OP_CLOSURE: { - int nup, j; - check(b < pt->sizep); - nup = pt->p[b]->nups; - check(pc + nup < pt->sizecode); - for (j = 1; j <= nup; j++) { - OpCode op1 = GET_OPCODE(pt->code[pc + j]); - check(op1 == OP_GETUPVAL || op1 == OP_MOVE); + case OP_JMP: { + int b = GETARG_sBx(i); + int dest = pc + 1 + b; + /* jump is forward and do not skip 'lastpc'? */ + if (pc < dest && dest <= lastpc) { + if (dest > jmptarget) + jmptarget = dest; /* update 'jmptarget' */ } - if (reg != NO_REG) /* tracing? */ - pc += nup; /* do not 'execute' these pseudo-instructions */ break; } - case OP_VARARG: { - check((pt->is_vararg & VARARG_ISVARARG) && - !(pt->is_vararg & VARARG_NEEDSARG)); - b--; - if (b == LUA_MULTRET) check(checkopenop(pt, pc)); - checkreg(pt, a+b-1); + default: + if (testAMode(op) && reg == a) /* any instruction that set A */ + setreg = filterpc(pc, jmptarget); break; - } - default: break; } } - return pt->code[last]; + return setreg; } -#undef check -#undef checkjump -#undef checkreg -/* }====================================================== */ - - -int luaG_checkcode (const Proto *pt) { - return (symbexec(pt, pt->sizecode, NO_REG) != 0); -} - - -static const char *kname (Proto *p, int c) { - if (ISK(c) && ttisstring(&p->k[INDEXK(c)])) - return svalue(&p->k[INDEXK(c)]); - else - return "?"; -} - - -static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos, +static const char *getobjname (Proto *p, int lastpc, int reg, const char **name) { - if (isLua(ci)) { /* a Lua function? */ - Proto *p = ci_func(ci)->l.p; - int pc = currentpc(L, ci); - Instruction i; - *name = luaF_getlocalname(p, stackpos+1, pc); - if (*name) /* is a local? */ - return "local"; - i = symbexec(p, pc, stackpos); /* try symbolic execution */ - lua_assert(pc != -1); - switch (GET_OPCODE(i)) { - case OP_GETGLOBAL: { - int g = GETARG_Bx(i); /* global index */ - lua_assert(ttisstring(&p->k[g])); - *name = svalue(&p->k[g]); - return "global"; - } + int pc; + *name = luaF_getlocalname(p, reg + 1, lastpc); + if (*name) /* is a local? */ + return "local"; + /* else try symbolic execution */ + pc = findsetreg(p, lastpc, reg); + if (pc != -1) { /* could find instruction? */ + Instruction i = p->code[pc]; + OpCode op = GET_OPCODE(i); + switch (op) { case OP_MOVE: { - int a = GETARG_A(i); - int b = GETARG_B(i); /* move from `b' to `a' */ - if (b < a) - return getobjname(L, ci, b, name); /* get name for `b' */ + int b = GETARG_B(i); /* move from 'b' to 'a' */ + if (b < GETARG_A(i)) + return getobjname(p, pc, b, name); /* get name for 'b' */ break; } + case OP_GETTABUP: case OP_GETTABLE: { int k = GETARG_C(i); /* key index */ - *name = kname(p, k); - return "field"; + int t = GETARG_B(i); /* table index */ + const char *vn = (op == OP_GETTABLE) /* name of indexed variable */ + ? luaF_getlocalname(p, t + 1, pc) + : upvalname(p, t); + kname(p, pc, k, name); + return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field"; } case OP_GETUPVAL: { - int u = GETARG_B(i); /* upvalue index */ - *name = p->upvalues ? getstr(p->upvalues[u]) : "?"; + *name = upvalname(p, GETARG_B(i)); return "upvalue"; } + case OP_LOADK: + case OP_LOADKX: { + int b = (op == OP_LOADK) ? GETARG_Bx(i) + : GETARG_Ax(p->code[pc + 1]); + if (ttisstring(&p->k[b])) { + *name = svalue(&p->k[b]); + return "constant"; + } + break; + } case OP_SELF: { int k = GETARG_C(i); /* key index */ - *name = kname(p, k); + kname(p, pc, k, name); return "method"; } - default: break; + default: break; /* go through to return NULL */ } } - return NULL; /* no useful name found */ + return NULL; /* could not find reasonable name */ } static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { - Instruction i; - if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1)) - return NULL; /* calling function is not Lua (or is unknown) */ - ci--; /* calling function */ - i = ci_func(ci)->l.p->code[currentpc(L, ci)]; - if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || - GET_OPCODE(i) == OP_TFORLOOP) - return getobjname(L, ci, GETARG_A(i), name); - else - return NULL; /* no useful name can be found */ + TMS tm = (TMS)0; /* to avoid warnings */ + Proto *p = ci_func(ci)->p; /* calling function */ + int pc = currentpc(ci); /* calling instruction index */ + Instruction i = p->code[pc]; /* calling instruction */ + if (ci->callstatus & CIST_HOOKED) { /* was it called inside a hook? */ + *name = "?"; + return "hook"; + } + switch (GET_OPCODE(i)) { + case OP_CALL: + case OP_TAILCALL: /* get function name */ + return getobjname(p, pc, GETARG_A(i), name); + case OP_TFORCALL: { /* for iterator */ + *name = "for iterator"; + return "for iterator"; + } + /* all other instructions can call only through metamethods */ + case OP_SELF: case OP_GETTABUP: case OP_GETTABLE: + tm = TM_INDEX; + break; + case OP_SETTABUP: case OP_SETTABLE: + tm = TM_NEWINDEX; + break; + case OP_ADD: case OP_SUB: case OP_MUL: case OP_MOD: + case OP_POW: case OP_DIV: case OP_IDIV: case OP_BAND: + case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: { + int offset = cast_int(GET_OPCODE(i)) - cast_int(OP_ADD); /* ORDER OP */ + tm = cast(TMS, offset + cast_int(TM_ADD)); /* ORDER TM */ + break; + } + case OP_UNM: tm = TM_UNM; break; + case OP_BNOT: tm = TM_BNOT; break; + case OP_LEN: tm = TM_LEN; break; + case OP_CONCAT: tm = TM_CONCAT; break; + case OP_EQ: tm = TM_EQ; break; + case OP_LT: tm = TM_LT; break; + case OP_LE: tm = TM_LE; break; + default: lua_assert(0); /* other instructions cannot call a function */ + } + *name = getstr(G(L)->tmname[tm]); + return "metamethod"; } +/* }====================================================== */ + + -/* only ANSI way to check whether a pointer points to an array */ +/* +** The subtraction of two potentially unrelated pointers is +** not ISO C, but it should not crash a program; the subsequent +** checks are ISO C and ensure a correct result. +*/ static int isinstack (CallInfo *ci, const TValue *o) { - StkId p; - for (p = ci->base; p < ci->top; p++) - if (o == p) return 1; - return 0; + ptrdiff_t i = o - ci->u.l.base; + return (0 <= i && i < (ci->top - ci->u.l.base) && ci->u.l.base + i == o); } -void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { - const char *name = NULL; - const char *t = luaT_typenames[ttype(o)]; - const char *kind = (isinstack(L->ci, o)) ? - getobjname(L, L->ci, cast_int(o - L->base), &name) : - NULL; - if (kind) - luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", - op, kind, name, t); - else - luaG_runerror(L, "attempt to %s a %s value", op, t); +/* +** Checks whether value 'o' came from an upvalue. (That can only happen +** with instructions OP_GETTABUP/OP_SETTABUP, which operate directly on +** upvalues.) +*/ +static const char *getupvalname (CallInfo *ci, const TValue *o, + const char **name) { + LClosure *c = ci_func(ci); + int i; + for (i = 0; i < c->nupvalues; i++) { + if (c->upvals[i]->v == o) { + *name = upvalname(c->p, i); + return "upvalue"; + } + } + return NULL; +} + + +static const char *varinfo (lua_State *L, const TValue *o) { + const char *name = NULL; /* to avoid warnings */ + CallInfo *ci = L->ci; + const char *kind = NULL; + if (isLua(ci)) { + kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ + if (!kind && isinstack(ci, o)) /* no? try a register */ + kind = getobjname(ci_func(ci)->p, currentpc(ci), + cast_int(o - ci->u.l.base), &name); + } + return (kind) ? luaO_pushfstring(L, " (%s '%s')", kind, name) : ""; +} + + +l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { + const char *t = luaT_objtypename(L, o); + luaG_runerror(L, "attempt to %s a %s value%s", op, t, varinfo(L, o)); } -void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { - if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; - lua_assert(!ttisstring(p1) && !ttisnumber(p1)); +l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) { + if (ttisstring(p1) || cvt2str(p1)) p1 = p2; luaG_typeerror(L, p1, "concatenate"); } -void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { - TValue temp; - if (luaV_tonumber(p1, &temp) == NULL) - p2 = p1; /* first operand is wrong */ - luaG_typeerror(L, p2, "perform arithmetic on"); +l_noret luaG_opinterror (lua_State *L, const TValue *p1, + const TValue *p2, const char *msg) { + lua_Number temp; + if (!tonumber(p1, &temp)) /* first operand is wrong? */ + p2 = p1; /* now second is wrong */ + luaG_typeerror(L, p2, msg); +} + + +/* +** Error when both values are convertible to numbers, but not to integers +*/ +l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) { + lua_Integer temp; + if (!tointeger(p1, &temp)) + p2 = p1; + luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2)); } -int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { - const char *t1 = luaT_typenames[ttype(p1)]; - const char *t2 = luaT_typenames[ttype(p2)]; - if (t1[2] == t2[2]) +l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { + const char *t1 = luaT_objtypename(L, p1); + const char *t2 = luaT_objtypename(L, p2); + if (strcmp(t1, t2) == 0) luaG_runerror(L, "attempt to compare two %s values", t1); else luaG_runerror(L, "attempt to compare %s with %s", t1, t2); - return 0; } -static void addinfo (lua_State *L, const char *msg) { - CallInfo *ci = L->ci; - if (isLua(ci)) { /* is Lua code? */ - char buff[LUA_IDSIZE]; /* add file:line information */ - int line = currentline(L, ci); - luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE); - luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); +/* add src:line information to 'msg' */ +const char *luaG_addinfo (lua_State *L, const char *msg, TString *src, + int line) { + char buff[LUA_IDSIZE]; + if (src) + luaO_chunkid(buff, getstr(src), LUA_IDSIZE); + else { /* no source available; use "?" instead */ + buff[0] = '?'; buff[1] = '\0'; } + return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); } -void luaG_errormsg (lua_State *L) { +l_noret luaG_errormsg (lua_State *L) { if (L->errfunc != 0) { /* is there an error handling function? */ StkId errfunc = restorestack(L, L->errfunc); - if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); setobjs2s(L, L->top, L->top - 1); /* move argument */ setobjs2s(L, L->top - 1, errfunc); /* push function */ - incr_top(L); - luaD_call(L, L->top - 2, 1); /* call it */ + L->top++; /* assume EXTRA_STACK */ + luaD_callnoyield(L, L->top - 2, 1); /* call it */ } luaD_throw(L, LUA_ERRRUN); } -void luaG_runerror (lua_State *L, const char *fmt, ...) { +l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { + CallInfo *ci = L->ci; + const char *msg; va_list argp; va_start(argp, fmt); - addinfo(L, luaO_pushvfstring(L, fmt, argp)); + msg = luaO_pushvfstring(L, fmt, argp); /* format message */ va_end(argp); + if (isLua(ci)) /* if Lua function, add source:line information */ + luaG_addinfo(L, msg, ci_func(ci)->p->source, currentline(ci)); luaG_errormsg(L); } + +void luaG_traceexec (lua_State *L) { + CallInfo *ci = L->ci; + lu_byte mask = L->hookmask; + int counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT)); + if (counthook) + resethookcount(L); /* reset count */ + else if (!(mask & LUA_MASKLINE)) + return; /* no line hook and count != 0; nothing to be done */ + if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */ + ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ + return; /* do not call hook again (VM yielded, so it did not move) */ + } + if (counthook) + luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */ + if (mask & LUA_MASKLINE) { + Proto *p = ci_func(ci)->p; + int npc = pcRel(ci->u.l.savedpc, p); + int newline = getfuncline(p, npc); + if (npc == 0 || /* call linehook when enter a new function, */ + ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */ + newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */ + luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */ + } + L->oldpc = ci->u.l.savedpc; + if (L->status == LUA_YIELD) { /* did hook yield? */ + if (counthook) + L->hookcount = 1; /* undo decrement to zero */ + ci->u.l.savedpc--; /* undo increment (resume will increment it again) */ + ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ + ci->func = L->top - 1; /* protect stack below results */ + luaD_throw(L, LUA_YIELD); + } +} + diff --git a/app/src/main/jni/lua/ldebug.h b/app/src/main/jni/lua/ldebug.h index ba28a97..0e31546 100644 --- a/app/src/main/jni/lua/ldebug.h +++ b/app/src/main/jni/lua/ldebug.h @@ -1,5 +1,5 @@ /* -** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: ldebug.h,v 2.14 2015/05/22 17:45:56 roberto Exp $ ** Auxiliary functions from Debug Interface module ** See Copyright Notice in lua.h */ @@ -13,21 +13,27 @@ #define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) -#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) +#define getfuncline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : -1) #define resethookcount(L) (L->hookcount = L->basehookcount) -LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o, - const char *opname); -LUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2); -LUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1, - const TValue *p2); -LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1, - const TValue *p2); -LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...); -LUAI_FUNC void luaG_errormsg (lua_State *L); -LUAI_FUNC int luaG_checkcode (const Proto *pt); -LUAI_FUNC int luaG_checkopenop (Instruction i); +LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, + const char *opname); +LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC l_noret luaG_opinterror (lua_State *L, const TValue *p1, + const TValue *p2, + const char *msg); +LUAI_FUNC l_noret luaG_tointerror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...); +LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg, + TString *src, int line); +LUAI_FUNC l_noret luaG_errormsg (lua_State *L); +LUAI_FUNC void luaG_traceexec (lua_State *L); + #endif diff --git a/app/src/main/jni/lua/ldo.c b/app/src/main/jni/lua/ldo.c index d1bf786..8804c99 100644 --- a/app/src/main/jni/lua/ldo.c +++ b/app/src/main/jni/lua/ldo.c @@ -1,19 +1,22 @@ /* -** $Id: ldo.c,v 2.38.1.4 2012/01/18 02:27:10 roberto Exp $ +** $Id: ldo.c,v 2.151 2015/12/16 16:40:07 roberto Exp $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ +#define ldo_c +#define LUA_CORE + +#include "lprefix.h" + #include #include #include -#define ldo_c -#define LUA_CORE - #include "lua.h" +#include "lapi.h" #include "ldebug.h" #include "ldo.h" #include "lfunc.h" @@ -32,6 +35,8 @@ +#define errorstatus(s) ((s) > LUA_YIELD) + /* ** {====================================================== @@ -39,6 +44,41 @@ ** ======================================================= */ +/* +** LUAI_THROW/LUAI_TRY define how Lua does exception handling. By +** default, Lua handles errors with exceptions when compiling as +** C++ code, with _longjmp/_setjmp when asked to use them, and with +** longjmp/setjmp otherwise. +*/ +#if !defined(LUAI_THROW) /* { */ + +#if defined(__cplusplus) && !defined(LUA_USE_LONGJMP) /* { */ + +/* C++ exceptions */ +#define LUAI_THROW(L,c) throw(c) +#define LUAI_TRY(L,c,a) \ + try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; } +#define luai_jmpbuf int /* dummy variable */ + +#elif defined(LUA_USE_POSIX) /* }{ */ + +/* in POSIX, try _longjmp/_setjmp (more efficient) */ +#define LUAI_THROW(L,c) _longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf + +#else /* }{ */ + +/* ISO C handling with long jumps */ +#define LUAI_THROW(L,c) longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf + +#endif /* } */ + +#endif /* } */ + + /* chain list of long jump buffers */ struct lua_longjmp { @@ -48,18 +88,17 @@ struct lua_longjmp { }; -void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { +static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { switch (errcode) { - case LUA_ERRMEM: { - setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG)); + case LUA_ERRMEM: { /* memory error? */ + setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ break; } case LUA_ERRERR: { setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); break; } - case LUA_ERRSYNTAX: - case LUA_ERRRUN: { + default: { setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ break; } @@ -68,296 +107,379 @@ void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { } -static void restore_stack_limit (lua_State *L) { - lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); - if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */ - int inuse = cast_int(L->ci - L->base_ci); - if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */ - luaD_reallocCI(L, LUAI_MAXCALLS); +l_noret luaD_throw (lua_State *L, int errcode) { + if (L->errorJmp) { /* thread has an error handler? */ + L->errorJmp->status = errcode; /* set status */ + LUAI_THROW(L, L->errorJmp); /* jump to it */ } -} - - -static void resetstack (lua_State *L, int status) { - L->ci = L->base_ci; - L->base = L->ci->base; - luaF_close(L, L->base); /* close eventual pending closures */ - luaD_seterrorobj(L, status, L->base); - L->nCcalls = L->baseCcalls; - L->allowhook = 1; - restore_stack_limit(L); - L->errfunc = 0; - L->errorJmp = NULL; -} - - -void luaD_throw (lua_State *L, int errcode) { - if (L->errorJmp) { - L->errorJmp->status = errcode; - LUAI_THROW(L, L->errorJmp); - } - else { - L->status = cast_byte(errcode); - if (G(L)->panic) { - resetstack(L, errcode); - lua_unlock(L); - G(L)->panic(L); + else { /* thread has no error handler */ + global_State *g = G(L); + L->status = cast_byte(errcode); /* mark it as dead */ + if (g->mainthread->errorJmp) { /* main thread has a handler? */ + setobjs2s(L, g->mainthread->top++, L->top - 1); /* copy error obj. */ + luaD_throw(g->mainthread, errcode); /* re-throw in main thread */ + } + else { /* no handler at all; abort */ + if (g->panic) { /* panic function? */ + seterrorobj(L, errcode, L->top); /* assume EXTRA_STACK */ + if (L->ci->top < L->top) + L->ci->top = L->top; /* pushing msg. can break this invariant */ + lua_unlock(L); + g->panic(L); /* call panic function (last chance to jump out) */ + } + abort(); } - exit(EXIT_FAILURE); } } int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { + unsigned short oldnCcalls = L->nCcalls; struct lua_longjmp lj; - lj.status = 0; + lj.status = LUA_OK; lj.previous = L->errorJmp; /* chain new error handler */ L->errorJmp = &lj; LUAI_TRY(L, &lj, (*f)(L, ud); ); L->errorJmp = lj.previous; /* restore old error handler */ + L->nCcalls = oldnCcalls; return lj.status; } /* }====================================================== */ +/* +** {================================================================== +** Stack reallocation +** =================================================================== +*/ static void correctstack (lua_State *L, TValue *oldstack) { CallInfo *ci; - GCObject *up; + UpVal *up; L->top = (L->top - oldstack) + L->stack; - for (up = L->openupval; up != NULL; up = up->gch.next) - gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; - for (ci = L->base_ci; ci <= L->ci; ci++) { + for (up = L->openupval; up != NULL; up = up->u.open.next) + up->v = (up->v - oldstack) + L->stack; + for (ci = L->ci; ci != NULL; ci = ci->previous) { ci->top = (ci->top - oldstack) + L->stack; - ci->base = (ci->base - oldstack) + L->stack; ci->func = (ci->func - oldstack) + L->stack; + if (isLua(ci)) + ci->u.l.base = (ci->u.l.base - oldstack) + L->stack; } - L->base = (L->base - oldstack) + L->stack; } +/* some space for error handling */ +#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) + + void luaD_reallocstack (lua_State *L, int newsize) { TValue *oldstack = L->stack; - int realsize = newsize + 1 + EXTRA_STACK; - lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); - luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); - L->stacksize = realsize; - L->stack_last = L->stack+newsize; + int lim = L->stacksize; + lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); + lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); + luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue); + for (; lim < newsize; lim++) + setnilvalue(L->stack + lim); /* erase new segment */ + L->stacksize = newsize; + L->stack_last = L->stack + newsize - EXTRA_STACK; correctstack(L, oldstack); } -void luaD_reallocCI (lua_State *L, int newsize) { - CallInfo *oldci = L->base_ci; - luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); - L->size_ci = newsize; - L->ci = (L->ci - oldci) + L->base_ci; - L->end_ci = L->base_ci + L->size_ci - 1; +void luaD_growstack (lua_State *L, int n) { + int size = L->stacksize; + if (size > LUAI_MAXSTACK) /* error after extra size? */ + luaD_throw(L, LUA_ERRERR); + else { + int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; + int newsize = 2 * size; + if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK; + if (newsize < needed) newsize = needed; + if (newsize > LUAI_MAXSTACK) { /* stack overflow? */ + luaD_reallocstack(L, ERRORSTACKSIZE); + luaG_runerror(L, "stack overflow"); + } + else + luaD_reallocstack(L, newsize); + } } -void luaD_growstack (lua_State *L, int n) { - if (n <= L->stacksize) /* double size is enough? */ - luaD_reallocstack(L, 2*L->stacksize); +static int stackinuse (lua_State *L) { + CallInfo *ci; + StkId lim = L->top; + for (ci = L->ci; ci != NULL; ci = ci->previous) { + lua_assert(ci->top <= L->stack_last); + if (lim < ci->top) lim = ci->top; + } + return cast_int(lim - L->stack) + 1; /* part of stack in use */ +} + + +void luaD_shrinkstack (lua_State *L) { + int inuse = stackinuse(L); + int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; + if (goodsize > LUAI_MAXSTACK) goodsize = LUAI_MAXSTACK; + if (L->stacksize > LUAI_MAXSTACK) /* was handling stack overflow? */ + luaE_freeCI(L); /* free all CIs (list grew because of an error) */ else - luaD_reallocstack(L, L->stacksize + n); + luaE_shrinkCI(L); /* shrink list */ + if (inuse <= LUAI_MAXSTACK && /* not handling stack overflow? */ + goodsize < L->stacksize) /* trying to shrink? */ + luaD_reallocstack(L, goodsize); /* shrink it */ + else + condmovestack(L,,); /* don't change stack (change only for debugging) */ } -static CallInfo *growCI (lua_State *L) { - if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */ - luaD_throw(L, LUA_ERRERR); - else { - luaD_reallocCI(L, 2*L->size_ci); - if (L->size_ci > LUAI_MAXCALLS) - luaG_runerror(L, "stack overflow"); - } - return ++L->ci; +void luaD_inctop (lua_State *L) { + luaD_checkstack(L, 1); + L->top++; } +/* }================================================================== */ -void luaD_callhook (lua_State *L, int event, int line) { + +/* +** Call a hook for the given event. Make sure there is a hook to be +** called. (Both 'L->hook' and 'L->hookmask', which triggers this +** function, can be changed asynchronously by signals.) +*/ +void luaD_hook (lua_State *L, int event, int line) { lua_Hook hook = L->hook; - if (hook && L->allowhook) { + if (hook && L->allowhook) { /* make sure there is a hook */ + CallInfo *ci = L->ci; ptrdiff_t top = savestack(L, L->top); - ptrdiff_t ci_top = savestack(L, L->ci->top); + ptrdiff_t ci_top = savestack(L, ci->top); lua_Debug ar; ar.event = event; ar.currentline = line; - if (event == LUA_HOOKTAILRET) - ar.i_ci = 0; /* tail call; no debug information about it */ - else - ar.i_ci = cast_int(L->ci - L->base_ci); + ar.i_ci = ci; luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ - L->ci->top = L->top + LUA_MINSTACK; - lua_assert(L->ci->top <= L->stack_last); + ci->top = L->top + LUA_MINSTACK; + lua_assert(ci->top <= L->stack_last); L->allowhook = 0; /* cannot call hooks inside a hook */ + ci->callstatus |= CIST_HOOKED; lua_unlock(L); (*hook)(L, &ar); lua_lock(L); lua_assert(!L->allowhook); L->allowhook = 1; - L->ci->top = restorestack(L, ci_top); + ci->top = restorestack(L, ci_top); L->top = restorestack(L, top); + ci->callstatus &= ~CIST_HOOKED; + } +} + + +static void callhook (lua_State *L, CallInfo *ci) { + int hook = LUA_HOOKCALL; + ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ + if (isLua(ci->previous) && + GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) { + ci->callstatus |= CIST_TAIL; + hook = LUA_HOOKTAILCALL; } + luaD_hook(L, hook, -1); + ci->u.l.savedpc--; /* correct 'pc' */ } static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { int i; int nfixargs = p->numparams; - Table *htab = NULL; StkId base, fixed; - for (; actual < nfixargs; ++actual) - setnilvalue(L->top++); -#if defined(LUA_COMPAT_VARARG) - if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */ - int nvar = actual - nfixargs; /* number of extra arguments */ - lua_assert(p->is_vararg & VARARG_HASARG); - luaC_checkGC(L); - luaD_checkstack(L, p->maxstacksize); - htab = luaH_new(L, nvar, 1); /* create `arg' table */ - for (i=0; itop - nvar + i); - /* store counter in field `n' */ - setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar)); - } -#endif /* move fixed parameters to final position */ fixed = L->top - actual; /* first fixed argument */ base = L->top; /* final position of first argument */ - for (i=0; itop++, fixed+i); - setnilvalue(fixed+i); - } - /* add `arg' parameter */ - if (htab) { - sethvalue(L, L->top++, htab); - lua_assert(iswhite(obj2gco(htab))); + for (i = 0; i < nfixargs && i < actual; i++) { + setobjs2s(L, L->top++, fixed + i); + setnilvalue(fixed + i); /* erase original copy (for GC) */ } + for (; i < nfixargs; i++) + setnilvalue(L->top++); /* complete missing arguments */ return base; } -static StkId tryfuncTM (lua_State *L, StkId func) { +/* +** Check whether __call metafield of 'func' is a function. If so, put +** it in stack below original 'func' so that 'luaD_precall' can call +** it. Raise an error if __call metafield is not a function. +*/ +static void tryfuncTM (lua_State *L, StkId func) { const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL); StkId p; - ptrdiff_t funcr = savestack(L, func); if (!ttisfunction(tm)) luaG_typeerror(L, func, "call"); - /* Open a hole inside the stack at `func' */ - for (p = L->top; p > func; p--) setobjs2s(L, p, p-1); - incr_top(L); - func = restorestack(L, funcr); /* previous call may change stack */ + /* Open a hole inside the stack at 'func' */ + for (p = L->top; p > func; p--) + setobjs2s(L, p, p-1); + L->top++; /* slot ensured by caller */ setobj2s(L, func, tm); /* tag method is the new function to be called */ - return func; } -#define inc_ci(L) \ - ((L->ci == L->end_ci) ? growCI(L) : \ - (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) +#define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) + + +/* macro to check stack size, preserving 'p' */ +#define checkstackp(L,n,p) \ + luaD_checkstackaux(L, n, \ + ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \ + luaC_checkGC(L), /* stack grow uses memory */ \ + p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ +/* +** Prepares a function call: checks the stack, creates a new CallInfo +** entry, fills in the relevant information, calls hook if needed. +** If function is a C function, does the call, too. (Otherwise, leave +** the execution ('luaV_execute') to the caller, to allow stackless +** calls.) Returns true iff function has been executed (C function). +*/ int luaD_precall (lua_State *L, StkId func, int nresults) { - LClosure *cl; - ptrdiff_t funcr; - if (!ttisfunction(func)) /* `func' is not a function? */ - func = tryfuncTM(L, func); /* check the `function' tag method */ - funcr = savestack(L, func); - cl = &clvalue(func)->l; - L->ci->savedpc = L->savedpc; - if (!cl->isC) { /* Lua function? prepare its call */ - CallInfo *ci; - StkId st, base; - Proto *p = cl->p; - luaD_checkstack(L, p->maxstacksize); - func = restorestack(L, funcr); - if (!p->is_vararg) { /* no varargs? */ - base = func + 1; - if (L->top > base + p->numparams) - L->top = base + p->numparams; - } - else { /* vararg function */ - int nargs = cast_int(L->top - func) - 1; - base = adjust_varargs(L, p, nargs); - func = restorestack(L, funcr); /* previous call may change the stack */ + lua_CFunction f; + CallInfo *ci; + switch (ttype(func)) { + case LUA_TCCL: /* C closure */ + f = clCvalue(func)->f; + goto Cfunc; + case LUA_TLCF: /* light C function */ + f = fvalue(func); + Cfunc: { + int n; /* number of returns */ + checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ + ci = next_ci(L); /* now 'enter' new function */ + ci->nresults = nresults; + ci->func = func; + ci->top = L->top + LUA_MINSTACK; + lua_assert(ci->top <= L->stack_last); + ci->callstatus = 0; + if (L->hookmask & LUA_MASKCALL) + luaD_hook(L, LUA_HOOKCALL, -1); + lua_unlock(L); + n = (*f)(L); /* do the actual call */ + lua_lock(L); + api_checknelems(L, n); + luaD_poscall(L, ci, L->top - n, n); + return 1; } - ci = inc_ci(L); /* now `enter' new function */ - ci->func = func; - L->base = ci->base = base; - ci->top = L->base + p->maxstacksize; - lua_assert(ci->top <= L->stack_last); - L->savedpc = p->code; /* starting point */ - ci->tailcalls = 0; - ci->nresults = nresults; - for (st = L->top; st < ci->top; st++) - setnilvalue(st); - L->top = ci->top; - if (L->hookmask & LUA_MASKCALL) { - L->savedpc++; /* hooks assume 'pc' is already incremented */ - luaD_callhook(L, LUA_HOOKCALL, -1); - L->savedpc--; /* correct 'pc' */ + case LUA_TLCL: { /* Lua function: prepare its call */ + StkId base; + Proto *p = clLvalue(func)->p; + int n = cast_int(L->top - func) - 1; /* number of real arguments */ + int fsize = p->maxstacksize; /* frame size */ + checkstackp(L, fsize, func); + if (p->is_vararg != 1) { /* do not use vararg? */ + for (; n < p->numparams; n++) + setnilvalue(L->top++); /* complete missing arguments */ + base = func + 1; + } + else + base = adjust_varargs(L, p, n); + ci = next_ci(L); /* now 'enter' new function */ + ci->nresults = nresults; + ci->func = func; + ci->u.l.base = base; + L->top = ci->top = base + fsize; + lua_assert(ci->top <= L->stack_last); + ci->u.l.savedpc = p->code; /* starting point */ + ci->callstatus = CIST_LUA; + if (L->hookmask & LUA_MASKCALL) + callhook(L, ci); + return 0; } - return PCRLUA; - } - else { /* if is a C function, call it */ - CallInfo *ci; - int n; - luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ - ci = inc_ci(L); /* now `enter' new function */ - ci->func = restorestack(L, funcr); - L->base = ci->base = ci->func + 1; - ci->top = L->top + LUA_MINSTACK; - lua_assert(ci->top <= L->stack_last); - ci->nresults = nresults; - if (L->hookmask & LUA_MASKCALL) - luaD_callhook(L, LUA_HOOKCALL, -1); - lua_unlock(L); - n = (*curr_func(L)->c.f)(L); /* do the actual call */ - lua_lock(L); - if (n < 0) /* yielding? */ - return PCRYIELD; - else { - luaD_poscall(L, L->top - n); - return PCRC; + default: { /* not a function */ + checkstackp(L, 1, func); /* ensure space for metamethod */ + tryfuncTM(L, func); /* try to get '__call' metamethod */ + return luaD_precall(L, func, nresults); /* now it must be a function */ } } } -static StkId callrethooks (lua_State *L, StkId firstResult) { - ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ - luaD_callhook(L, LUA_HOOKRET, -1); - if (f_isLua(L->ci)) { /* Lua function? */ - while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */ - luaD_callhook(L, LUA_HOOKTAILRET, -1); +/* +** Given 'nres' results at 'firstResult', move 'wanted' of them to 'res'. +** Handle most typical cases (zero results for commands, one result for +** expressions, multiple results for tail calls/single parameters) +** separated. +*/ +static int moveresults (lua_State *L, const TValue *firstResult, StkId res, + int nres, int wanted) { + switch (wanted) { /* handle typical cases separately */ + case 0: break; /* nothing to move */ + case 1: { /* one result needed */ + if (nres == 0) /* no results? */ + firstResult = luaO_nilobject; /* adjust with nil */ + setobjs2s(L, res, firstResult); /* move it to proper place */ + break; + } + case LUA_MULTRET: { + int i; + for (i = 0; i < nres; i++) /* move all results to correct place */ + setobjs2s(L, res + i, firstResult + i); + L->top = res + nres; + return 0; /* wanted == LUA_MULTRET */ + } + default: { + int i; + if (wanted <= nres) { /* enough results? */ + for (i = 0; i < wanted; i++) /* move wanted results to correct place */ + setobjs2s(L, res + i, firstResult + i); + } + else { /* not enough results; use all of them plus nils */ + for (i = 0; i < nres; i++) /* move all results to correct place */ + setobjs2s(L, res + i, firstResult + i); + for (; i < wanted; i++) /* complete wanted number of results */ + setnilvalue(res + i); + } + break; + } } - return restorestack(L, fr); + L->top = res + wanted; /* top points after the last result */ + return 1; } -int luaD_poscall (lua_State *L, StkId firstResult) { +/* +** Finishes a function call: calls hook if necessary, removes CallInfo, +** moves current number of results to proper place; returns 0 iff call +** wanted multiple (variable number of) results. +*/ +int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { StkId res; - int wanted, i; - CallInfo *ci; - if (L->hookmask & LUA_MASKRET) - firstResult = callrethooks(L, firstResult); - ci = L->ci--; + int wanted = ci->nresults; + if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { + if (L->hookmask & LUA_MASKRET) { + ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ + luaD_hook(L, LUA_HOOKRET, -1); + firstResult = restorestack(L, fr); + } + L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */ + } res = ci->func; /* res == final position of 1st result */ - wanted = ci->nresults; - L->base = (ci - 1)->base; /* restore base */ - L->savedpc = (ci - 1)->savedpc; /* restore savedpc */ - /* move results to correct place */ - for (i = wanted; i != 0 && firstResult < L->top; i--) - setobjs2s(L, res++, firstResult++); - while (i-- > 0) - setnilvalue(res++); - L->top = res; - return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */ + L->ci = ci->previous; /* back to caller */ + /* move results to proper place */ + return moveresults(L, firstResult, res, nres, wanted); +} + + +/* +** Check appropriate error for stack overflow ("regular" overflow or +** overflow while handling stack overflow). If 'nCalls' is larger than +** LUAI_MAXCCALLS (which means it is handling a "regular" overflow) but +** smaller than 9/8 of LUAI_MAXCCALLS, does not report an error (to +** allow overflow handling to work) +*/ +static void stackerror (lua_State *L) { + if (L->nCcalls == LUAI_MAXCCALLS) + luaG_runerror(L, "C stack overflow"); + else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) + luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ } @@ -366,112 +488,251 @@ int luaD_poscall (lua_State *L, StkId firstResult) { ** The arguments are on the stack, right after the function. ** When returns, all the results are on the stack, starting at the original ** function position. -*/ +*/ void luaD_call (lua_State *L, StkId func, int nResults) { - if (++L->nCcalls >= LUAI_MAXCCALLS) { - if (L->nCcalls == LUAI_MAXCCALLS) - luaG_runerror(L, "C stack overflow"); - else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) - luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ - } - if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */ - luaV_execute(L, 1); /* call it */ + if (++L->nCcalls >= LUAI_MAXCCALLS) + stackerror(L); + if (!luaD_precall(L, func, nResults)) /* is a Lua function? */ + luaV_execute(L); /* call it */ L->nCcalls--; - luaC_checkGC(L); } -static void resume (lua_State *L, void *ud) { - StkId firstArg = cast(StkId, ud); +/* +** Similar to 'luaD_call', but does not allow yields during the call +*/ +void luaD_callnoyield (lua_State *L, StkId func, int nResults) { + L->nny++; + luaD_call(L, func, nResults); + L->nny--; +} + + +/* +** Completes the execution of an interrupted C function, calling its +** continuation function. +*/ +static void finishCcall (lua_State *L, int status) { CallInfo *ci = L->ci; - if (L->status == 0) { /* start coroutine? */ - lua_assert(ci == L->base_ci && firstArg > L->base); - if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA) - return; + int n; + /* must have a continuation and must be able to call it */ + lua_assert(ci->u.c.k != NULL && L->nny == 0); + /* error status can only happen in a protected call */ + lua_assert((ci->callstatus & CIST_YPCALL) || status == LUA_YIELD); + if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */ + ci->callstatus &= ~CIST_YPCALL; /* finish 'lua_pcall' */ + L->errfunc = ci->u.c.old_errfunc; } - else { /* resuming from previous yield */ - lua_assert(L->status == LUA_YIELD); - L->status = 0; - if (!f_isLua(ci)) { /* `common' yield? */ - /* finish interrupted execution of `OP_CALL' */ - lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL || - GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL); - if (luaD_poscall(L, firstArg)) /* complete it... */ - L->top = L->ci->top; /* and correct top if not multiple results */ + /* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already + handled */ + adjustresults(L, ci->nresults); + /* call continuation function */ + lua_unlock(L); + n = (*ci->u.c.k)(L, status, ci->u.c.ctx); + lua_lock(L); + api_checknelems(L, n); + /* finish 'luaD_precall' */ + luaD_poscall(L, ci, L->top - n, n); +} + + +/* +** Executes "full continuation" (everything in the stack) of a +** previously interrupted coroutine until the stack is empty (or another +** interruption long-jumps out of the loop). If the coroutine is +** recovering from an error, 'ud' points to the error status, which must +** be passed to the first continuation function (otherwise the default +** status is LUA_YIELD). +*/ +static void unroll (lua_State *L, void *ud) { + if (ud != NULL) /* error status? */ + finishCcall(L, *(int *)ud); /* finish 'lua_pcallk' callee */ + while (L->ci != &L->base_ci) { /* something in the stack */ + if (!isLua(L->ci)) /* C function? */ + finishCcall(L, LUA_YIELD); /* complete its execution */ + else { /* Lua function */ + luaV_finishOp(L); /* finish interrupted instruction */ + luaV_execute(L); /* execute down to higher C 'boundary' */ } - else /* yielded inside a hook: just continue its execution */ - L->base = L->ci->base; } - luaV_execute(L, cast_int(L->ci - L->base_ci)); } -static int resume_error (lua_State *L, const char *msg) { - L->top = L->ci->base; - setsvalue2s(L, L->top, luaS_new(L, msg)); - incr_top(L); - lua_unlock(L); - return LUA_ERRRUN; +/* +** Try to find a suspended protected call (a "recover point") for the +** given thread. +*/ +static CallInfo *findpcall (lua_State *L) { + CallInfo *ci; + for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */ + if (ci->callstatus & CIST_YPCALL) + return ci; + } + return NULL; /* no pending pcall */ +} + + +/* +** Recovers from an error in a coroutine. Finds a recover point (if +** there is one) and completes the execution of the interrupted +** 'luaD_pcall'. If there is no recover point, returns zero. +*/ +static int recover (lua_State *L, int status) { + StkId oldtop; + CallInfo *ci = findpcall(L); + if (ci == NULL) return 0; /* no recovery point */ + /* "finish" luaD_pcall */ + oldtop = restorestack(L, ci->extra); + luaF_close(L, oldtop); + seterrorobj(L, status, oldtop); + L->ci = ci; + L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */ + L->nny = 0; /* should be zero to be yieldable */ + luaD_shrinkstack(L); + L->errfunc = ci->u.c.old_errfunc; + return 1; /* continue running the coroutine */ +} + + +/* +** signal an error in the call to 'resume', not in the execution of the +** coroutine itself. (Such errors should not be handled by any coroutine +** error handler and should not kill the coroutine.) +*/ +static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) { + L->top = firstArg; /* remove args from the stack */ + setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */ + api_incr_top(L); + luaD_throw(L, -1); /* jump back to 'lua_resume' */ } -LUA_API int lua_resume (lua_State *L, int nargs) { +/* +** Do the work for 'lua_resume' in protected mode. Most of the work +** depends on the status of the coroutine: initial state, suspended +** inside a hook, or regularly suspended (optionally with a continuation +** function), plus erroneous cases: non-suspended coroutine or dead +** coroutine. +*/ +static void resume (lua_State *L, void *ud) { + int nCcalls = L->nCcalls; + int n = *(cast(int*, ud)); /* number of arguments */ + StkId firstArg = L->top - n; /* first argument */ + CallInfo *ci = L->ci; + if (nCcalls >= LUAI_MAXCCALLS) + resume_error(L, "C stack overflow", firstArg); + if (L->status == LUA_OK) { /* may be starting a coroutine */ + if (ci != &L->base_ci) /* not in base level? */ + resume_error(L, "cannot resume non-suspended coroutine", firstArg); + /* coroutine is in base level; start running it */ + if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */ + luaV_execute(L); /* call it */ + } + else if (L->status != LUA_YIELD) + resume_error(L, "cannot resume dead coroutine", firstArg); + else { /* resuming from previous yield */ + L->status = LUA_OK; /* mark that it is running (again) */ + ci->func = restorestack(L, ci->extra); + if (isLua(ci)) /* yielded inside a hook? */ + luaV_execute(L); /* just continue running Lua code */ + else { /* 'common' yield */ + if (ci->u.c.k != NULL) { /* does it have a continuation function? */ + lua_unlock(L); + n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */ + lua_lock(L); + api_checknelems(L, n); + firstArg = L->top - n; /* yield results come from continuation */ + } + luaD_poscall(L, ci, firstArg, n); /* finish 'luaD_precall' */ + } + unroll(L, NULL); /* run continuation */ + } + lua_assert(nCcalls == L->nCcalls); +} + + +LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) { int status; + unsigned short oldnny = L->nny; /* save "number of non-yieldable" calls */ lua_lock(L); - if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci)) - return resume_error(L, "cannot resume non-suspended coroutine"); - if (L->nCcalls >= LUAI_MAXCCALLS) - return resume_error(L, "C stack overflow"); luai_userstateresume(L, nargs); - lua_assert(L->errfunc == 0); - L->baseCcalls = ++L->nCcalls; - status = luaD_rawrunprotected(L, resume, L->top - nargs); - if (status != 0) { /* error? */ - L->status = cast_byte(status); /* mark thread as `dead' */ - luaD_seterrorobj(L, status, L->top); - L->ci->top = L->top; - } - else { - lua_assert(L->nCcalls == L->baseCcalls); - status = L->status; + L->nCcalls = (from) ? from->nCcalls + 1 : 1; + L->nny = 0; /* allow yields */ + api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); + status = luaD_rawrunprotected(L, resume, &nargs); + if (status == -1) /* error calling 'lua_resume'? */ + status = LUA_ERRRUN; + else { /* continue running after recoverable errors */ + while (errorstatus(status) && recover(L, status)) { + /* unroll continuation */ + status = luaD_rawrunprotected(L, unroll, &status); + } + if (errorstatus(status)) { /* unrecoverable error? */ + L->status = cast_byte(status); /* mark thread as 'dead' */ + seterrorobj(L, status, L->top); /* push error message */ + L->ci->top = L->top; + } + else lua_assert(status == L->status); /* normal end or yield */ } - --L->nCcalls; + L->nny = oldnny; /* restore 'nny' */ + L->nCcalls--; + lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0)); lua_unlock(L); return status; } -LUA_API int lua_yield (lua_State *L, int nresults) { +LUA_API int lua_isyieldable (lua_State *L) { + return (L->nny == 0); +} + + +LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, + lua_KFunction k) { + CallInfo *ci = L->ci; luai_userstateyield(L, nresults); lua_lock(L); - if (L->nCcalls > L->baseCcalls) - luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); - L->base = L->top - nresults; /* protect stack slots below */ + api_checknelems(L, nresults); + if (L->nny > 0) { + if (L != G(L)->mainthread) + luaG_runerror(L, "attempt to yield across a C-call boundary"); + else + luaG_runerror(L, "attempt to yield from outside a coroutine"); + } L->status = LUA_YIELD; + ci->extra = savestack(L, ci->func); /* save current 'func' */ + if (isLua(ci)) { /* inside a hook? */ + api_check(L, k == NULL, "hooks cannot continue after yielding"); + } + else { + if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ + ci->u.c.ctx = ctx; /* save context */ + ci->func = L->top - nresults - 1; /* protect stack below results */ + luaD_throw(L, LUA_YIELD); + } + lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ lua_unlock(L); - return -1; + return 0; /* return to 'luaD_hook' */ } int luaD_pcall (lua_State *L, Pfunc func, void *u, ptrdiff_t old_top, ptrdiff_t ef) { int status; - unsigned short oldnCcalls = L->nCcalls; - ptrdiff_t old_ci = saveci(L, L->ci); + CallInfo *old_ci = L->ci; lu_byte old_allowhooks = L->allowhook; + unsigned short old_nny = L->nny; ptrdiff_t old_errfunc = L->errfunc; L->errfunc = ef; status = luaD_rawrunprotected(L, func, u); - if (status != 0) { /* an error occurred? */ + if (status != LUA_OK) { /* an error occurred? */ StkId oldtop = restorestack(L, old_top); - luaF_close(L, oldtop); /* close eventual pending closures */ - luaD_seterrorobj(L, status, oldtop); - L->nCcalls = oldnCcalls; - L->ci = restoreci(L, old_ci); - L->base = L->ci->base; - L->savedpc = L->ci->savedpc; + luaF_close(L, oldtop); /* close possible pending closures */ + seterrorobj(L, status, oldtop); + L->ci = old_ci; L->allowhook = old_allowhooks; - restore_stack_limit(L); + L->nny = old_nny; + luaD_shrinkstack(L); } L->errfunc = old_errfunc; return status; @@ -482,37 +743,57 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u, /* ** Execute a protected parser. */ -struct SParser { /* data to `f_parser' */ +struct SParser { /* data to 'f_parser' */ ZIO *z; - Mbuffer buff; /* buffer to be used by the scanner */ + Mbuffer buff; /* dynamic structure used by the scanner */ + Dyndata dyd; /* dynamic structures used by the parser */ + const char *mode; const char *name; }; + +static void checkmode (lua_State *L, const char *mode, const char *x) { + if (mode && strchr(mode, x[0]) == NULL) { + luaO_pushfstring(L, + "attempt to load a %s chunk (mode is '%s')", x, mode); + luaD_throw(L, LUA_ERRSYNTAX); + } +} + + static void f_parser (lua_State *L, void *ud) { - int i; - Proto *tf; - Closure *cl; + LClosure *cl; struct SParser *p = cast(struct SParser *, ud); - int c = luaZ_lookahead(p->z); - luaC_checkGC(L); - tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, - &p->buff, p->name); - cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); - cl->l.p = tf; - for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */ - cl->l.upvals[i] = luaF_newupval(L); - setclvalue(L, L->top, cl); - incr_top(L); + int c = zgetc(p->z); /* read first character */ + if (c == LUA_SIGNATURE[0]) { + checkmode(L, p->mode, "binary"); + cl = luaU_undump(L, p->z, p->name); + } + else { + checkmode(L, p->mode, "text"); + cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); + } + lua_assert(cl->nupvalues == cl->p->sizeupvalues); + luaF_initupvals(L, cl); } -int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) { +int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, + const char *mode) { struct SParser p; int status; - p.z = z; p.name = name; + L->nny++; /* cannot yield during parsing */ + p.z = z; p.name = name; p.mode = mode; + p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0; + p.dyd.gt.arr = NULL; p.dyd.gt.size = 0; + p.dyd.label.arr = NULL; p.dyd.label.size = 0; luaZ_initbuffer(L, &p.buff); status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); luaZ_freebuffer(L, &p.buff); + luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size); + luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size); + luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size); + L->nny--; return status; } diff --git a/app/src/main/jni/lua/ldo.h b/app/src/main/jni/lua/ldo.h index 98fddac..4f5d51c 100644 --- a/app/src/main/jni/lua/ldo.h +++ b/app/src/main/jni/lua/ldo.h @@ -1,5 +1,5 @@ /* -** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: ldo.h,v 2.29 2015/12/21 13:02:14 roberto Exp $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -13,45 +13,46 @@ #include "lzio.h" -#define luaD_checkstack(L,n) \ - if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \ - luaD_growstack(L, n); \ - else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); +/* +** Macro to check stack size and grow stack if needed. Parameters +** 'pre'/'pos' allow the macro to preserve a pointer into the +** stack across reallocations, doing the work only when needed. +** 'condmovestack' is used in heavy tests to force a stack reallocation +** at every check. +*/ +#define luaD_checkstackaux(L,n,pre,pos) \ + if (L->stack_last - L->top <= (n)) \ + { pre; luaD_growstack(L, n); pos; } else { condmovestack(L,pre,pos); } + +/* In general, 'pre'/'pos' are empty (nothing to save) */ +#define luaD_checkstack(L,n) luaD_checkstackaux(L,n,(void)0,(void)0) -#define incr_top(L) {luaD_checkstack(L,1); L->top++;} #define savestack(L,p) ((char *)(p) - (char *)L->stack) #define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) -#define saveci(L,p) ((char *)(p) - (char *)L->base_ci) -#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) - -/* results from luaD_precall */ -#define PCRLUA 0 /* initiated a call to a Lua function */ -#define PCRC 1 /* did a call to a C function */ -#define PCRYIELD 2 /* C funtion yielded */ - - -/* type of protected functions, to be ran by `runprotected' */ +/* type of protected functions, to be ran by 'runprotected' */ typedef void (*Pfunc) (lua_State *L, void *ud); -LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name); -LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line); +LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, + const char *mode); +LUAI_FUNC void luaD_hook (lua_State *L, int event, int line); LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); +LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults); LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, ptrdiff_t oldtop, ptrdiff_t ef); -LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); -LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize); +LUAI_FUNC int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, + int nres); LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); LUAI_FUNC void luaD_growstack (lua_State *L, int n); +LUAI_FUNC void luaD_shrinkstack (lua_State *L); +LUAI_FUNC void luaD_inctop (lua_State *L); -LUAI_FUNC void luaD_throw (lua_State *L, int errcode); +LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode); LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); -LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop); - #endif diff --git a/app/src/main/jni/lua/ldump.c b/app/src/main/jni/lua/ldump.c index c9d3d48..016e300 100644 --- a/app/src/main/jni/lua/ldump.c +++ b/app/src/main/jni/lua/ldump.c @@ -1,164 +1,215 @@ /* -** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: ldump.c,v 2.37 2015/10/08 15:53:49 roberto Exp $ ** save precompiled Lua chunks ** See Copyright Notice in lua.h */ -#include - #define ldump_c #define LUA_CORE +#include "lprefix.h" + + +#include + #include "lua.h" #include "lobject.h" #include "lstate.h" #include "lundump.h" + typedef struct { - lua_State* L; - lua_Writer writer; - void* data; - int strip; - int status; + lua_State *L; + lua_Writer writer; + void *data; + int strip; + int status; } DumpState; -#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) -#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) - -static void DumpBlock(const void* b, size_t size, DumpState* D) -{ - if (D->status==0) - { - lua_unlock(D->L); - D->status=(*D->writer)(D->L,b,size,D->data); - lua_lock(D->L); - } + +/* +** All high-level dumps go through DumpVector; you can change it to +** change the endianness of the result +*/ +#define DumpVector(v,n,D) DumpBlock(v,(n)*sizeof((v)[0]),D) + +#define DumpLiteral(s,D) DumpBlock(s, sizeof(s) - sizeof(char), D) + + +static void DumpBlock (const void *b, size_t size, DumpState *D) { + if (D->status == 0 && size > 0) { + lua_unlock(D->L); + D->status = (*D->writer)(D->L, b, size, D->data); + lua_lock(D->L); + } } -static void DumpChar(int y, DumpState* D) -{ - char x=(char)y; - DumpVar(x,D); + +#define DumpVar(x,D) DumpVector(&x,1,D) + + +static void DumpByte (int y, DumpState *D) { + lu_byte x = (lu_byte)y; + DumpVar(x, D); } -static void DumpInt(int x, DumpState* D) -{ - DumpVar(x,D); + +static void DumpInt (int x, DumpState *D) { + DumpVar(x, D); } -static void DumpNumber(lua_Number x, DumpState* D) -{ - DumpVar(x,D); + +static void DumpNumber (lua_Number x, DumpState *D) { + DumpVar(x, D); } -static void DumpVector(const void* b, int n, size_t size, DumpState* D) -{ - DumpInt(n,D); - DumpMem(b,n,size,D); + +static void DumpInteger (lua_Integer x, DumpState *D) { + DumpVar(x, D); } -static void DumpString(const TString* s, DumpState* D) -{ - if (s==NULL || getstr(s)==NULL) - { - size_t size=0; - DumpVar(size,D); - } - else - { - size_t size=s->tsv.len+1; /* include trailing '\0' */ - DumpVar(size,D); - DumpBlock(getstr(s),size,D); - } + +static void DumpString (const TString *s, DumpState *D) { + if (s == NULL) + DumpByte(0, D); + else { + size_t size = tsslen(s) + 1; /* include trailing '\0' */ + const char *str = getstr(s); + if (size < 0xFF) + DumpByte(cast_int(size), D); + else { + DumpByte(0xFF, D); + DumpVar(size, D); + } + DumpVector(str, size - 1, D); /* no need to save '\0' */ + } +} + + +static void DumpCode (const Proto *f, DumpState *D) { + DumpInt(f->sizecode, D); + DumpVector(f->code, f->sizecode, D); } -#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) - -static void DumpFunction(const Proto* f, const TString* p, DumpState* D); - -static void DumpConstants(const Proto* f, DumpState* D) -{ - int i,n=f->sizek; - DumpInt(n,D); - for (i=0; ik[i]; - DumpChar(ttype(o),D); - switch (ttype(o)) - { - case LUA_TNIL: - break; - case LUA_TBOOLEAN: - DumpChar(bvalue(o),D); - break; - case LUA_TNUMBER: - DumpNumber(nvalue(o),D); - break; - case LUA_TSTRING: - DumpString(rawtsvalue(o),D); - break; - default: - lua_assert(0); /* cannot happen */ - break; + +static void DumpFunction(const Proto *f, TString *psource, DumpState *D); + +static void DumpConstants (const Proto *f, DumpState *D) { + int i; + int n = f->sizek; + DumpInt(n, D); + for (i = 0; i < n; i++) { + const TValue *o = &f->k[i]; + DumpByte(ttype(o), D); + switch (ttype(o)) { + case LUA_TNIL: + break; + case LUA_TBOOLEAN: + DumpByte(bvalue(o), D); + break; + case LUA_TNUMFLT: + DumpNumber(fltvalue(o), D); + break; + case LUA_TNUMINT: + DumpInteger(ivalue(o), D); + break; + case LUA_TSHRSTR: + case LUA_TLNGSTR: + DumpString(tsvalue(o), D); + break; + default: + lua_assert(0); + } } - } - n=f->sizep; - DumpInt(n,D); - for (i=0; ip[i],f->source,D); } -static void DumpDebug(const Proto* f, DumpState* D) -{ - int i,n; - n= (D->strip) ? 0 : f->sizelineinfo; - DumpVector(f->lineinfo,n,sizeof(int),D); - n= (D->strip) ? 0 : f->sizelocvars; - DumpInt(n,D); - for (i=0; ilocvars[i].varname,D); - DumpInt(f->locvars[i].startpc,D); - DumpInt(f->locvars[i].endpc,D); - } - n= (D->strip) ? 0 : f->sizeupvalues; - DumpInt(n,D); - for (i=0; iupvalues[i],D); + +static void DumpProtos (const Proto *f, DumpState *D) { + int i; + int n = f->sizep; + DumpInt(n, D); + for (i = 0; i < n; i++) + DumpFunction(f->p[i], f->source, D); } -static void DumpFunction(const Proto* f, const TString* p, DumpState* D) -{ - DumpString((f->source==p || D->strip) ? NULL : f->source,D); - DumpInt(f->linedefined,D); - DumpInt(f->lastlinedefined,D); - DumpChar(f->nups,D); - DumpChar(f->numparams,D); - DumpChar(f->is_vararg,D); - DumpChar(f->maxstacksize,D); - DumpCode(f,D); - DumpConstants(f,D); - DumpDebug(f,D); + +static void DumpUpvalues (const Proto *f, DumpState *D) { + int i, n = f->sizeupvalues; + DumpInt(n, D); + for (i = 0; i < n; i++) { + DumpByte(f->upvalues[i].instack, D); + DumpByte(f->upvalues[i].idx, D); + } } -static void DumpHeader(DumpState* D) -{ - char h[LUAC_HEADERSIZE]; - luaU_header(h); - DumpBlock(h,LUAC_HEADERSIZE,D); + +static void DumpDebug (const Proto *f, DumpState *D) { + int i, n; + n = (D->strip) ? 0 : f->sizelineinfo; + DumpInt(n, D); + DumpVector(f->lineinfo, n, D); + n = (D->strip) ? 0 : f->sizelocvars; + DumpInt(n, D); + for (i = 0; i < n; i++) { + DumpString(f->locvars[i].varname, D); + DumpInt(f->locvars[i].startpc, D); + DumpInt(f->locvars[i].endpc, D); + } + n = (D->strip) ? 0 : f->sizeupvalues; + DumpInt(n, D); + for (i = 0; i < n; i++) + DumpString(f->upvalues[i].name, D); } + +static void DumpFunction (const Proto *f, TString *psource, DumpState *D) { + if (D->strip || f->source == psource) + DumpString(NULL, D); /* no debug info or same source as its parent */ + else + DumpString(f->source, D); + DumpInt(f->linedefined, D); + DumpInt(f->lastlinedefined, D); + DumpByte(f->numparams, D); + DumpByte(f->is_vararg, D); + DumpByte(f->maxstacksize, D); + DumpCode(f, D); + DumpConstants(f, D); + DumpUpvalues(f, D); + DumpProtos(f, D); + DumpDebug(f, D); +} + + +static void DumpHeader (DumpState *D) { + DumpLiteral(LUA_SIGNATURE, D); + DumpByte(LUAC_VERSION, D); + DumpByte(LUAC_FORMAT, D); + DumpLiteral(LUAC_DATA, D); + DumpByte(sizeof(int), D); + DumpByte(sizeof(size_t), D); + DumpByte(sizeof(Instruction), D); + DumpByte(sizeof(lua_Integer), D); + DumpByte(sizeof(lua_Number), D); + DumpInteger(LUAC_INT, D); + DumpNumber(LUAC_NUM, D); +} + + /* ** dump Lua function as precompiled chunk */ -int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) -{ - DumpState D; - D.L=L; - D.writer=w; - D.data=data; - D.strip=strip; - D.status=0; - DumpHeader(&D); - DumpFunction(f,NULL,&D); - return D.status; +int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data, + int strip) { + DumpState D; + D.L = L; + D.writer = w; + D.data = data; + D.strip = strip; + D.status = 0; + DumpHeader(&D); + DumpByte(f->sizeupvalues, &D); + DumpFunction(f, NULL, &D); + return D.status; } + diff --git a/app/src/main/jni/lua/lfunc.c b/app/src/main/jni/lua/lfunc.c index 813e88f..67967da 100644 --- a/app/src/main/jni/lua/lfunc.c +++ b/app/src/main/jni/lua/lfunc.c @@ -1,15 +1,17 @@ /* -** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $ +** $Id: lfunc.c,v 2.45 2014/11/02 19:19:04 roberto Exp $ ** Auxiliary functions to manipulate prototypes and closures ** See Copyright Notice in lua.h */ - -#include - #define lfunc_c #define LUA_CORE +#include "lprefix.h" + + +#include + #include "lua.h" #include "lfunc.h" @@ -20,117 +22,99 @@ -Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) { - Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); - luaC_link(L, obj2gco(c), LUA_TFUNCTION); - c->c.isC = 1; - c->c.env = e; - c->c.nupvalues = cast_byte(nelems); +CClosure *luaF_newCclosure (lua_State *L, int n) { + GCObject *o = luaC_newobj(L, LUA_TCCL, sizeCclosure(n)); + CClosure *c = gco2ccl(o); + c->nupvalues = cast_byte(n); return c; } -Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) { - Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); - luaC_link(L, obj2gco(c), LUA_TFUNCTION); - c->l.isC = 0; - c->l.env = e; - c->l.nupvalues = cast_byte(nelems); - while (nelems--) c->l.upvals[nelems] = NULL; +LClosure *luaF_newLclosure (lua_State *L, int n) { + GCObject *o = luaC_newobj(L, LUA_TLCL, sizeLclosure(n)); + LClosure *c = gco2lcl(o); + c->p = NULL; + c->nupvalues = cast_byte(n); + while (n--) c->upvals[n] = NULL; return c; } - -UpVal *luaF_newupval (lua_State *L) { - UpVal *uv = luaM_new(L, UpVal); - luaC_link(L, obj2gco(uv), LUA_TUPVAL); - uv->v = &uv->u.value; - setnilvalue(uv->v); - return uv; +/* +** fill a closure with new closed upvalues +*/ +void luaF_initupvals (lua_State *L, LClosure *cl) { + int i; + for (i = 0; i < cl->nupvalues; i++) { + UpVal *uv = luaM_new(L, UpVal); + uv->refcount = 1; + uv->v = &uv->u.value; /* make it closed */ + setnilvalue(uv->v); + cl->upvals[i] = uv; + } } UpVal *luaF_findupval (lua_State *L, StkId level) { - global_State *g = G(L); - GCObject **pp = &L->openupval; + UpVal **pp = &L->openupval; UpVal *p; UpVal *uv; - while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) { - lua_assert(p->v != &p->u.value); - if (p->v == level) { /* found a corresponding upvalue? */ - if (isdead(g, obj2gco(p))) /* is it dead? */ - changewhite(obj2gco(p)); /* ressurect it */ - return p; - } - pp = &p->next; + lua_assert(isintwups(L) || L->openupval == NULL); + while (*pp != NULL && (p = *pp)->v >= level) { + lua_assert(upisopen(p)); + if (p->v == level) /* found a corresponding upvalue? */ + return p; /* return it */ + pp = &p->u.open.next; } - uv = luaM_new(L, UpVal); /* not found: create a new one */ - uv->tt = LUA_TUPVAL; - uv->marked = luaC_white(g); + /* not found: create a new upvalue */ + uv = luaM_new(L, UpVal); + uv->refcount = 0; + uv->u.open.next = *pp; /* link it to list of open upvalues */ + uv->u.open.touched = 1; + *pp = uv; uv->v = level; /* current value lives in the stack */ - uv->next = *pp; /* chain it in the proper position */ - *pp = obj2gco(uv); - uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ - uv->u.l.next = g->uvhead.u.l.next; - uv->u.l.next->u.l.prev = uv; - g->uvhead.u.l.next = uv; - lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); + if (!isintwups(L)) { /* thread not in list of threads with upvalues? */ + L->twups = G(L)->twups; /* link it to the list */ + G(L)->twups = L; + } return uv; } -static void unlinkupval (UpVal *uv) { - lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); - uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */ - uv->u.l.prev->u.l.next = uv->u.l.next; -} - - -void luaF_freeupval (lua_State *L, UpVal *uv) { - if (uv->v != &uv->u.value) /* is it open? */ - unlinkupval(uv); /* remove from open list */ - luaM_free(L, uv); /* free upvalue */ -} - - void luaF_close (lua_State *L, StkId level) { UpVal *uv; - global_State *g = G(L); - while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) { - GCObject *o = obj2gco(uv); - lua_assert(!isblack(o) && uv->v != &uv->u.value); - L->openupval = uv->next; /* remove from `open' list */ - if (isdead(g, o)) - luaF_freeupval(L, uv); /* free upvalue */ + while (L->openupval != NULL && (uv = L->openupval)->v >= level) { + lua_assert(upisopen(uv)); + L->openupval = uv->u.open.next; /* remove from 'open' list */ + if (uv->refcount == 0) /* no references? */ + luaM_free(L, uv); /* free upvalue */ else { - unlinkupval(uv); - setobj(L, &uv->u.value, uv->v); + setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */ uv->v = &uv->u.value; /* now current value lives here */ - luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ + luaC_upvalbarrier(L, uv); } } } Proto *luaF_newproto (lua_State *L) { - Proto *f = luaM_new(L, Proto); - luaC_link(L, obj2gco(f), LUA_TPROTO); + GCObject *o = luaC_newobj(L, LUA_TPROTO, sizeof(Proto)); + Proto *f = gco2p(o); f->k = NULL; f->sizek = 0; f->p = NULL; f->sizep = 0; f->code = NULL; + f->cache = NULL; f->sizecode = 0; + f->lineinfo = NULL; f->sizelineinfo = 0; - f->sizeupvalues = 0; - f->nups = 0; f->upvalues = NULL; + f->sizeupvalues = 0; f->numparams = 0; f->is_vararg = 0; f->maxstacksize = 0; - f->lineinfo = NULL; - f->sizelocvars = 0; f->locvars = NULL; + f->sizelocvars = 0; f->linedefined = 0; f->lastlinedefined = 0; f->source = NULL; @@ -139,25 +123,18 @@ Proto *luaF_newproto (lua_State *L) { void luaF_freeproto (lua_State *L, Proto *f) { - luaM_freearray(L, f->code, f->sizecode, Instruction); - luaM_freearray(L, f->p, f->sizep, Proto *); - luaM_freearray(L, f->k, f->sizek, TValue); - luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); - luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); - luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); + luaM_freearray(L, f->code, f->sizecode); + luaM_freearray(L, f->p, f->sizep); + luaM_freearray(L, f->k, f->sizek); + luaM_freearray(L, f->lineinfo, f->sizelineinfo); + luaM_freearray(L, f->locvars, f->sizelocvars); + luaM_freearray(L, f->upvalues, f->sizeupvalues); luaM_free(L, f); } -void luaF_freeclosure (lua_State *L, Closure *c) { - int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) : - sizeLclosure(c->l.nupvalues); - luaM_freemem(L, c, size); -} - - /* -** Look for n-th local variable at line `line' in function `func'. +** Look for n-th local variable at line 'line' in function 'func'. ** Returns NULL if not found. */ const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { diff --git a/app/src/main/jni/lua/lfunc.h b/app/src/main/jni/lua/lfunc.h index a68cf51..2eeb0d5 100644 --- a/app/src/main/jni/lua/lfunc.h +++ b/app/src/main/jni/lua/lfunc.h @@ -1,5 +1,5 @@ /* -** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lfunc.h,v 2.15 2015/01/13 15:49:11 roberto Exp $ ** Auxiliary functions to manipulate prototypes and closures ** See Copyright Notice in lua.h */ @@ -18,15 +18,42 @@ cast(int, sizeof(TValue *)*((n)-1))) +/* test whether thread is in 'twups' list */ +#define isintwups(L) (L->twups != L) + + +/* +** maximum number of upvalues in a closure (both C and Lua). (Value +** must fit in a VM register.) +*/ +#define MAXUPVAL 255 + + +/* +** Upvalues for Lua closures +*/ +struct UpVal { + TValue *v; /* points to stack or to its own value */ + lu_mem refcount; /* reference counter */ + union { + struct { /* (when open) */ + UpVal *next; /* linked list */ + int touched; /* mark to avoid cycles with dead threads */ + } open; + TValue value; /* the value (when closed) */ + } u; +}; + +#define upisopen(up) ((up)->v != &(up)->u.value) + + LUAI_FUNC Proto *luaF_newproto (lua_State *L); -LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e); -LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e); -LUAI_FUNC UpVal *luaF_newupval (lua_State *L); +LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nelems); +LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nelems); +LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); LUAI_FUNC void luaF_close (lua_State *L, StkId level); LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); -LUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c); -LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv); LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, int pc); diff --git a/app/src/main/jni/lua/lgc.c b/app/src/main/jni/lua/lgc.c index e909c79..7c29fb0 100644 --- a/app/src/main/jni/lua/lgc.c +++ b/app/src/main/jni/lua/lgc.c @@ -1,14 +1,17 @@ /* -** $Id: lgc.c,v 2.38.1.2 2011/03/18 18:05:38 roberto Exp $ +** $Id: lgc.c,v 2.212 2016/03/31 19:02:03 roberto Exp $ ** Garbage Collector ** See Copyright Notice in lua.h */ -#include - #define lgc_c #define LUA_CORE +#include "lprefix.h" + + +#include + #include "lua.h" #include "ldebug.h" @@ -23,376 +26,693 @@ #include "ltm.h" -#define GCSTEPSIZE 1024u -#define GCSWEEPMAX 40 -#define GCSWEEPCOST 10 -#define GCFINALIZECOST 100 +/* +** internal state for collector while inside the atomic phase. The +** collector should never be in this state while running regular code. +*/ +#define GCSinsideatomic (GCSpause + 1) +/* +** cost of sweeping one element (the size of a small object divided +** by some adjust for the sweep speed) +*/ +#define GCSWEEPCOST ((sizeof(TString) + 4) / 4) -#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS)) +/* maximum number of elements to sweep in each single step */ +#define GCSWEEPMAX (cast_int((GCSTEPSIZE / GCSWEEPCOST) / 4)) -#define makewhite(g,x) \ - ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g))) +/* cost of calling one finalizer */ +#define GCFINALIZECOST GCSWEEPCOST -#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) -#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) -#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) +/* +** macro to adjust 'stepmul': 'stepmul' is actually used like +** 'stepmul / STEPMULADJ' (value chosen by tests) +*/ +#define STEPMULADJ 200 + + +/* +** macro to adjust 'pause': 'pause' is actually used like +** 'pause / PAUSEADJ' (value chosen by tests) +*/ +#define PAUSEADJ 100 + +/* +** 'makewhite' erases all color bits then sets only the current white +** bit +*/ +#define maskcolors (~(bitmask(BLACKBIT) | WHITEBITS)) +#define makewhite(g,x) \ + (x->marked = cast_byte((x->marked & maskcolors) | luaC_white(g))) -#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) -#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT) +#define white2gray(x) resetbits(x->marked, WHITEBITS) +#define black2gray(x) resetbit(x->marked, BLACKBIT) -#define KEYWEAK bitmask(KEYWEAKBIT) -#define VALUEWEAK bitmask(VALUEWEAKBIT) +#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) +#define checkdeadkey(n) lua_assert(!ttisdeadkey(gkey(n)) || ttisnil(gval(n))) + + +#define checkconsistency(obj) \ + lua_longassert(!iscollectable(obj) || righttt(obj)) #define markvalue(g,o) { checkconsistency(o); \ - if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); } + if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } + +#define markobject(g,t) { if (iswhite(t)) reallymarkobject(g, obj2gco(t)); } + +/* +** mark an object that can be NULL (either because it is really optional, +** or it was stripped as debug info, or inside an uncompleted structure) +*/ +#define markobjectN(g,t) { if (t) markobject(g,t); } + +static void reallymarkobject (global_State *g, GCObject *o); + + +/* +** {====================================================== +** Generic functions +** ======================================================= +*/ -#define markobject(g,t) { if (iswhite(obj2gco(t))) \ - reallymarkobject(g, obj2gco(t)); } +/* +** one after last element in a hash array +*/ +#define gnodelast(h) gnode(h, cast(size_t, sizenode(h))) -#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) + +/* +** link collectable object 'o' into list pointed by 'p' +*/ +#define linkgclist(o,p) ((o)->gclist = (p), (p) = obj2gco(o)) +/* +** If key is not marked, mark its entry as dead. This allows key to be +** collected, but keeps its entry in the table. A dead node is needed +** when Lua looks up for a key (it may be part of a chain) and when +** traversing a weak table (key might be removed from the table during +** traversal). Other places never manipulate dead keys, because its +** associated nil value is enough to signal that the entry is logically +** empty. +*/ static void removeentry (Node *n) { lua_assert(ttisnil(gval(n))); - if (iscollectable(gkey(n))) - setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */ + if (valiswhite(gkey(n))) + setdeadvalue(wgkey(n)); /* unused and unmarked key; remove it */ +} + + +/* +** tells whether a key or value can be cleared from a weak +** table. Non-collectable objects are never removed from weak +** tables. Strings behave as 'values', so are never removed too. for +** other objects: if really collected, cannot keep them; for objects +** being finalized, keep them in keys, but not in values +*/ +static int iscleared (global_State *g, const TValue *o) { + if (!iscollectable(o)) return 0; + else if (ttisstring(o)) { + markobject(g, tsvalue(o)); /* strings are 'values', so are never weak */ + return 0; + } + else return iswhite(gcvalue(o)); } +/* +** barrier that moves collector forward, that is, mark the white object +** being pointed by a black object. (If in sweep phase, clear the black +** object to white [sweep it] to avoid other barrier calls for this +** same object.) +*/ +void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { + global_State *g = G(L); + lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); + if (keepinvariant(g)) /* must keep invariant? */ + reallymarkobject(g, v); /* restore invariant */ + else { /* sweep phase */ + lua_assert(issweepphase(g)); + makewhite(g, o); /* mark main obj. as white to avoid other barriers */ + } +} + + +/* +** barrier that moves collector backward, that is, mark the black object +** pointing to a white object as gray again. +*/ +void luaC_barrierback_ (lua_State *L, Table *t) { + global_State *g = G(L); + lua_assert(isblack(t) && !isdead(g, t)); + black2gray(t); /* make table gray (again) */ + linkgclist(t, g->grayagain); +} + + +/* +** barrier for assignments to closed upvalues. Because upvalues are +** shared among closures, it is impossible to know the color of all +** closures pointing to it. So, we assume that the object being assigned +** must be marked. +*/ +void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) { + global_State *g = G(L); + GCObject *o = gcvalue(uv->v); + lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */ + if (keepinvariant(g)) + markobject(g, o); +} + + +void luaC_fix (lua_State *L, GCObject *o) { + global_State *g = G(L); + lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */ + white2gray(o); /* they will be gray forever */ + g->allgc = o->next; /* remove object from 'allgc' list */ + o->next = g->fixedgc; /* link it to 'fixedgc' list */ + g->fixedgc = o; +} + + +/* +** create a new collectable object (with given type and size) and link +** it to 'allgc' list. +*/ +GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { + global_State *g = G(L); + GCObject *o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz)); + o->marked = luaC_white(g); + o->tt = tt; + o->next = g->allgc; + g->allgc = o; + return o; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** Mark functions +** ======================================================= +*/ + + +/* +** mark an object. Userdata, strings, and closed upvalues are visited +** and turned black here. Other objects are marked gray and added +** to appropriate list to be visited (and turned black) later. (Open +** upvalues are already linked in 'headuv' list.) +*/ static void reallymarkobject (global_State *g, GCObject *o) { - lua_assert(iswhite(o) && !isdead(g, o)); + reentry: white2gray(o); - switch (o->gch.tt) { - case LUA_TSTRING: { - return; + switch (o->tt) { + case LUA_TSHRSTR: { + gray2black(o); + g->GCmemtrav += sizelstring(gco2ts(o)->shrlen); + break; + } + case LUA_TLNGSTR: { + gray2black(o); + g->GCmemtrav += sizelstring(gco2ts(o)->u.lnglen); + break; } case LUA_TUSERDATA: { - Table *mt = gco2u(o)->metatable; - gray2black(o); /* udata are never gray */ - if (mt) markobject(g, mt); - markobject(g, gco2u(o)->env); - return; - } - case LUA_TUPVAL: { - UpVal *uv = gco2uv(o); - markvalue(g, uv->v); - if (uv->v == &uv->u.value) /* closed? */ - gray2black(o); /* open upvalues are never black */ - return; - } - case LUA_TFUNCTION: { - gco2cl(o)->c.gclist = g->gray; - g->gray = o; + TValue uvalue; + markobjectN(g, gco2u(o)->metatable); /* mark its metatable */ + gray2black(o); + g->GCmemtrav += sizeudata(gco2u(o)); + getuservalue(g->mainthread, gco2u(o), &uvalue); + if (valiswhite(&uvalue)) { /* markvalue(g, &uvalue); */ + o = gcvalue(&uvalue); + goto reentry; + } + break; + } + case LUA_TLCL: { + linkgclist(gco2lcl(o), g->gray); + break; + } + case LUA_TCCL: { + linkgclist(gco2ccl(o), g->gray); break; } case LUA_TTABLE: { - gco2h(o)->gclist = g->gray; - g->gray = o; + linkgclist(gco2t(o), g->gray); break; } case LUA_TTHREAD: { - gco2th(o)->gclist = g->gray; - g->gray = o; + linkgclist(gco2th(o), g->gray); break; } case LUA_TPROTO: { - gco2p(o)->gclist = g->gray; - g->gray = o; + linkgclist(gco2p(o), g->gray); break; } - default: lua_assert(0); + default: lua_assert(0); break; } } -static void marktmu (global_State *g) { - GCObject *u = g->tmudata; - if (u) { - do { - u = u->gch.next; - makewhite(g, u); /* may be marked, if left from previous GC */ - reallymarkobject(g, u); - } while (u != g->tmudata); - } +/* +** mark metamethods for basic types +*/ +static void markmt (global_State *g) { + int i; + for (i=0; i < LUA_NUMTAGS; i++) + markobjectN(g, g->mt[i]); } -/* move `dead' udata that need finalization to list `tmudata' */ -size_t luaC_separateudata (lua_State *L, int all) { - global_State *g = G(L); - size_t deadmem = 0; - GCObject **p = &g->mainthread->next; - GCObject *curr; - while ((curr = *p) != NULL) { - if (!(iswhite(curr) || all) || isfinalized(gco2u(curr))) - p = &curr->gch.next; /* don't bother with them */ - else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) { - markfinalized(gco2u(curr)); /* don't need finalization */ - p = &curr->gch.next; - } - else { /* must call its gc method */ - deadmem += sizeudata(gco2u(curr)); - markfinalized(gco2u(curr)); - *p = curr->gch.next; - /* link `curr' at the end of `tmudata' list */ - if (g->tmudata == NULL) /* list is empty? */ - g->tmudata = curr->gch.next = curr; /* creates a circular list */ - else { - curr->gch.next = g->tmudata->gch.next; - g->tmudata->gch.next = curr; - g->tmudata = curr; +/* +** mark all objects in list of being-finalized +*/ +static void markbeingfnz (global_State *g) { + GCObject *o; + for (o = g->tobefnz; o != NULL; o = o->next) + markobject(g, o); +} + + +/* +** Mark all values stored in marked open upvalues from non-marked threads. +** (Values from marked threads were already marked when traversing the +** thread.) Remove from the list threads that no longer have upvalues and +** not-marked threads. +*/ +static void remarkupvals (global_State *g) { + lua_State *thread; + lua_State **p = &g->twups; + while ((thread = *p) != NULL) { + lua_assert(!isblack(thread)); /* threads are never black */ + if (isgray(thread) && thread->openupval != NULL) + p = &thread->twups; /* keep marked thread with upvalues in the list */ + else { /* thread is not marked or without upvalues */ + UpVal *uv; + *p = thread->twups; /* remove thread from the list */ + thread->twups = thread; /* mark that it is out of list */ + for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) { + if (uv->u.open.touched) { + markvalue(g, uv->v); /* remark upvalue's value */ + uv->u.open.touched = 0; + } } } } - return deadmem; } -static int traversetable (global_State *g, Table *h) { - int i; - int weakkey = 0; - int weakvalue = 0; - const TValue *mode; - if (h->metatable) - markobject(g, h->metatable); - mode = gfasttm(g, h->metatable, TM_MODE); - if (mode && ttisstring(mode)) { /* is there a weak mode? */ - weakkey = (strchr(svalue(mode), 'k') != NULL); - weakvalue = (strchr(svalue(mode), 'v') != NULL); - if (weakkey || weakvalue) { /* is really weak? */ - h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ - h->marked |= cast_byte((weakkey << KEYWEAKBIT) | - (weakvalue << VALUEWEAKBIT)); - h->gclist = g->weak; /* must be cleared after GC, ... */ - g->weak = obj2gco(h); /* ... so put in the appropriate list */ - } - } - if (weakkey && weakvalue) return 1; - if (!weakvalue) { - i = h->sizearray; - while (i--) - markvalue(g, &h->array[i]); - } - i = sizenode(h); - while (i--) { - Node *n = gnode(h, i); - lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n))); - if (ttisnil(gval(n))) - removeentry(n); /* remove empty entries */ +/* +** mark root set and reset all gray lists, to start a new collection +*/ +static void restartcollection (global_State *g) { + g->gray = g->grayagain = NULL; + g->weak = g->allweak = g->ephemeron = NULL; + markobject(g, g->mainthread); + markvalue(g, &g->l_registry); + markmt(g); + markbeingfnz(g); /* mark any finalizing object left from previous cycle */ +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Traverse functions +** ======================================================= +*/ + +/* +** Traverse a table with weak values and link it to proper list. During +** propagate phase, keep it in 'grayagain' list, to be revisited in the +** atomic phase. In the atomic phase, if table has any white value, +** put it in 'weak' list, to be cleared. +*/ +static void traverseweakvalue (global_State *g, Table *h) { + Node *n, *limit = gnodelast(h); + /* if there is array part, assume it may have white values (it is not + worth traversing it now just to check) */ + int hasclears = (h->sizearray > 0); + for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ + checkdeadkey(n); + if (ttisnil(gval(n))) /* entry is empty? */ + removeentry(n); /* remove it */ else { lua_assert(!ttisnil(gkey(n))); - if (!weakkey) markvalue(g, gkey(n)); - if (!weakvalue) markvalue(g, gval(n)); + markvalue(g, gkey(n)); /* mark key */ + if (!hasclears && iscleared(g, gval(n))) /* is there a white value? */ + hasclears = 1; /* table will have to be cleared */ } } - return weakkey || weakvalue; + if (g->gcstate == GCSpropagate) + linkgclist(h, g->grayagain); /* must retraverse it in atomic phase */ + else if (hasclears) + linkgclist(h, g->weak); /* has to be cleared later */ } /* -** All marks are conditional because a GC may happen while the -** prototype is still being created +** Traverse an ephemeron table and link it to proper list. Returns true +** iff any object was marked during this traversal (which implies that +** convergence has to continue). During propagation phase, keep table +** in 'grayagain' list, to be visited again in the atomic phase. In +** the atomic phase, if table has any white->white entry, it has to +** be revisited during ephemeron convergence (as that key may turn +** black). Otherwise, if it has any white key, table has to be cleared +** (in the atomic phase). */ -static void traverseproto (global_State *g, Proto *f) { - int i; - if (f->source) stringmark(f->source); - for (i=0; isizek; i++) /* mark literals */ - markvalue(g, &f->k[i]); - for (i=0; isizeupvalues; i++) { /* mark upvalue names */ - if (f->upvalues[i]) - stringmark(f->upvalues[i]); - } - for (i=0; isizep; i++) { /* mark nested protos */ - if (f->p[i]) - markobject(g, f->p[i]); +static int traverseephemeron (global_State *g, Table *h) { + int marked = 0; /* true if an object is marked in this traversal */ + int hasclears = 0; /* true if table has white keys */ + int hasww = 0; /* true if table has entry "white-key -> white-value" */ + Node *n, *limit = gnodelast(h); + unsigned int i; + /* traverse array part */ + for (i = 0; i < h->sizearray; i++) { + if (valiswhite(&h->array[i])) { + marked = 1; + reallymarkobject(g, gcvalue(&h->array[i])); + } } - for (i=0; isizelocvars; i++) { /* mark local-variable names */ - if (f->locvars[i].varname) - stringmark(f->locvars[i].varname); + /* traverse hash part */ + for (n = gnode(h, 0); n < limit; n++) { + checkdeadkey(n); + if (ttisnil(gval(n))) /* entry is empty? */ + removeentry(n); /* remove it */ + else if (iscleared(g, gkey(n))) { /* key is not marked (yet)? */ + hasclears = 1; /* table must be cleared */ + if (valiswhite(gval(n))) /* value not marked yet? */ + hasww = 1; /* white-white entry */ + } + else if (valiswhite(gval(n))) { /* value not marked yet? */ + marked = 1; + reallymarkobject(g, gcvalue(gval(n))); /* mark it now */ + } } + /* link table into proper list */ + if (g->gcstate == GCSpropagate) + linkgclist(h, g->grayagain); /* must retraverse it in atomic phase */ + else if (hasww) /* table has white->white entries? */ + linkgclist(h, g->ephemeron); /* have to propagate again */ + else if (hasclears) /* table has white keys? */ + linkgclist(h, g->allweak); /* may have to clean white keys */ + return marked; } - -static void traverseclosure (global_State *g, Closure *cl) { - markobject(g, cl->c.env); - if (cl->c.isC) { - int i; - for (i=0; ic.nupvalues; i++) /* mark its upvalues */ - markvalue(g, &cl->c.upvalue[i]); +static void traversestrongtable (global_State *g, Table *h) { + Node *n, *limit = gnodelast(h); + unsigned int i; + for (i = 0; i < h->sizearray; i++) /* traverse array part */ + markvalue(g, &h->array[i]); + for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ + checkdeadkey(n); + if (ttisnil(gval(n))) /* entry is empty? */ + removeentry(n); /* remove it */ + else { + lua_assert(!ttisnil(gkey(n))); + markvalue(g, gkey(n)); /* mark key */ + markvalue(g, gval(n)); /* mark value */ + } } - else { - int i; - lua_assert(cl->l.nupvalues == cl->l.p->nups); - markobject(g, cl->l.p); - for (i=0; il.nupvalues; i++) /* mark its upvalues */ - markobject(g, cl->l.upvals[i]); +} + + +static lu_mem traversetable (global_State *g, Table *h) { + const char *weakkey, *weakvalue; + const TValue *mode = gfasttm(g, h->metatable, TM_MODE); + markobjectN(g, h->metatable); + if (mode && ttisstring(mode) && /* is there a weak mode? */ + ((weakkey = strchr(svalue(mode), 'k')), + (weakvalue = strchr(svalue(mode), 'v')), + (weakkey || weakvalue))) { /* is really weak? */ + black2gray(h); /* keep table gray */ + if (!weakkey) /* strong keys? */ + traverseweakvalue(g, h); + else if (!weakvalue) /* strong values? */ + traverseephemeron(g, h); + else /* all weak */ + linkgclist(h, g->allweak); /* nothing to traverse now */ } + else /* not weak */ + traversestrongtable(g, h); + return sizeof(Table) + sizeof(TValue) * h->sizearray + + sizeof(Node) * cast(size_t, sizenode(h)); } -static void checkstacksizes (lua_State *L, StkId max) { - int ci_used = cast_int(L->ci - L->base_ci); /* number of `ci' in use */ - int s_used = cast_int(max - L->stack); /* part of stack in use */ - if (L->size_ci > LUAI_MAXCALLS) /* handling overflow? */ - return; /* do not touch the stacks */ - if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) - luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ - condhardstacktests(luaD_reallocCI(L, ci_used + 1)); - if (4*s_used < L->stacksize && - 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) - luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ - condhardstacktests(luaD_reallocstack(L, s_used)); +/* +** Traverse a prototype. (While a prototype is being build, its +** arrays can be larger than needed; the extra slots are filled with +** NULL, so the use of 'markobjectN') +*/ +static int traverseproto (global_State *g, Proto *f) { + int i; + if (f->cache && iswhite(f->cache)) + f->cache = NULL; /* allow cache to be collected */ + markobjectN(g, f->source); + for (i = 0; i < f->sizek; i++) /* mark literals */ + markvalue(g, &f->k[i]); + for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */ + markobjectN(g, f->upvalues[i].name); + for (i = 0; i < f->sizep; i++) /* mark nested protos */ + markobjectN(g, f->p[i]); + for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ + markobjectN(g, f->locvars[i].varname); + return sizeof(Proto) + sizeof(Instruction) * f->sizecode + + sizeof(Proto *) * f->sizep + + sizeof(TValue) * f->sizek + + sizeof(int) * f->sizelineinfo + + sizeof(LocVar) * f->sizelocvars + + sizeof(Upvaldesc) * f->sizeupvalues; } -static void traversestack (global_State *g, lua_State *l) { - StkId o, lim; - CallInfo *ci; - markvalue(g, gt(l)); - lim = l->top; - for (ci = l->base_ci; ci <= l->ci; ci++) { - lua_assert(ci->top <= l->stack_last); - if (lim < ci->top) lim = ci->top; +static lu_mem traverseCclosure (global_State *g, CClosure *cl) { + int i; + for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ + markvalue(g, &cl->upvalue[i]); + return sizeCclosure(cl->nupvalues); +} + +/* +** open upvalues point to values in a thread, so those values should +** be marked when the thread is traversed except in the atomic phase +** (because then the value cannot be changed by the thread and the +** thread may not be traversed again) +*/ +static lu_mem traverseLclosure (global_State *g, LClosure *cl) { + int i; + markobjectN(g, cl->p); /* mark its prototype */ + for (i = 0; i < cl->nupvalues; i++) { /* mark its upvalues */ + UpVal *uv = cl->upvals[i]; + if (uv != NULL) { + if (upisopen(uv) && g->gcstate != GCSinsideatomic) + uv->u.open.touched = 1; /* can be marked in 'remarkupvals' */ + else + markvalue(g, uv->v); + } } - for (o = l->stack; o < l->top; o++) + return sizeLclosure(cl->nupvalues); +} + + +static lu_mem traversethread (global_State *g, lua_State *th) { + StkId o = th->stack; + if (o == NULL) + return 1; /* stack not completely built yet */ + lua_assert(g->gcstate == GCSinsideatomic || + th->openupval == NULL || isintwups(th)); + for (; o < th->top; o++) /* mark live elements in the stack */ markvalue(g, o); - for (; o <= lim; o++) - setnilvalue(o); - checkstacksizes(l, lim); + if (g->gcstate == GCSinsideatomic) { /* final traversal? */ + StkId lim = th->stack + th->stacksize; /* real end of stack */ + for (; o < lim; o++) /* clear not-marked stack slice */ + setnilvalue(o); + /* 'remarkupvals' may have removed thread from 'twups' list */ + if (!isintwups(th) && th->openupval != NULL) { + th->twups = g->twups; /* link it back to the list */ + g->twups = th; + } + } + else if (g->gckind != KGC_EMERGENCY) + luaD_shrinkstack(th); /* do not change stack in emergency cycle */ + return (sizeof(lua_State) + sizeof(TValue) * th->stacksize + + sizeof(CallInfo) * th->nci); } /* -** traverse one gray object, turning it to black. -** Returns `quantity' traversed. +** traverse one gray object, turning it to black (except for threads, +** which are always gray). */ -static l_mem propagatemark (global_State *g) { +static void propagatemark (global_State *g) { + lu_mem size; GCObject *o = g->gray; lua_assert(isgray(o)); gray2black(o); - switch (o->gch.tt) { + switch (o->tt) { case LUA_TTABLE: { - Table *h = gco2h(o); - g->gray = h->gclist; - if (traversetable(g, h)) /* table is weak? */ - black2gray(o); /* keep it gray */ - return sizeof(Table) + sizeof(TValue) * h->sizearray + - sizeof(Node) * sizenode(h); - } - case LUA_TFUNCTION: { - Closure *cl = gco2cl(o); - g->gray = cl->c.gclist; - traverseclosure(g, cl); - return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) : - sizeLclosure(cl->l.nupvalues); + Table *h = gco2t(o); + g->gray = h->gclist; /* remove from 'gray' list */ + size = traversetable(g, h); + break; + } + case LUA_TLCL: { + LClosure *cl = gco2lcl(o); + g->gray = cl->gclist; /* remove from 'gray' list */ + size = traverseLclosure(g, cl); + break; + } + case LUA_TCCL: { + CClosure *cl = gco2ccl(o); + g->gray = cl->gclist; /* remove from 'gray' list */ + size = traverseCclosure(g, cl); + break; } case LUA_TTHREAD: { lua_State *th = gco2th(o); - g->gray = th->gclist; - th->gclist = g->grayagain; - g->grayagain = o; + g->gray = th->gclist; /* remove from 'gray' list */ + linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ black2gray(o); - traversestack(g, th); - return sizeof(lua_State) + sizeof(TValue) * th->stacksize + - sizeof(CallInfo) * th->size_ci; + size = traversethread(g, th); + break; } case LUA_TPROTO: { Proto *p = gco2p(o); - g->gray = p->gclist; - traverseproto(g, p); - return sizeof(Proto) + sizeof(Instruction) * p->sizecode + - sizeof(Proto *) * p->sizep + - sizeof(TValue) * p->sizek + - sizeof(int) * p->sizelineinfo + - sizeof(LocVar) * p->sizelocvars + - sizeof(TString *) * p->sizeupvalues; + g->gray = p->gclist; /* remove from 'gray' list */ + size = traverseproto(g, p); + break; } - default: lua_assert(0); return 0; + default: lua_assert(0); return; } + g->GCmemtrav += size; } -static size_t propagateall (global_State *g) { - size_t m = 0; - while (g->gray) m += propagatemark(g); - return m; +static void propagateall (global_State *g) { + while (g->gray) propagatemark(g); +} + + +static void convergeephemerons (global_State *g) { + int changed; + do { + GCObject *w; + GCObject *next = g->ephemeron; /* get ephemeron list */ + g->ephemeron = NULL; /* tables may return to this list when traversed */ + changed = 0; + while ((w = next) != NULL) { + next = gco2t(w)->gclist; + if (traverseephemeron(g, gco2t(w))) { /* traverse marked some value? */ + propagateall(g); /* propagate changes */ + changed = 1; /* will have to revisit all ephemeron tables */ + } + } + } while (changed); } +/* }====================================================== */ + /* -** The next function tells whether a key or value can be cleared from -** a weak table. Non-collectable objects are never removed from weak -** tables. Strings behave as `values', so are never removed too. for -** other objects: if really collected, cannot keep them; for userdata -** being finalized, keep them in keys, but not in values +** {====================================================== +** Sweep Functions +** ======================================================= */ -static int iscleared (const TValue *o, int iskey) { - if (!iscollectable(o)) return 0; - if (ttisstring(o)) { - stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */ - return 0; + + +/* +** clear entries with unmarked keys from all weaktables in list 'l' up +** to element 'f' +*/ +static void clearkeys (global_State *g, GCObject *l, GCObject *f) { + for (; l != f; l = gco2t(l)->gclist) { + Table *h = gco2t(l); + Node *n, *limit = gnodelast(h); + for (n = gnode(h, 0); n < limit; n++) { + if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) { + setnilvalue(gval(n)); /* remove value ... */ + removeentry(n); /* and remove entry from table */ + } + } } - return iswhite(gcvalue(o)) || - (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); } /* -** clear collected entries from weaktables +** clear entries with unmarked values from all weaktables in list 'l' up +** to element 'f' */ -static void cleartable (GCObject *l) { - while (l) { - Table *h = gco2h(l); - int i = h->sizearray; - lua_assert(testbit(h->marked, VALUEWEAKBIT) || - testbit(h->marked, KEYWEAKBIT)); - if (testbit(h->marked, VALUEWEAKBIT)) { - while (i--) { - TValue *o = &h->array[i]; - if (iscleared(o, 0)) /* value was collected? */ - setnilvalue(o); /* remove value */ - } +static void clearvalues (global_State *g, GCObject *l, GCObject *f) { + for (; l != f; l = gco2t(l)->gclist) { + Table *h = gco2t(l); + Node *n, *limit = gnodelast(h); + unsigned int i; + for (i = 0; i < h->sizearray; i++) { + TValue *o = &h->array[i]; + if (iscleared(g, o)) /* value was collected? */ + setnilvalue(o); /* remove value */ } - i = sizenode(h); - while (i--) { - Node *n = gnode(h, i); - if (!ttisnil(gval(n)) && /* non-empty entry? */ - (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) { + for (n = gnode(h, 0); n < limit; n++) { + if (!ttisnil(gval(n)) && iscleared(g, gval(n))) { setnilvalue(gval(n)); /* remove value ... */ - removeentry(n); /* remove entry from table */ + removeentry(n); /* and remove entry from table */ } } - l = h->gclist; } } +void luaC_upvdeccount (lua_State *L, UpVal *uv) { + lua_assert(uv->refcount > 0); + uv->refcount--; + if (uv->refcount == 0 && !upisopen(uv)) + luaM_free(L, uv); +} + + +static void freeLclosure (lua_State *L, LClosure *cl) { + int i; + for (i = 0; i < cl->nupvalues; i++) { + UpVal *uv = cl->upvals[i]; + if (uv) + luaC_upvdeccount(L, uv); + } + luaM_freemem(L, cl, sizeLclosure(cl->nupvalues)); +} + + static void freeobj (lua_State *L, GCObject *o) { - switch (o->gch.tt) { + switch (o->tt) { case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; - case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; - case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; - case LUA_TTABLE: luaH_free(L, gco2h(o)); break; - case LUA_TTHREAD: { - lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread); - luaE_freethread(L, gco2th(o)); + case LUA_TLCL: { + freeLclosure(L, gco2lcl(o)); break; } - case LUA_TSTRING: { - G(L)->strt.nuse--; - luaM_freemem(L, o, sizestring(gco2ts(o))); + case LUA_TCCL: { + luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); break; } - case LUA_TUSERDATA: { - luaM_freemem(L, o, sizeudata(gco2u(o))); + case LUA_TTABLE: luaH_free(L, gco2t(o)); break; + case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break; + case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; + case LUA_TSHRSTR: + luaS_remove(L, gco2ts(o)); /* remove it from hash table */ + luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen)); + break; + case LUA_TLNGSTR: { + luaM_freemem(L, o, sizelstring(gco2ts(o)->u.lnglen)); break; } default: lua_assert(0); @@ -400,205 +720,372 @@ static void freeobj (lua_State *L, GCObject *o) { } - #define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) +static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count); +/* +** sweep at most 'count' elements from a list of GCObjects erasing dead +** objects, where a dead object is one marked with the old (non current) +** white; change all non-dead objects back to white, preparing for next +** collection cycle. Return where to continue the traversal or NULL if +** list is finished. +*/ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { - GCObject *curr; global_State *g = G(L); - int deadmask = otherwhite(g); - while ((curr = *p) != NULL && count-- > 0) { - if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */ - sweepwholelist(L, &gco2th(curr)->openupval); - if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */ - lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT)); - makewhite(g, curr); /* make it white (for next cycle) */ - p = &curr->gch.next; - } - else { /* must erase `curr' */ - lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); - *p = curr->gch.next; - if (curr == g->rootgc) /* is the first element of the list? */ - g->rootgc = curr->gch.next; /* adjust first */ - freeobj(L, curr); + int ow = otherwhite(g); + int white = luaC_white(g); /* current white */ + while (*p != NULL && count-- > 0) { + GCObject *curr = *p; + int marked = curr->marked; + if (isdeadm(ow, marked)) { /* is 'curr' dead? */ + *p = curr->next; /* remove 'curr' from list */ + freeobj(L, curr); /* erase 'curr' */ + } + else { /* change mark to 'white' */ + curr->marked = cast_byte((marked & maskcolors) | white); + p = &curr->next; /* go to next element */ } } + return (*p == NULL) ? NULL : p; +} + + +/* +** sweep a list until a live object (or end of list) +*/ +static GCObject **sweeptolive (lua_State *L, GCObject **p) { + GCObject **old = p; + do { + p = sweeplist(L, p, 1); + } while (p == old); return p; } +/* }====================================================== */ -static void checkSizes (lua_State *L) { - global_State *g = G(L); - /* check size of string hash */ - if (g->strt.nuse < cast(lu_int32, g->strt.size/4) && - g->strt.size > MINSTRTABSIZE*2) - luaS_resize(L, g->strt.size/2); /* table is too big */ - /* check size of buffer */ - if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */ - size_t newsize = luaZ_sizebuffer(&g->buff) / 2; - luaZ_resizebuffer(L, &g->buff, newsize); + +/* +** {====================================================== +** Finalization +** ======================================================= +*/ + +/* +** If possible, shrink string table +*/ +static void checkSizes (lua_State *L, global_State *g) { + if (g->gckind != KGC_EMERGENCY) { + l_mem olddebt = g->GCdebt; + if (g->strt.nuse < g->strt.size / 4) /* string table too big? */ + luaS_resize(L, g->strt.size / 2); /* shrink it a little */ + g->GCestimate += g->GCdebt - olddebt; /* update estimate */ } } -static void GCTM (lua_State *L) { +static GCObject *udata2finalize (global_State *g) { + GCObject *o = g->tobefnz; /* get first element */ + lua_assert(tofinalize(o)); + g->tobefnz = o->next; /* remove it from 'tobefnz' list */ + o->next = g->allgc; /* return it to 'allgc' list */ + g->allgc = o; + resetbit(o->marked, FINALIZEDBIT); /* object is "normal" again */ + if (issweepphase(g)) + makewhite(g, o); /* "sweep" object */ + return o; +} + + +static void dothecall (lua_State *L, void *ud) { + UNUSED(ud); + luaD_callnoyield(L, L->top - 2, 0); +} + + +static void GCTM (lua_State *L, int propagateerrors) { global_State *g = G(L); - GCObject *o = g->tmudata->gch.next; /* get first element */ - Udata *udata = rawgco2u(o); const TValue *tm; - /* remove udata from `tmudata' */ - if (o == g->tmudata) /* last element? */ - g->tmudata = NULL; - else - g->tmudata->gch.next = udata->uv.next; - udata->uv.next = g->mainthread->next; /* return it to `root' list */ - g->mainthread->next = o; - makewhite(g, o); - tm = fasttm(L, udata->uv.metatable, TM_GC); - if (tm != NULL) { + TValue v; + setgcovalue(L, &v, udata2finalize(g)); + tm = luaT_gettmbyobj(L, &v, TM_GC); + if (tm != NULL && ttisfunction(tm)) { /* is there a finalizer? */ + int status; lu_byte oldah = L->allowhook; - lu_mem oldt = g->GCthreshold; - L->allowhook = 0; /* stop debug hooks during GC tag method */ - g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */ - setobj2s(L, L->top, tm); - setuvalue(L, L->top+1, udata); - L->top += 2; - luaD_call(L, L->top - 2, 0); + int running = g->gcrunning; + L->allowhook = 0; /* stop debug hooks during GC metamethod */ + g->gcrunning = 0; /* avoid GC steps */ + setobj2s(L, L->top, tm); /* push finalizer... */ + setobj2s(L, L->top + 1, &v); /* ... and its argument */ + L->top += 2; /* and (next line) call the finalizer */ + status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); L->allowhook = oldah; /* restore hooks */ - g->GCthreshold = oldt; /* restore threshold */ + g->gcrunning = running; /* restore state */ + if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ + if (status == LUA_ERRRUN) { /* is there an error object? */ + const char *msg = (ttisstring(L->top - 1)) + ? svalue(L->top - 1) + : "no message"; + luaO_pushfstring(L, "error in __gc metamethod (%s)", msg); + status = LUA_ERRGCMM; /* error in __gc metamethod */ + } + luaD_throw(L, status); /* re-throw error */ + } } } /* -** Call all GC tag methods +** call a few (up to 'g->gcfinnum') finalizers */ -void luaC_callGCTM (lua_State *L) { - while (G(L)->tmudata) - GCTM(L); +static int runafewfinalizers (lua_State *L) { + global_State *g = G(L); + unsigned int i; + lua_assert(!g->tobefnz || g->gcfinnum > 0); + for (i = 0; g->tobefnz && i < g->gcfinnum; i++) + GCTM(L, 1); /* call one finalizer */ + g->gcfinnum = (!g->tobefnz) ? 0 /* nothing more to finalize? */ + : g->gcfinnum * 2; /* else call a few more next time */ + return i; } -void luaC_freeall (lua_State *L) { +/* +** call all pending finalizers +*/ +static void callallpendingfinalizers (lua_State *L) { global_State *g = G(L); - int i; - g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); /* mask to collect all elements */ - sweepwholelist(L, &g->rootgc); - for (i = 0; i < g->strt.size; i++) /* free all string lists */ - sweepwholelist(L, &g->strt.hash[i]); + while (g->tobefnz) + GCTM(L, 0); } -static void markmt (global_State *g) { - int i; - for (i=0; imt[i]) markobject(g, g->mt[i]); +/* +** find last 'next' field in list 'p' list (to add elements in its end) +*/ +static GCObject **findlast (GCObject **p) { + while (*p != NULL) + p = &(*p)->next; + return p; } -/* mark root set */ -static void markroot (lua_State *L) { - global_State *g = G(L); - g->gray = NULL; - g->grayagain = NULL; - g->weak = NULL; - markobject(g, g->mainthread); - /* make global table be traversed before main stack */ - markvalue(g, gt(g->mainthread)); - markvalue(g, registry(L)); - markmt(g); - g->gcstate = GCSpropagate; +/* +** move all unreachable objects (or 'all' objects) that need +** finalization from list 'finobj' to list 'tobefnz' (to be finalized) +*/ +static void separatetobefnz (global_State *g, int all) { + GCObject *curr; + GCObject **p = &g->finobj; + GCObject **lastnext = findlast(&g->tobefnz); + while ((curr = *p) != NULL) { /* traverse all finalizable objects */ + lua_assert(tofinalize(curr)); + if (!(iswhite(curr) || all)) /* not being collected? */ + p = &curr->next; /* don't bother with it */ + else { + *p = curr->next; /* remove 'curr' from 'finobj' list */ + curr->next = *lastnext; /* link at the end of 'tobefnz' list */ + *lastnext = curr; + lastnext = &curr->next; + } + } } -static void remarkupvals (global_State *g) { - UpVal *uv; - for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { - lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); - if (isgray(obj2gco(uv))) - markvalue(g, uv->v); +/* +** if object 'o' has a finalizer, remove it from 'allgc' list (must +** search the list to find it) and link it in 'finobj' list. +*/ +void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { + global_State *g = G(L); + if (tofinalize(o) || /* obj. is already marked... */ + gfasttm(g, mt, TM_GC) == NULL) /* or has no finalizer? */ + return; /* nothing to be done */ + else { /* move 'o' to 'finobj' list */ + GCObject **p; + if (issweepphase(g)) { + makewhite(g, o); /* "sweep" object 'o' */ + if (g->sweepgc == &o->next) /* should not remove 'sweepgc' object */ + g->sweepgc = sweeptolive(L, g->sweepgc); /* change 'sweepgc' */ + } + /* search for pointer pointing to 'o' */ + for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ } + *p = o->next; /* remove 'o' from 'allgc' list */ + o->next = g->finobj; /* link it in 'finobj' list */ + g->finobj = o; + l_setbit(o->marked, FINALIZEDBIT); /* mark it as such */ } } +/* }====================================================== */ + + + +/* +** {====================================================== +** GC control +** ======================================================= +*/ + + +/* +** Set a reasonable "time" to wait before starting a new GC cycle; cycle +** will start when memory use hits threshold. (Division by 'estimate' +** should be OK: it cannot be zero (because Lua cannot even start with +** less than PAUSEADJ bytes). +*/ +static void setpause (global_State *g) { + l_mem threshold, debt; + l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */ + lua_assert(estimate > 0); + threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */ + ? estimate * g->gcpause /* no overflow */ + : MAX_LMEM; /* overflow; truncate to maximum */ + debt = gettotalbytes(g) - threshold; + luaE_setdebt(g, debt); +} -static void atomic (lua_State *L) { + +/* +** Enter first sweep phase. +** The call to 'sweeplist' tries to make pointer point to an object +** inside the list (instead of to the header), so that the real sweep do +** not need to skip objects created between "now" and the start of the +** real sweep. +*/ +static void entersweep (lua_State *L) { + global_State *g = G(L); + g->gcstate = GCSswpallgc; + lua_assert(g->sweepgc == NULL); + g->sweepgc = sweeplist(L, &g->allgc, 1); +} + + +void luaC_freeallobjects (lua_State *L) { global_State *g = G(L); - size_t udsize; /* total size of userdata to be finalized */ + separatetobefnz(g, 1); /* separate all objects with finalizers */ + lua_assert(g->finobj == NULL); + callallpendingfinalizers(L); + lua_assert(g->tobefnz == NULL); + g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ + g->gckind = KGC_NORMAL; + sweepwholelist(L, &g->finobj); + sweepwholelist(L, &g->allgc); + sweepwholelist(L, &g->fixedgc); /* collect fixed objects */ + lua_assert(g->strt.nuse == 0); +} + + +static l_mem atomic (lua_State *L) { + global_State *g = G(L); + l_mem work; + GCObject *origweak, *origall; + GCObject *grayagain = g->grayagain; /* save original list */ + lua_assert(g->ephemeron == NULL && g->weak == NULL); + lua_assert(!iswhite(g->mainthread)); + g->gcstate = GCSinsideatomic; + g->GCmemtrav = 0; /* start counting work */ + markobject(g, L); /* mark running thread */ + /* registry and global metatables may be changed by API */ + markvalue(g, &g->l_registry); + markmt(g); /* mark global metatables */ /* remark occasional upvalues of (maybe) dead threads */ remarkupvals(g); - /* traverse objects cautch by write barrier and by 'remarkupvals' */ - propagateall(g); - /* remark weak tables */ - g->gray = g->weak; - g->weak = NULL; - lua_assert(!iswhite(obj2gco(g->mainthread))); - markobject(g, L); /* mark running thread */ - markmt(g); /* mark basic metatables (again) */ - propagateall(g); - /* remark gray again */ - g->gray = g->grayagain; - g->grayagain = NULL; - propagateall(g); - udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */ - marktmu(g); /* mark `preserved' userdata */ - udsize += propagateall(g); /* remark, to propagate `preserveness' */ - cleartable(g->weak); /* remove collected objects from weak tables */ - /* flip current white */ - g->currentwhite = cast_byte(otherwhite(g)); - g->sweepstrgc = 0; - g->sweepgc = &g->rootgc; - g->gcstate = GCSsweepstring; - g->estimate = g->totalbytes - udsize; /* first estimate */ -} - - -static l_mem singlestep (lua_State *L) { + propagateall(g); /* propagate changes */ + work = g->GCmemtrav; /* stop counting (do not recount 'grayagain') */ + g->gray = grayagain; + propagateall(g); /* traverse 'grayagain' list */ + g->GCmemtrav = 0; /* restart counting */ + convergeephemerons(g); + /* at this point, all strongly accessible objects are marked. */ + /* Clear values from weak tables, before checking finalizers */ + clearvalues(g, g->weak, NULL); + clearvalues(g, g->allweak, NULL); + origweak = g->weak; origall = g->allweak; + work += g->GCmemtrav; /* stop counting (objects being finalized) */ + separatetobefnz(g, 0); /* separate objects to be finalized */ + g->gcfinnum = 1; /* there may be objects to be finalized */ + markbeingfnz(g); /* mark objects that will be finalized */ + propagateall(g); /* remark, to propagate 'resurrection' */ + g->GCmemtrav = 0; /* restart counting */ + convergeephemerons(g); + /* at this point, all resurrected objects are marked. */ + /* remove dead objects from weak tables */ + clearkeys(g, g->ephemeron, NULL); /* clear keys from all ephemeron tables */ + clearkeys(g, g->allweak, NULL); /* clear keys from all 'allweak' tables */ + /* clear values from resurrected weak tables */ + clearvalues(g, g->weak, origweak); + clearvalues(g, g->allweak, origall); + luaS_clearcache(g); + g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ + work += g->GCmemtrav; /* complete counting */ + return work; /* estimate of memory marked by 'atomic' */ +} + + +static lu_mem sweepstep (lua_State *L, global_State *g, + int nextstate, GCObject **nextlist) { + if (g->sweepgc) { + l_mem olddebt = g->GCdebt; + g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); + g->GCestimate += g->GCdebt - olddebt; /* update estimate */ + if (g->sweepgc) /* is there still something to sweep? */ + return (GCSWEEPMAX * GCSWEEPCOST); + } + /* else enter next state */ + g->gcstate = nextstate; + g->sweepgc = nextlist; + return 0; +} + + +static lu_mem singlestep (lua_State *L) { global_State *g = G(L); - /*lua_checkmemory(L);*/ switch (g->gcstate) { case GCSpause: { - markroot(L); /* start a new collection */ - return 0; + g->GCmemtrav = g->strt.size * sizeof(GCObject*); + restartcollection(g); + g->gcstate = GCSpropagate; + return g->GCmemtrav; } case GCSpropagate: { - if (g->gray) - return propagatemark(g); - else { /* no more `gray' objects */ - atomic(L); /* finish mark phase */ - return 0; - } + g->GCmemtrav = 0; + lua_assert(g->gray); + propagatemark(g); + if (g->gray == NULL) /* no more gray objects? */ + g->gcstate = GCSatomic; /* finish propagate phase */ + return g->GCmemtrav; /* memory traversed in this step */ } - case GCSsweepstring: { - lu_mem old = g->totalbytes; - sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); - if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */ - g->gcstate = GCSsweep; /* end sweep-string phase */ - lua_assert(old >= g->totalbytes); - g->estimate -= old - g->totalbytes; - return GCSWEEPCOST; - } - case GCSsweep: { - lu_mem old = g->totalbytes; - g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); - if (*g->sweepgc == NULL) { /* nothing more to sweep? */ - checkSizes(L); - g->gcstate = GCSfinalize; /* end sweep phase */ - } - lua_assert(old >= g->totalbytes); - g->estimate -= old - g->totalbytes; - return GCSWEEPMAX*GCSWEEPCOST; - } - case GCSfinalize: { - if (g->tmudata) { - GCTM(L); - if (g->estimate > GCFINALIZECOST) - g->estimate -= GCFINALIZECOST; - return GCFINALIZECOST; + case GCSatomic: { + lu_mem work; + propagateall(g); /* make sure gray list is empty */ + work = atomic(L); /* work is what was traversed by 'atomic' */ + entersweep(L); + g->GCestimate = gettotalbytes(g); /* first estimate */; + return work; + } + case GCSswpallgc: { /* sweep "regular" objects */ + return sweepstep(L, g, GCSswpfinobj, &g->finobj); + } + case GCSswpfinobj: { /* sweep objects with finalizers */ + return sweepstep(L, g, GCSswptobefnz, &g->tobefnz); + } + case GCSswptobefnz: { /* sweep objects to be finalized */ + return sweepstep(L, g, GCSswpend, NULL); + } + case GCSswpend: { /* finish sweeps */ + makewhite(g, g->mainthread); /* sweep main thread */ + checkSizes(L, g); + g->gcstate = GCScallfin; + return 0; + } + case GCScallfin: { /* call remaining finalizers */ + if (g->tobefnz && g->gckind != KGC_EMERGENCY) { + int n = runafewfinalizers(L); + return (n * GCFINALIZECOST); } - else { - g->gcstate = GCSpause; /* end collection */ - g->gcdept = 0; + else { /* emergency mode or no more finalizers */ + g->gcstate = GCSpause; /* finish collection */ return 0; } } @@ -607,104 +1094,83 @@ static l_mem singlestep (lua_State *L) { } -void luaC_step (lua_State *L) { - global_State *g = G(L); - l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; - if (lim == 0) - lim = (MAX_LUMEM-1)/2; /* no limit */ - g->gcdept += g->totalbytes - g->GCthreshold; - do { - lim -= singlestep(L); - if (g->gcstate == GCSpause) - break; - } while (lim > 0); - if (g->gcstate != GCSpause) { - if (g->gcdept < GCSTEPSIZE) - g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/g->gcstepmul;*/ - else { - g->gcdept -= GCSTEPSIZE; - g->GCthreshold = g->totalbytes; - } - } - else { - setthreshold(g); - } -} - - -void luaC_fullgc (lua_State *L) { +/* +** advances the garbage collector until it reaches a state allowed +** by 'statemask' +*/ +void luaC_runtilstate (lua_State *L, int statesmask) { global_State *g = G(L); - if (g->gcstate <= GCSpropagate) { - /* reset sweep marks to sweep all elements (returning them to white) */ - g->sweepstrgc = 0; - g->sweepgc = &g->rootgc; - /* reset other collector lists */ - g->gray = NULL; - g->grayagain = NULL; - g->weak = NULL; - g->gcstate = GCSsweepstring; - } - lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate); - /* finish any pending sweep phase */ - while (g->gcstate != GCSfinalize) { - lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); + while (!testbit(statesmask, g->gcstate)) singlestep(L); - } - markroot(L); - while (g->gcstate != GCSpause) { - singlestep(L); - } - setthreshold(g); } -void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { - global_State *g = G(L); - lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); - lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); - lua_assert(ttype(&o->gch) != LUA_TTABLE); - /* must keep invariant? */ - if (g->gcstate == GCSpropagate) - reallymarkobject(g, v); /* restore invariant */ - else /* don't mind */ - makewhite(g, o); /* mark as white just to avoid other barriers */ +/* +** get GC debt and convert it from Kb to 'work units' (avoid zero debt +** and overflows) +*/ +static l_mem getdebt (global_State *g) { + l_mem debt = g->GCdebt; + int stepmul = g->gcstepmul; + if (debt <= 0) return 0; /* minimal debt */ + else { + debt = (debt / STEPMULADJ) + 1; + debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM; + return debt; + } } - -void luaC_barrierback (lua_State *L, Table *t) { +/* +** performs a basic GC step when collector is running +*/ +void luaC_step (lua_State *L) { global_State *g = G(L); - GCObject *o = obj2gco(t); - lua_assert(isblack(o) && !isdead(g, o)); - lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); - black2gray(o); /* make table gray (again) */ - t->gclist = g->grayagain; - g->grayagain = o; + l_mem debt = getdebt(g); /* GC deficit (be paid now) */ + if (!g->gcrunning) { /* not running? */ + luaE_setdebt(g, -GCSTEPSIZE * 10); /* avoid being called too often */ + return; + } + do { /* repeat until pause or enough "credit" (negative debt) */ + lu_mem work = singlestep(L); /* perform one single step */ + debt -= work; + } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause); + if (g->gcstate == GCSpause) + setpause(g); /* pause until next cycle */ + else { + debt = (debt / g->gcstepmul) * STEPMULADJ; /* convert 'work units' to Kb */ + luaE_setdebt(g, debt); + runafewfinalizers(L); + } } -void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { +/* +** Performs a full GC cycle; if 'isemergency', set a flag to avoid +** some operations which could change the interpreter state in some +** unexpected ways (running finalizers and shrinking some structures). +** Before running the collection, check 'keepinvariant'; if it is true, +** there may be some objects marked as black, so the collector has +** to sweep all objects to turn them back to white (as white has not +** changed, nothing will be collected). +*/ +void luaC_fullgc (lua_State *L, int isemergency) { global_State *g = G(L); - o->gch.next = g->rootgc; - g->rootgc = o; - o->gch.marked = luaC_white(g); - o->gch.tt = tt; + lua_assert(g->gckind == KGC_NORMAL); + if (isemergency) g->gckind = KGC_EMERGENCY; /* set flag */ + if (keepinvariant(g)) { /* black objects? */ + entersweep(L); /* sweep everything to turn them back to white */ + } + /* finish any pending sweep phase to start a new cycle */ + luaC_runtilstate(L, bitmask(GCSpause)); + luaC_runtilstate(L, ~bitmask(GCSpause)); /* start new collection */ + luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */ + /* estimate must be correct after a full GC cycle */ + lua_assert(g->GCestimate == gettotalbytes(g)); + luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ + g->gckind = KGC_NORMAL; + setpause(g); } +/* }====================================================== */ -void luaC_linkupval (lua_State *L, UpVal *uv) { - global_State *g = G(L); - GCObject *o = obj2gco(uv); - o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */ - g->rootgc = o; - if (isgray(o)) { - if (g->gcstate == GCSpropagate) { - gray2black(o); /* closed upvalues need barrier */ - luaC_barrier(L, uv, uv->v); - } - else { /* sweep phase: sweep it (turning it into white) */ - makewhite(g, o); - lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); - } - } -} diff --git a/app/src/main/jni/lua/lgc.h b/app/src/main/jni/lua/lgc.h index 5a8dc60..aed3e18 100644 --- a/app/src/main/jni/lua/lgc.h +++ b/app/src/main/jni/lua/lgc.h @@ -1,5 +1,5 @@ /* -** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lgc.h,v 2.91 2015/12/21 13:02:14 roberto Exp $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -9,102 +9,139 @@ #include "lobject.h" +#include "lstate.h" + +/* +** Collectable objects may have one of three colors: white, which +** means the object is not marked; gray, which means the +** object is marked, but its references may be not marked; and +** black, which means that the object and all its references are marked. +** The main invariant of the garbage collector, while marking objects, +** is that a black object can never point to a white one. Moreover, +** any gray object must be in a "gray list" (gray, grayagain, weak, +** allweak, ephemeron) so that it can be visited again before finishing +** the collection cycle. These lists have no meaning when the invariant +** is not being enforced (e.g., sweep phase). +*/ + + + +/* how much to allocate before next GC step */ +#if !defined(GCSTEPSIZE) +/* ~100 small strings */ +#define GCSTEPSIZE (cast_int(100 * sizeof(TString))) +#endif /* ** Possible states of the Garbage Collector */ -#define GCSpause 0 -#define GCSpropagate 1 -#define GCSsweepstring 2 -#define GCSsweep 3 -#define GCSfinalize 4 +#define GCSpropagate 0 +#define GCSatomic 1 +#define GCSswpallgc 2 +#define GCSswpfinobj 3 +#define GCSswptobefnz 4 +#define GCSswpend 5 +#define GCScallfin 6 +#define GCSpause 7 + + +#define issweepphase(g) \ + (GCSswpallgc <= (g)->gcstate && (g)->gcstate <= GCSswpend) /* -** some userful bit tricks +** macro to tell when main invariant (white objects cannot point to black +** ones) must be kept. During a collection, the sweep +** phase may break the invariant, as objects turned white may point to +** still-black objects. The invariant is restored when sweep ends and +** all objects are white again. */ -#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) -#define setbits(x,m) ((x) |= (m)) -#define testbits(x,m) ((x) & (m)) -#define bitmask(b) (1<<(b)) -#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) -#define l_setbit(x,b) setbits(x, bitmask(b)) -#define resetbit(x,b) resetbits(x, bitmask(b)) -#define testbit(x,b) testbits(x, bitmask(b)) -#define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2))) -#define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2))) -#define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2))) +#define keepinvariant(g) ((g)->gcstate <= GCSatomic) /* -** Layout for bit use in `marked' field: -** bit 0 - object is white (type 0) -** bit 1 - object is white (type 1) -** bit 2 - object is black -** bit 3 - for userdata: has been finalized -** bit 3 - for tables: has weak keys -** bit 4 - for tables: has weak values -** bit 5 - object is fixed (should not be collected) -** bit 6 - object is "super" fixed (only the main thread) +** some useful bit tricks */ +#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) +#define setbits(x,m) ((x) |= (m)) +#define testbits(x,m) ((x) & (m)) +#define bitmask(b) (1<<(b)) +#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) +#define l_setbit(x,b) setbits(x, bitmask(b)) +#define resetbit(x,b) resetbits(x, bitmask(b)) +#define testbit(x,b) testbits(x, bitmask(b)) + + +/* Layout for bit use in 'marked' field: */ +#define WHITE0BIT 0 /* object is white (type 0) */ +#define WHITE1BIT 1 /* object is white (type 1) */ +#define BLACKBIT 2 /* object is black */ +#define FINALIZEDBIT 3 /* object has been marked for finalization */ +/* bit 7 is currently used by tests (luaL_checkmemory) */ - -#define WHITE0BIT 0 -#define WHITE1BIT 1 -#define BLACKBIT 2 -#define FINALIZEDBIT 3 -#define KEYWEAKBIT 3 -#define VALUEWEAKBIT 4 -#define FIXEDBIT 5 -#define SFIXEDBIT 6 #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) -#define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) -#define isblack(x) testbit((x)->gch.marked, BLACKBIT) -#define isgray(x) (!isblack(x) && !iswhite(x)) +#define iswhite(x) testbits((x)->marked, WHITEBITS) +#define isblack(x) testbit((x)->marked, BLACKBIT) +#define isgray(x) /* neither white nor black */ \ + (!testbits((x)->marked, WHITEBITS | bitmask(BLACKBIT))) -#define otherwhite(g) (g->currentwhite ^ WHITEBITS) -#define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) +#define tofinalize(x) testbit((x)->marked, FINALIZEDBIT) -#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) -#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) +#define otherwhite(g) ((g)->currentwhite ^ WHITEBITS) +#define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow))) +#define isdead(g,v) isdeadm(otherwhite(g), (v)->marked) -#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) +#define changewhite(x) ((x)->marked ^= WHITEBITS) +#define gray2black(x) l_setbit((x)->marked, BLACKBIT) #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) -#define luaC_checkGC(L) { \ - condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ - if (G(L)->totalbytes >= G(L)->GCthreshold) \ - luaC_step(L); } +/* +** Does one step of collection when debt becomes positive. 'pre'/'pos' +** allows some adjustments to be done only when needed. macro +** 'condchangemem' is used only for heavy tests (forcing a full +** GC cycle on every opportunity) +*/ +#define luaC_condGC(L,pre,pos) \ + { if (G(L)->GCdebt > 0) { pre; luaC_step(L); pos;}; \ + condchangemem(L,pre,pos); } + +/* more often than not, 'pre'/'pos' are empty */ +#define luaC_checkGC(L) luaC_condGC(L,(void)0,(void)0) -#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ - luaC_barrierf(L,obj2gco(p),gcvalue(v)); } +#define luaC_barrier(L,p,v) ( \ + (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \ + luaC_barrier_(L,obj2gco(p),gcvalue(v)) : cast_void(0)) -#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \ - luaC_barrierback(L,t); } +#define luaC_barrierback(L,p,v) ( \ + (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \ + luaC_barrierback_(L,p) : cast_void(0)) -#define luaC_objbarrier(L,p,o) \ - { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ - luaC_barrierf(L,obj2gco(p),obj2gco(o)); } +#define luaC_objbarrier(L,p,o) ( \ + (isblack(p) && iswhite(o)) ? \ + luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0)) -#define luaC_objbarriert(L,t,o) \ - { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); } +#define luaC_upvalbarrier(L,uv) ( \ + (iscollectable((uv)->v) && !upisopen(uv)) ? \ + luaC_upvalbarrier_(L,uv) : cast_void(0)) -LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all); -LUAI_FUNC void luaC_callGCTM (lua_State *L); -LUAI_FUNC void luaC_freeall (lua_State *L); +LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o); +LUAI_FUNC void luaC_freeallobjects (lua_State *L); LUAI_FUNC void luaC_step (lua_State *L); -LUAI_FUNC void luaC_fullgc (lua_State *L); -LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt); -LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); -LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); -LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); +LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); +LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); +LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz); +LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); +LUAI_FUNC void luaC_barrierback_ (lua_State *L, Table *o); +LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv); +LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); +LUAI_FUNC void luaC_upvdeccount (lua_State *L, UpVal *uv); #endif diff --git a/app/src/main/jni/lua/linit.c b/app/src/main/jni/lua/linit.c index c1f90df..8ce94cc 100644 --- a/app/src/main/jni/lua/linit.c +++ b/app/src/main/jni/lua/linit.c @@ -1,6 +1,6 @@ /* -** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $ -** Initialization of libraries for lua.c +** $Id: linit.c,v 1.38 2015/01/05 13:48:33 roberto Exp $ +** Initialization of libraries for lua.c and other clients ** See Copyright Notice in lua.h */ @@ -8,31 +8,61 @@ #define linit_c #define LUA_LIB +/* +** If you embed Lua in your program and need to open the standard +** libraries, call luaL_openlibs in your program. If you need a +** different set of libraries, copy this file to your project and edit +** it to suit your needs. +** +** You can also *preload* libraries, so that a later 'require' can +** open the library, which is already linked to the application. +** For that, do the following code: +** +** luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD"); +** lua_pushcfunction(L, luaopen_modname); +** lua_setfield(L, -2, modname); +** lua_pop(L, 1); // remove _PRELOAD table +*/ + +#include "lprefix.h" + + +#include + #include "lua.h" #include "lualib.h" #include "lauxlib.h" -static const luaL_Reg lualibs[] = { - {"", luaopen_base}, +/* +** these libs are loaded by lua.c and are readily available to any Lua +** program +*/ +static const luaL_Reg loadedlibs[] = { + {"_G", luaopen_base}, {LUA_LOADLIBNAME, luaopen_package}, + {LUA_COLIBNAME, luaopen_coroutine}, {LUA_TABLIBNAME, luaopen_table}, {LUA_IOLIBNAME, luaopen_io}, {LUA_OSLIBNAME, luaopen_os}, {LUA_STRLIBNAME, luaopen_string}, {LUA_MATHLIBNAME, luaopen_math}, + {LUA_UTF8LIBNAME, luaopen_utf8}, {LUA_DBLIBNAME, luaopen_debug}, +#if defined(LUA_COMPAT_BITLIB) + {LUA_BITLIBNAME, luaopen_bit32}, +#endif {NULL, NULL} }; LUALIB_API void luaL_openlibs (lua_State *L) { - const luaL_Reg *lib = lualibs; - for (; lib->func; lib++) { - lua_pushcfunction(L, lib->func); - lua_pushstring(L, lib->name); - lua_call(L, 1, 0); + const luaL_Reg *lib; + /* "require" functions from 'loadedlibs' and set results to global table */ + for (lib = loadedlibs; lib->func; lib++) { + luaL_requiref(L, lib->name, lib->func, 1); + lua_pop(L, 1); /* remove lib */ } } diff --git a/app/src/main/jni/lua/liolib.c b/app/src/main/jni/lua/liolib.c index 649f9a5..aa78e59 100644 --- a/app/src/main/jni/lua/liolib.c +++ b/app/src/main/jni/lua/liolib.c @@ -1,18 +1,22 @@ /* -** $Id: liolib.c,v 2.73.1.4 2010/05/14 15:33:51 roberto Exp $ +** $Id: liolib.c,v 2.149 2016/05/02 14:03:19 roberto Exp $ ** Standard I/O (and system) library ** See Copyright Notice in lua.h */ +#define liolib_c +#define LUA_LIB + +#include "lprefix.h" + +#include #include +#include #include #include #include -#define liolib_c -#define LUA_LIB - #include "lua.h" #include "lauxlib.h" @@ -20,48 +24,135 @@ -#define IO_INPUT 1 -#define IO_OUTPUT 2 +/* +** Change this macro to accept other modes for 'fopen' besides +** the standard ones. +*/ +#if !defined(l_checkmode) -static const char *const fnames[] = {"input", "output"}; +/* accepted extensions to 'mode' in 'fopen' */ +#if !defined(L_MODEEXT) +#define L_MODEEXT "b" +#endif +/* Check whether 'mode' matches '[rwa]%+?[L_MODEEXT]*' */ +#define l_checkmode(mode) \ + (*mode != '\0' && strchr("rwa", *(mode++)) != NULL && \ + (*mode != '+' || (++mode, 1)) && /* skip if char is '+' */ \ + (strspn(mode, L_MODEEXT) == strlen(mode))) -static int pushresult (lua_State *L, int i, const char *filename) { - int en = errno; /* calls to Lua API may change this value */ - if (i) { - lua_pushboolean(L, 1); - return 1; - } - else { - lua_pushnil(L); - if (filename) - lua_pushfstring(L, "%s: %s", filename, strerror(en)); - else - lua_pushfstring(L, "%s", strerror(en)); - lua_pushinteger(L, en); - return 3; - } -} +#endif +/* +** {====================================================== +** l_popen spawns a new process connected to the current +** one through the file streams. +** ======================================================= +*/ -static void fileerror (lua_State *L, int arg, const char *filename) { - lua_pushfstring(L, "%s: %s", filename, strerror(errno)); - luaL_argerror(L, arg, lua_tostring(L, -1)); -} +#if !defined(l_popen) /* { */ + +#if defined(LUA_USE_POSIX) /* { */ + +#define l_popen(L,c,m) (fflush(NULL), popen(c,m)) +#define l_pclose(L,file) (pclose(file)) + +#elif defined(LUA_USE_WINDOWS) /* }{ */ + +#define l_popen(L,c,m) (_popen(c,m)) +#define l_pclose(L,file) (_pclose(file)) + +#else /* }{ */ + +/* ISO C definitions */ +#define l_popen(L,c,m) \ + ((void)((void)c, m), \ + luaL_error(L, "'popen' not supported"), \ + (FILE*)0) +#define l_pclose(L,file) ((void)L, (void)file, -1) + +#endif /* } */ + +#endif /* } */ + +/* }====================================================== */ + + +#if !defined(l_getc) /* { */ + +#if defined(LUA_USE_POSIX) +#define l_getc(f) getc_unlocked(f) +#define l_lockfile(f) flockfile(f) +#define l_unlockfile(f) funlockfile(f) +#else +#define l_getc(f) getc(f) +#define l_lockfile(f) ((void)0) +#define l_unlockfile(f) ((void)0) +#endif + +#endif /* } */ + + +/* +** {====================================================== +** l_fseek: configuration for longer offsets +** ======================================================= +*/ + +#if !defined(l_fseek) /* { */ + +#if defined(LUA_USE_POSIX) /* { */ + +#include +#define l_fseek(f,o,w) fseeko(f,o,w) +#define l_ftell(f) ftello(f) +#define l_seeknum off_t -#define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE)) +#elif defined(LUA_USE_WINDOWS) && !defined(_CRTIMP_TYPEINFO) \ + && defined(_MSC_VER) && (_MSC_VER >= 1400) /* }{ */ + +/* Windows (but not DDK) and Visual C++ 2005 or higher */ +#define l_fseek(f,o,w) _fseeki64(f,o,w) +#define l_ftell(f) _ftelli64(f) +#define l_seeknum __int64 + +#else /* }{ */ + +/* ISO C definitions */ +#define l_fseek(f,o,w) fseek(f,o,w) +#define l_ftell(f) ftell(f) +#define l_seeknum long + +#endif /* } */ + +#endif /* } */ + +/* }====================================================== */ + + +#define IO_PREFIX "_IO_" +#define IOPREF_LEN (sizeof(IO_PREFIX)/sizeof(char) - 1) +#define IO_INPUT (IO_PREFIX "input") +#define IO_OUTPUT (IO_PREFIX "output") + + +typedef luaL_Stream LStream; + + +#define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE)) + +#define isclosed(p) ((p)->closef == NULL) static int io_type (lua_State *L) { - void *ud; + LStream *p; luaL_checkany(L, 1); - ud = lua_touserdata(L, 1); - lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); - if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1)) + p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE); + if (p == NULL) lua_pushnil(L); /* not a file */ - else if (*((FILE **)ud) == NULL) + else if (isclosed(p)) lua_pushliteral(L, "closed file"); else lua_pushliteral(L, "file"); @@ -69,47 +160,64 @@ static int io_type (lua_State *L) { } +static int f_tostring (lua_State *L) { + LStream *p = tolstream(L); + if (isclosed(p)) + lua_pushliteral(L, "file (closed)"); + else + lua_pushfstring(L, "file (%p)", p->f); + return 1; +} + + static FILE *tofile (lua_State *L) { - FILE **f = tofilep(L); - if (*f == NULL) + LStream *p = tolstream(L); + if (isclosed(p)) luaL_error(L, "attempt to use a closed file"); - return *f; + lua_assert(p->f); + return p->f; } - /* -** When creating file handles, always creates a `closed' file handle +** When creating file handles, always creates a 'closed' file handle ** before opening the actual file; so, if there is a memory error, the -** file is not left opened. +** handle is in a consistent state. */ -static FILE **newfile (lua_State *L) { - FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); - *pf = NULL; /* file handle is currently `closed' */ - luaL_getmetatable(L, LUA_FILEHANDLE); - lua_setmetatable(L, -2); - return pf; +static LStream *newprefile (lua_State *L) { + LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream)); + p->closef = NULL; /* mark file handle as 'closed' */ + luaL_setmetatable(L, LUA_FILEHANDLE); + return p; } /* -** function to (not) close the standard files stdin, stdout, and stderr +** Calls the 'close' function from a file handle. The 'volatile' avoids +** a bug in some versions of the Clang compiler (e.g., clang 3.0 for +** 32 bits). */ -static int io_noclose (lua_State *L) { - lua_pushnil(L); - lua_pushliteral(L, "cannot close standard file"); - return 2; +static int aux_close (lua_State *L) { + LStream *p = tolstream(L); + volatile lua_CFunction cf = p->closef; + p->closef = NULL; /* mark stream as closed */ + return (*cf)(L); /* close it */ } -/* -** function to close 'popen' files -*/ -static int io_pclose (lua_State *L) { - FILE **p = tofilep(L); - int ok = lua_pclose(L, *p); - *p = NULL; - return pushresult(L, ok, NULL); +static int io_close (lua_State *L) { + if (lua_isnone(L, 1)) /* no argument? */ + lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */ + tofile(L); /* make sure argument is an open stream */ + return aux_close(L); +} + + +static int f_gc (lua_State *L) { + LStream *p = tolstream(L); + if (!isclosed(p) && p->f != NULL) + aux_close(L); /* ignore closed and incompletely open files */ + return 0; } @@ -117,103 +225,88 @@ static int io_pclose (lua_State *L) { ** function to close regular files */ static int io_fclose (lua_State *L) { - FILE **p = tofilep(L); - int ok = (fclose(*p) == 0); - *p = NULL; - return pushresult(L, ok, NULL); + LStream *p = tolstream(L); + int res = fclose(p->f); + return luaL_fileresult(L, (res == 0), NULL); } -static int aux_close (lua_State *L) { - lua_getfenv(L, 1); - lua_getfield(L, -1, "__close"); - return (lua_tocfunction(L, -1))(L); +static LStream *newfile (lua_State *L) { + LStream *p = newprefile(L); + p->f = NULL; + p->closef = &io_fclose; + return p; } -static int io_close (lua_State *L) { - if (lua_isnone(L, 1)) - lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); - tofile(L); /* make sure argument is a file */ - return aux_close(L); -} - - -static int io_gc (lua_State *L) { - FILE *f = *tofilep(L); - /* ignore closed files */ - if (f != NULL) - aux_close(L); - return 0; -} - - -static int io_tostring (lua_State *L) { - FILE *f = *tofilep(L); - if (f == NULL) - lua_pushliteral(L, "file (closed)"); - else - lua_pushfstring(L, "file (%p)", f); - return 1; +static void opencheck (lua_State *L, const char *fname, const char *mode) { + LStream *p = newfile(L); + p->f = fopen(fname, mode); + if (p->f == NULL) + luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno)); } static int io_open (lua_State *L) { const char *filename = luaL_checkstring(L, 1); const char *mode = luaL_optstring(L, 2, "r"); - FILE **pf = newfile(L); - *pf = fopen(filename, mode); - return (*pf == NULL) ? pushresult(L, 0, filename) : 1; + LStream *p = newfile(L); + const char *md = mode; /* to traverse/check mode */ + luaL_argcheck(L, l_checkmode(md), 2, "invalid mode"); + p->f = fopen(filename, mode); + return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; } /* -** this function has a separated environment, which defines the -** correct __close for 'popen' files +** function to close 'popen' files */ +static int io_pclose (lua_State *L) { + LStream *p = tolstream(L); + return luaL_execresult(L, l_pclose(L, p->f)); +} + + static int io_popen (lua_State *L) { const char *filename = luaL_checkstring(L, 1); const char *mode = luaL_optstring(L, 2, "r"); - FILE **pf = newfile(L); - *pf = lua_popen(L, filename, mode); - return (*pf == NULL) ? pushresult(L, 0, filename) : 1; + LStream *p = newprefile(L); + p->f = l_popen(L, filename, mode); + p->closef = &io_pclose; + return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; } static int io_tmpfile (lua_State *L) { - FILE **pf = newfile(L); - *pf = tmpfile(); - return (*pf == NULL) ? pushresult(L, 0, NULL) : 1; + LStream *p = newfile(L); + p->f = tmpfile(); + return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1; } -static FILE *getiofile (lua_State *L, int findex) { - FILE *f; - lua_rawgeti(L, LUA_ENVIRONINDEX, findex); - f = *(FILE **)lua_touserdata(L, -1); - if (f == NULL) - luaL_error(L, "standard %s file is closed", fnames[findex - 1]); - return f; +static FILE *getiofile (lua_State *L, const char *findex) { + LStream *p; + lua_getfield(L, LUA_REGISTRYINDEX, findex); + p = (LStream *)lua_touserdata(L, -1); + if (isclosed(p)) + luaL_error(L, "standard %s file is closed", findex + IOPREF_LEN); + return p->f; } -static int g_iofile (lua_State *L, int f, const char *mode) { +static int g_iofile (lua_State *L, const char *f, const char *mode) { if (!lua_isnoneornil(L, 1)) { const char *filename = lua_tostring(L, 1); - if (filename) { - FILE **pf = newfile(L); - *pf = fopen(filename, mode); - if (*pf == NULL) - fileerror(L, 1, filename); - } + if (filename) + opencheck(L, filename, mode); else { tofile(L); /* check that it's a valid file handle */ lua_pushvalue(L, 1); } - lua_rawseti(L, LUA_ENVIRONINDEX, f); + lua_setfield(L, LUA_REGISTRYINDEX, f); } /* return current value */ - lua_rawgeti(L, LUA_ENVIRONINDEX, f); + lua_getfield(L, LUA_REGISTRYINDEX, f); return 1; } @@ -231,35 +324,46 @@ static int io_output (lua_State *L) { static int io_readline (lua_State *L); -static void aux_lines (lua_State *L, int idx, int toclose) { - lua_pushvalue(L, idx); +/* +** maximum number of arguments to 'f:lines'/'io.lines' (it + 3 must fit +** in the limit for upvalues of a closure) +*/ +#define MAXARGLINE 250 + +static void aux_lines (lua_State *L, int toclose) { + int n = lua_gettop(L) - 1; /* number of arguments to read */ + luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments"); + lua_pushinteger(L, n); /* number of arguments to read */ lua_pushboolean(L, toclose); /* close/not close file when finished */ - lua_pushcclosure(L, io_readline, 2); + lua_rotate(L, 2, 2); /* move 'n' and 'toclose' to their positions */ + lua_pushcclosure(L, io_readline, 3 + n); } static int f_lines (lua_State *L) { tofile(L); /* check that it's a valid file handle */ - aux_lines(L, 1, 0); + aux_lines(L, 0); return 1; } static int io_lines (lua_State *L) { - if (lua_isnoneornil(L, 1)) { /* no arguments? */ - /* will iterate over default input */ - lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT); - return f_lines(L); + int toclose; + if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ + if (lua_isnil(L, 1)) { /* no file name? */ + lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */ + lua_replace(L, 1); /* put it at index 1 */ + tofile(L); /* check that it's a valid file handle */ + toclose = 0; /* do not close it after iteration */ } - else { + else { /* open a new file */ const char *filename = luaL_checkstring(L, 1); - FILE **pf = newfile(L); - *pf = fopen(filename, "r"); - if (*pf == NULL) - fileerror(L, 1, filename); - aux_lines(L, lua_gettop(L), 1); - return 1; + opencheck(L, filename, "r"); + lua_replace(L, 1); /* put file at index 1 */ + toclose = 1; /* close it after iteration */ } + aux_lines(L, toclose); + return 1; } @@ -270,64 +374,149 @@ static int io_lines (lua_State *L) { */ -static int read_number (lua_State *L, FILE *f) { - lua_Number d; - if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { - lua_pushnumber(L, d); - return 1; +/* maximum length of a numeral */ +#if !defined (L_MAXLENNUM) +#define L_MAXLENNUM 200 +#endif + + +/* auxiliary structure used by 'read_number' */ +typedef struct { + FILE *f; /* file being read */ + int c; /* current character (look ahead) */ + int n; /* number of elements in buffer 'buff' */ + char buff[L_MAXLENNUM + 1]; /* +1 for ending '\0' */ +} RN; + + +/* +** Add current char to buffer (if not out of space) and read next one +*/ +static int nextc (RN *rn) { + if (rn->n >= L_MAXLENNUM) { /* buffer overflow? */ + rn->buff[0] = '\0'; /* invalidate result */ + return 0; /* fail */ } else { - lua_pushnil(L); /* "result" to be removed */ - return 0; /* read fails */ + rn->buff[rn->n++] = rn->c; /* save current char */ + rn->c = l_getc(rn->f); /* read next one */ + return 1; + } +} + + +/* +** Accept current char if it is in 'set' (of size 2) +*/ +static int test2 (RN *rn, const char *set) { + if (rn->c == set[0] || rn->c == set[1]) + return nextc(rn); + else return 0; +} + + +/* +** Read a sequence of (hex)digits +*/ +static int readdigits (RN *rn, int hex) { + int count = 0; + while ((hex ? isxdigit(rn->c) : isdigit(rn->c)) && nextc(rn)) + count++; + return count; +} + + +/* +** Read a number: first reads a valid prefix of a numeral into a buffer. +** Then it calls 'lua_stringtonumber' to check whether the format is +** correct and to convert it to a Lua number +*/ +static int read_number (lua_State *L, FILE *f) { + RN rn; + int count = 0; + int hex = 0; + char decp[2]; + rn.f = f; rn.n = 0; + decp[0] = lua_getlocaledecpoint(); /* get decimal point from locale */ + decp[1] = '.'; /* always accept a dot */ + l_lockfile(rn.f); + do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */ + test2(&rn, "-+"); /* optional signal */ + if (test2(&rn, "00")) { + if (test2(&rn, "xX")) hex = 1; /* numeral is hexadecimal */ + else count = 1; /* count initial '0' as a valid digit */ + } + count += readdigits(&rn, hex); /* integral part */ + if (test2(&rn, decp)) /* decimal point? */ + count += readdigits(&rn, hex); /* fractional part */ + if (count > 0 && test2(&rn, (hex ? "pP" : "eE"))) { /* exponent mark? */ + test2(&rn, "-+"); /* exponent signal */ + readdigits(&rn, 0); /* exponent digits */ + } + ungetc(rn.c, rn.f); /* unread look-ahead char */ + l_unlockfile(rn.f); + rn.buff[rn.n] = '\0'; /* finish string */ + if (lua_stringtonumber(L, rn.buff)) /* is this a valid number? */ + return 1; /* ok */ + else { /* invalid format */ + lua_pushnil(L); /* "result" to be removed */ + return 0; /* read fails */ } } static int test_eof (lua_State *L, FILE *f) { int c = getc(f); - ungetc(c, f); - lua_pushlstring(L, NULL, 0); + ungetc(c, f); /* no-op when c == EOF */ + lua_pushliteral(L, ""); return (c != EOF); } -static int read_line (lua_State *L, FILE *f) { +static int read_line (lua_State *L, FILE *f, int chop) { luaL_Buffer b; + int c = '\0'; luaL_buffinit(L, &b); - for (;;) { - size_t l; - char *p = luaL_prepbuffer(&b); - if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ - luaL_pushresult(&b); /* close buffer */ - return (lua_objlen(L, -1) > 0); /* check whether read something */ - } - l = strlen(p); - if (l == 0 || p[l-1] != '\n') - luaL_addsize(&b, l); - else { - luaL_addsize(&b, l - 1); /* do not include `eol' */ - luaL_pushresult(&b); /* close buffer */ - return 1; /* read at least an `eol' */ - } + while (c != EOF && c != '\n') { /* repeat until end of line */ + char *buff = luaL_prepbuffer(&b); /* preallocate buffer */ + int i = 0; + l_lockfile(f); /* no memory errors can happen inside the lock */ + while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n') + buff[i++] = c; + l_unlockfile(f); + luaL_addsize(&b, i); } + if (!chop && c == '\n') /* want a newline and have one? */ + luaL_addchar(&b, c); /* add ending newline to result */ + luaL_pushresult(&b); /* close buffer */ + /* return ok if read something (either a newline or something else) */ + return (c == '\n' || lua_rawlen(L, -1) > 0); } -static int read_chars (lua_State *L, FILE *f, size_t n) { - size_t rlen; /* how much to read */ - size_t nr; /* number of chars actually read */ +static void read_all (lua_State *L, FILE *f) { + size_t nr; luaL_Buffer b; luaL_buffinit(L, &b); - rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ - do { + do { /* read file in chunks of LUAL_BUFFERSIZE bytes */ char *p = luaL_prepbuffer(&b); - if (rlen > n) rlen = n; /* cannot read more than asked */ - nr = fread(p, sizeof(char), rlen, f); + nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f); luaL_addsize(&b, nr); - n -= nr; /* still have to read `n' chars */ - } while (n > 0 && nr == rlen); /* until end of count or eof */ + } while (nr == LUAL_BUFFERSIZE); + luaL_pushresult(&b); /* close buffer */ +} + + +static int read_chars (lua_State *L, FILE *f, size_t n) { + size_t nr; /* number of chars actually read */ + char *p; + luaL_Buffer b; + luaL_buffinit(L, &b); + p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */ + nr = fread(p, sizeof(char), n, f); /* try to read 'n' chars */ + luaL_addsize(&b, nr); luaL_pushresult(&b); /* close buffer */ - return (n == 0 || lua_objlen(L, -1) > 0); + return (nr > 0); /* true iff read something */ } @@ -337,7 +526,7 @@ static int g_read (lua_State *L, FILE *f, int first) { int n; clearerr(f); if (nargs == 0) { /* no arguments? */ - success = read_line(L, f); + success = read_line(L, f, 1); n = first+1; /* to return 1 result */ } else { /* ensure stack space for all results and for auxlib's buffer */ @@ -345,21 +534,24 @@ static int g_read (lua_State *L, FILE *f, int first) { success = 1; for (n = first; nargs-- && success; n++) { if (lua_type(L, n) == LUA_TNUMBER) { - size_t l = (size_t)lua_tointeger(L, n); + size_t l = (size_t)luaL_checkinteger(L, n); success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); } else { - const char *p = lua_tostring(L, n); - luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); - switch (p[1]) { + const char *p = luaL_checkstring(L, n); + if (*p == '*') p++; /* skip optional '*' (for compatibility) */ + switch (*p) { case 'n': /* number */ success = read_number(L, f); break; case 'l': /* line */ - success = read_line(L, f); + success = read_line(L, f, 1); + break; + case 'L': /* line with end-of-line */ + success = read_line(L, f, 0); break; case 'a': /* file */ - read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ + read_all(L, f); /* read entire file */ success = 1; /* always success */ break; default: @@ -369,7 +561,7 @@ static int g_read (lua_State *L, FILE *f, int first) { } } if (ferror(f)) - return pushresult(L, 0, NULL); + return luaL_fileresult(L, 0, NULL); if (!success) { lua_pop(L, 1); /* remove last result */ lua_pushnil(L); /* push nil instead */ @@ -389,16 +581,25 @@ static int f_read (lua_State *L) { static int io_readline (lua_State *L) { - FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1)); - int sucess; - if (f == NULL) /* file is already closed? */ - luaL_error(L, "file is already closed"); - sucess = read_line(L, f); - if (ferror(f)) - return luaL_error(L, "%s", strerror(errno)); - if (sucess) return 1; - else { /* EOF */ - if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */ + LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1)); + int i; + int n = (int)lua_tointeger(L, lua_upvalueindex(2)); + if (isclosed(p)) /* file is already closed? */ + return luaL_error(L, "file is already closed"); + lua_settop(L , 1); + luaL_checkstack(L, n, "too many arguments"); + for (i = 1; i <= n; i++) /* push arguments to 'g_read' */ + lua_pushvalue(L, lua_upvalueindex(3 + i)); + n = g_read(L, p->f, 2); /* 'n' is number of results */ + lua_assert(n > 0); /* should return at least a nil */ + if (lua_toboolean(L, -n)) /* read at least one value? */ + return n; /* return them */ + else { /* first result is nil: EOF or error */ + if (n > 1) { /* is there error information? */ + /* 2nd result is error message */ + return luaL_error(L, "%s", lua_tostring(L, -n + 1)); + } + if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ lua_settop(L, 0); lua_pushvalue(L, lua_upvalueindex(1)); aux_close(L); /* close it */ @@ -411,13 +612,15 @@ static int io_readline (lua_State *L) { static int g_write (lua_State *L, FILE *f, int arg) { - int nargs = lua_gettop(L) - 1; + int nargs = lua_gettop(L) - arg; int status = 1; for (; nargs--; arg++) { if (lua_type(L, arg) == LUA_TNUMBER) { /* optimization: could be done exactly as for strings */ - status = status && - fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; + int len = lua_isinteger(L, arg) + ? fprintf(f, LUA_INTEGER_FMT, lua_tointeger(L, arg)) + : fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)); + status = status && (len > 0); } else { size_t l; @@ -425,7 +628,8 @@ static int g_write (lua_State *L, FILE *f, int arg) { status = status && (fwrite(s, sizeof(char), l, f) == l); } } - return pushresult(L, status, NULL); + if (status) return 1; /* file handle already on stack top */ + else return luaL_fileresult(L, status, NULL); } @@ -435,7 +639,9 @@ static int io_write (lua_State *L) { static int f_write (lua_State *L) { - return g_write(L, tofile(L), 2); + FILE *f = tofile(L); + lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */ + return g_write(L, f, 2); } @@ -444,12 +650,15 @@ static int f_seek (lua_State *L) { static const char *const modenames[] = {"set", "cur", "end", NULL}; FILE *f = tofile(L); int op = luaL_checkoption(L, 2, "cur", modenames); - long offset = luaL_optlong(L, 3, 0); - op = fseek(f, offset, mode[op]); + lua_Integer p3 = luaL_optinteger(L, 3, 0); + l_seeknum offset = (l_seeknum)p3; + luaL_argcheck(L, (lua_Integer)offset == p3, 3, + "not an integer in proper range"); + op = l_fseek(f, offset, mode[op]); if (op) - return pushresult(L, 0, NULL); /* error */ + return luaL_fileresult(L, 0, NULL); /* error */ else { - lua_pushinteger(L, ftell(f)); + lua_pushinteger(L, (lua_Integer)l_ftell(f)); return 1; } } @@ -461,22 +670,25 @@ static int f_setvbuf (lua_State *L) { FILE *f = tofile(L); int op = luaL_checkoption(L, 2, NULL, modenames); lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); - int res = setvbuf(f, NULL, mode[op], sz); - return pushresult(L, res == 0, NULL); + int res = setvbuf(f, NULL, mode[op], (size_t)sz); + return luaL_fileresult(L, res == 0, NULL); } static int io_flush (lua_State *L) { - return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); + return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); } static int f_flush (lua_State *L) { - return pushresult(L, fflush(tofile(L)) == 0, NULL); + return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL); } +/* +** functions for 'io' library +*/ static const luaL_Reg iolib[] = { {"close", io_close}, {"flush", io_flush}, @@ -493,6 +705,9 @@ static const luaL_Reg iolib[] = { }; +/* +** methods for file handles +*/ static const luaL_Reg flib[] = { {"close", io_close}, {"flush", f_flush}, @@ -501,8 +716,8 @@ static const luaL_Reg flib[] = { {"seek", f_seek}, {"setvbuf", f_setvbuf}, {"write", f_write}, - {"__gc", io_gc}, - {"__tostring", io_tostring}, + {"__gc", f_gc}, + {"__tostring", f_tostring}, {NULL, NULL} }; @@ -511,46 +726,43 @@ static void createmeta (lua_State *L) { luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ lua_pushvalue(L, -1); /* push metatable */ lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ - luaL_register(L, NULL, flib); /* file methods */ + luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */ + lua_pop(L, 1); /* pop new metatable */ } -static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { - *newfile(L) = f; - if (k > 0) { - lua_pushvalue(L, -1); - lua_rawseti(L, LUA_ENVIRONINDEX, k); - } - lua_pushvalue(L, -2); /* copy environment */ - lua_setfenv(L, -2); /* set it */ - lua_setfield(L, -3, fname); +/* +** function to (not) close the standard files stdin, stdout, and stderr +*/ +static int io_noclose (lua_State *L) { + LStream *p = tolstream(L); + p->closef = &io_noclose; /* keep file opened */ + lua_pushnil(L); + lua_pushliteral(L, "cannot close standard file"); + return 2; } -static void newfenv (lua_State *L, lua_CFunction cls) { - lua_createtable(L, 0, 1); - lua_pushcfunction(L, cls); - lua_setfield(L, -2, "__close"); +static void createstdfile (lua_State *L, FILE *f, const char *k, + const char *fname) { + LStream *p = newprefile(L); + p->f = f; + p->closef = &io_noclose; + if (k != NULL) { + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */ + } + lua_setfield(L, -2, fname); /* add file to module */ } -LUALIB_API int luaopen_io (lua_State *L) { +LUAMOD_API int luaopen_io (lua_State *L) { + luaL_newlib(L, iolib); /* new module */ createmeta(L); - /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ - newfenv(L, io_fclose); - lua_replace(L, LUA_ENVIRONINDEX); - /* open library */ - luaL_register(L, LUA_IOLIBNAME, iolib); /* create (and set) default files */ - newfenv(L, io_noclose); /* close function for default files */ createstdfile(L, stdin, IO_INPUT, "stdin"); createstdfile(L, stdout, IO_OUTPUT, "stdout"); - createstdfile(L, stderr, 0, "stderr"); - lua_pop(L, 1); /* pop environment for default files */ - lua_getfield(L, -1, "popen"); - newfenv(L, io_pclose); /* create environment for 'popen' */ - lua_setfenv(L, -2); /* set fenv for 'popen' */ - lua_pop(L, 1); /* pop 'popen' */ + createstdfile(L, stderr, NULL, "stderr"); return 1; } diff --git a/app/src/main/jni/lua/llex.c b/app/src/main/jni/lua/llex.c index 68c6d25..7032827 100644 --- a/app/src/main/jni/lua/llex.c +++ b/app/src/main/jni/lua/llex.c @@ -1,20 +1,24 @@ /* -** $Id: llex.c,v 2.20.1.2 2009/11/23 14:58:22 roberto Exp $ +** $Id: llex.c,v 2.96 2016/05/02 14:02:12 roberto Exp $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ +#define llex_c +#define LUA_CORE + +#include "lprefix.h" + -#include #include #include -#define llex_c -#define LUA_CORE - #include "lua.h" +#include "lctype.h" +#include "ldebug.h" #include "ldo.h" +#include "lgc.h" #include "llex.h" #include "lobject.h" #include "lparser.h" @@ -29,125 +33,145 @@ - #define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') /* ORDER RESERVED */ -const char *const luaX_tokens [] = { +static const char *const luaX_tokens [] = { "and", "break", "do", "else", "elseif", - "end", "false", "for", "function", "if", + "end", "false", "for", "function", "goto", "if", "in", "local", "nil", "not", "or", "repeat", "return", "then", "true", "until", "while", - "..", "...", "==", ">=", "<=", "~=", - "", "", "", "", - NULL + "//", "..", "...", "==", ">=", "<=", "~=", + "<<", ">>", "::", "", + "", "", "", "" }; #define save_and_next(ls) (save(ls, ls->current), next(ls)) +static l_noret lexerror (LexState *ls, const char *msg, int token); + + static void save (LexState *ls, int c) { Mbuffer *b = ls->buff; - if (b->n + 1 > b->buffsize) { + if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) { size_t newsize; - if (b->buffsize >= MAX_SIZET/2) - luaX_lexerror(ls, "lexical element too long", 0); - newsize = b->buffsize * 2; + if (luaZ_sizebuffer(b) >= MAX_SIZE/2) + lexerror(ls, "lexical element too long", 0); + newsize = luaZ_sizebuffer(b) * 2; luaZ_resizebuffer(ls->L, b, newsize); } - b->buffer[b->n++] = cast(char, c); + b->buffer[luaZ_bufflen(b)++] = cast(char, c); } void luaX_init (lua_State *L) { int i; + TString *e = luaS_newliteral(L, LUA_ENV); /* create env name */ + luaC_fix(L, obj2gco(e)); /* never collect this name */ for (i=0; itsv.reserved = cast_byte(i+1); /* reserved word */ + luaC_fix(L, obj2gco(ts)); /* reserved words are never collected */ + ts->extra = cast_byte(i+1); /* reserved word */ } } -#define MAXSRC 80 - - const char *luaX_token2str (LexState *ls, int token) { - if (token < FIRST_RESERVED) { - lua_assert(token == cast(unsigned char, token)); - return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)", token) : - luaO_pushfstring(ls->L, "%c", token); + if (token < FIRST_RESERVED) { /* single-byte symbols? */ + lua_assert(token == cast_uchar(token)); + return luaO_pushfstring(ls->L, "'%c'", token); + } + else { + const char *s = luaX_tokens[token - FIRST_RESERVED]; + if (token < TK_EOS) /* fixed format (symbols and reserved words)? */ + return luaO_pushfstring(ls->L, "'%s'", s); + else /* names, strings, and numerals */ + return s; } - else - return luaX_tokens[token-FIRST_RESERVED]; } static const char *txtToken (LexState *ls, int token) { switch (token) { - case TK_NAME: - case TK_STRING: - case TK_NUMBER: + case TK_NAME: case TK_STRING: + case TK_FLT: case TK_INT: save(ls, '\0'); - return luaZ_buffer(ls->buff); + return luaO_pushfstring(ls->L, "'%s'", luaZ_buffer(ls->buff)); default: return luaX_token2str(ls, token); } } -void luaX_lexerror (LexState *ls, const char *msg, int token) { - char buff[MAXSRC]; - luaO_chunkid(buff, getstr(ls->source), MAXSRC); - msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); +static l_noret lexerror (LexState *ls, const char *msg, int token) { + msg = luaG_addinfo(ls->L, msg, ls->source, ls->linenumber); if (token) - luaO_pushfstring(ls->L, "%s near " LUA_QS, msg, txtToken(ls, token)); + luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token)); luaD_throw(ls->L, LUA_ERRSYNTAX); } -void luaX_syntaxerror (LexState *ls, const char *msg) { - luaX_lexerror(ls, msg, ls->t.token); +l_noret luaX_syntaxerror (LexState *ls, const char *msg) { + lexerror(ls, msg, ls->t.token); } +/* +** creates a new string and anchors it in scanner's table so that +** it will not be collected until the end of the compilation +** (by that time it should be anchored somewhere) +*/ TString *luaX_newstring (LexState *ls, const char *str, size_t l) { lua_State *L = ls->L; - TString *ts = luaS_newlstr(L, str, l); - TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */ - if (ttisnil(o)) { - setbvalue(o, 1); /* make sure `str' will not be collected */ + TValue *o; /* entry for 'str' */ + TString *ts = luaS_newlstr(L, str, l); /* create new string */ + setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */ + o = luaH_set(L, ls->h, L->top - 1); + if (ttisnil(o)) { /* not in use yet? */ + /* boolean value does not need GC barrier; + table has no metatable, so it does not need to invalidate cache */ + setbvalue(o, 1); /* t[string] = true */ luaC_checkGC(L); } + else { /* string already present */ + ts = tsvalue(keyfromval(o)); /* re-use value previously stored */ + } + L->top--; /* remove string from stack */ return ts; } +/* +** increment line number and skips newline sequence (any of +** \n, \r, \n\r, or \r\n) +*/ static void inclinenumber (LexState *ls) { int old = ls->current; lua_assert(currIsNewline(ls)); - next(ls); /* skip `\n' or `\r' */ + next(ls); /* skip '\n' or '\r' */ if (currIsNewline(ls) && ls->current != old) - next(ls); /* skip `\n\r' or `\r\n' */ + next(ls); /* skip '\n\r' or '\r\n' */ if (++ls->linenumber >= MAX_INT) - luaX_syntaxerror(ls, "chunk has too many lines"); + lexerror(ls, "chunk has too many lines", 0); } -void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { - ls->decpoint = '.'; +void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source, + int firstchar) { + ls->t.token = 0; ls->L = L; + ls->current = firstchar; ls->lookahead.token = TK_EOS; /* no look-ahead token */ ls->z = z; ls->fs = NULL; ls->linenumber = 1; ls->lastline = 1; ls->source = source; + ls->envn = luaS_newliteral(L, LUA_ENV); /* get env name */ luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ - next(ls); /* read first char */ } @@ -159,45 +183,71 @@ void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { */ - -static int check_next (LexState *ls, const char *set) { - if (!strchr(set, ls->current)) - return 0; - save_and_next(ls); - return 1; -} - - -static void buffreplace (LexState *ls, char from, char to) { - size_t n = luaZ_bufflen(ls->buff); - char *p = luaZ_buffer(ls->buff); - while (n--) - if (p[n] == from) p[n] = to; +static int check_next1 (LexState *ls, int c) { + if (ls->current == c) { + next(ls); + return 1; + } + else return 0; } -static void trydecpoint (LexState *ls, SemInfo *seminfo) { - luaX_lexerror(ls, "malformed number", TK_NUMBER); +/* +** Check whether current char is in set 'set' (with two chars) and +** saves it +*/ +static int check_next2 (LexState *ls, const char *set) { + lua_assert(set[2] == '\0'); + if (ls->current == set[0] || ls->current == set[1]) { + save_and_next(ls); + return 1; + } + else return 0; } /* LUA_NUMBER */ -static void read_numeral (LexState *ls, SemInfo *seminfo) { - lua_assert(isdigit(ls->current)); - do { - save_and_next(ls); - } while (isdigit(ls->current) || ls->current == '.'); - if (check_next(ls, "Ee")) /* `E'? */ - check_next(ls, "+-"); /* optional exponent sign */ - while (isalnum(ls->current) || ls->current == '_') - save_and_next(ls); +/* +** this function is quite liberal in what it accepts, as 'luaO_str2num' +** will reject ill-formed numerals. +*/ +static int read_numeral (LexState *ls, SemInfo *seminfo) { + TValue obj; + const char *expo = "Ee"; + int first = ls->current; + lua_assert(lisdigit(ls->current)); + save_and_next(ls); + if (first == '0' && check_next2(ls, "xX")) /* hexadecimal? */ + expo = "Pp"; + for (;;) { + if (check_next2(ls, expo)) /* exponent part? */ + check_next2(ls, "-+"); /* optional exponent sign */ + if (lisxdigit(ls->current)) + save_and_next(ls); + else if (ls->current == '.') + save_and_next(ls); + else break; + } save(ls, '\0'); - buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ - if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */ - trydecpoint(ls, seminfo); /* try to update decimal point separator */ + if (luaO_str2num(luaZ_buffer(ls->buff), &obj) == 0) /* format error? */ + lexerror(ls, "malformed number", TK_FLT); + if (ttisinteger(&obj)) { + seminfo->i = ivalue(&obj); + return TK_INT; + } + else { + lua_assert(ttisfloat(&obj)); + seminfo->r = fltvalue(&obj); + return TK_FLT; + } } +/* +** skip a sequence '[=*[' or ']=*]'; if sequence is well formed, return +** its number of '='s; otherwise, return a negative number (-1 iff there +** are no '='s after initial bracket) +*/ static int skip_sep (LexState *ls) { int count = 0; int s = ls->current; @@ -212,43 +262,27 @@ static int skip_sep (LexState *ls) { static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { - int cont = 0; - (void)(cont); /* avoid warnings when `cont' is not used */ - save_and_next(ls); /* skip 2nd `[' */ + int line = ls->linenumber; /* initial line (for error message) */ + save_and_next(ls); /* skip 2nd '[' */ if (currIsNewline(ls)) /* string starts with a newline? */ inclinenumber(ls); /* skip it */ for (;;) { switch (ls->current) { - case EOZ: - luaX_lexerror(ls, (seminfo) ? "unfinished long string" : - "unfinished long comment", TK_EOS); + case EOZ: { /* error */ + const char *what = (seminfo ? "string" : "comment"); + const char *msg = luaO_pushfstring(ls->L, + "unfinished long %s (starting at line %d)", what, line); + lexerror(ls, msg, TK_EOS); break; /* to avoid warnings */ -#if defined(LUA_COMPAT_LSTR) - case '[': { - if (skip_sep(ls) == sep) { - save_and_next(ls); /* skip 2nd `[' */ - cont++; -#if LUA_COMPAT_LSTR == 1 - if (sep == 0) - luaX_lexerror(ls, "nesting of [[...]] is deprecated", '['); -#endif - } - break; } -#endif case ']': { if (skip_sep(ls) == sep) { - save_and_next(ls); /* skip 2nd `]' */ -#if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2 - cont--; - if (sep == 0 && cont >= 0) break; -#endif + save_and_next(ls); /* skip 2nd ']' */ goto endloop; } break; } - case '\n': - case '\r': { + case '\n': case '\r': { save(ls, '\n'); inclinenumber(ls); if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ @@ -266,51 +300,121 @@ static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { } -static void read_string (LexState *ls, int del, SemInfo *seminfo) { +static void esccheck (LexState *ls, int c, const char *msg) { + if (!c) { + if (ls->current != EOZ) + save_and_next(ls); /* add current to buffer for error message */ + lexerror(ls, msg, TK_STRING); + } +} + + +static int gethexa (LexState *ls) { save_and_next(ls); + esccheck (ls, lisxdigit(ls->current), "hexadecimal digit expected"); + return luaO_hexavalue(ls->current); +} + + +static int readhexaesc (LexState *ls) { + int r = gethexa(ls); + r = (r << 4) + gethexa(ls); + luaZ_buffremove(ls->buff, 2); /* remove saved chars from buffer */ + return r; +} + + +static unsigned long readutf8esc (LexState *ls) { + unsigned long r; + int i = 4; /* chars to be removed: '\', 'u', '{', and first digit */ + save_and_next(ls); /* skip 'u' */ + esccheck(ls, ls->current == '{', "missing '{'"); + r = gethexa(ls); /* must have at least one digit */ + while ((save_and_next(ls), lisxdigit(ls->current))) { + i++; + r = (r << 4) + luaO_hexavalue(ls->current); + esccheck(ls, r <= 0x10FFFF, "UTF-8 value too large"); + } + esccheck(ls, ls->current == '}', "missing '}'"); + next(ls); /* skip '}' */ + luaZ_buffremove(ls->buff, i); /* remove saved chars from buffer */ + return r; +} + + +static void utf8esc (LexState *ls) { + char buff[UTF8BUFFSZ]; + int n = luaO_utf8esc(buff, readutf8esc(ls)); + for (; n > 0; n--) /* add 'buff' to string */ + save(ls, buff[UTF8BUFFSZ - n]); +} + + +static int readdecesc (LexState *ls) { + int i; + int r = 0; /* result accumulator */ + for (i = 0; i < 3 && lisdigit(ls->current); i++) { /* read up to 3 digits */ + r = 10*r + ls->current - '0'; + save_and_next(ls); + } + esccheck(ls, r <= UCHAR_MAX, "decimal escape too large"); + luaZ_buffremove(ls->buff, i); /* remove read digits from buffer */ + return r; +} + + +static void read_string (LexState *ls, int del, SemInfo *seminfo) { + save_and_next(ls); /* keep delimiter (for error messages) */ while (ls->current != del) { switch (ls->current) { case EOZ: - luaX_lexerror(ls, "unfinished string", TK_EOS); - continue; /* to avoid warnings */ + lexerror(ls, "unfinished string", TK_EOS); + break; /* to avoid warnings */ case '\n': case '\r': - luaX_lexerror(ls, "unfinished string", TK_STRING); - continue; /* to avoid warnings */ - case '\\': { - int c; - next(ls); /* do not save the `\' */ + lexerror(ls, "unfinished string", TK_STRING); + break; /* to avoid warnings */ + case '\\': { /* escape sequences */ + int c; /* final character to be saved */ + save_and_next(ls); /* keep '\\' for error messages */ switch (ls->current) { - case 'a': c = '\a'; break; - case 'b': c = '\b'; break; - case 'f': c = '\f'; break; - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 't': c = '\t'; break; - case 'v': c = '\v'; break; - case '\n': /* go through */ - case '\r': save(ls, '\n'); inclinenumber(ls); continue; - case EOZ: continue; /* will raise an error next loop */ - default: { - if (!isdigit(ls->current)) - save_and_next(ls); /* handles \\, \", \', and \? */ - else { /* \xxx */ - int i = 0; - c = 0; - do { - c = 10*c + (ls->current-'0'); - next(ls); - } while (++i<3 && isdigit(ls->current)); - if (c > UCHAR_MAX) - luaX_lexerror(ls, "escape sequence too large", TK_STRING); - save(ls, c); + case 'a': c = '\a'; goto read_save; + case 'b': c = '\b'; goto read_save; + case 'f': c = '\f'; goto read_save; + case 'n': c = '\n'; goto read_save; + case 'r': c = '\r'; goto read_save; + case 't': c = '\t'; goto read_save; + case 'v': c = '\v'; goto read_save; + case 'x': c = readhexaesc(ls); goto read_save; + case 'u': utf8esc(ls); goto no_save; + case '\n': case '\r': + inclinenumber(ls); c = '\n'; goto only_save; + case '\\': case '\"': case '\'': + c = ls->current; goto read_save; + case EOZ: goto no_save; /* will raise an error next loop */ + case 'z': { /* zap following span of spaces */ + luaZ_buffremove(ls->buff, 1); /* remove '\\' */ + next(ls); /* skip the 'z' */ + while (lisspace(ls->current)) { + if (currIsNewline(ls)) inclinenumber(ls); + else next(ls); } - continue; + goto no_save; + } + default: { + esccheck(ls, lisdigit(ls->current), "invalid escape sequence"); + c = readdecesc(ls); /* digital escape '\ddd' */ + goto only_save; } } - save(ls, c); - next(ls); - continue; + read_save: + next(ls); + /* go through */ + only_save: + luaZ_buffremove(ls->buff, 1); /* remove '\\' */ + save(ls, c); + /* go through */ + no_save: break; } default: save_and_next(ls); @@ -326,109 +430,115 @@ static int llex (LexState *ls, SemInfo *seminfo) { luaZ_resetbuffer(ls->buff); for (;;) { switch (ls->current) { - case '\n': - case '\r': { + case '\n': case '\r': { /* line breaks */ inclinenumber(ls); - continue; + break; + } + case ' ': case '\f': case '\t': case '\v': { /* spaces */ + next(ls); + break; } - case '-': { + case '-': { /* '-' or '--' (comment) */ next(ls); if (ls->current != '-') return '-'; /* else is a comment */ next(ls); - if (ls->current == '[') { + if (ls->current == '[') { /* long comment? */ int sep = skip_sep(ls); - luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ + luaZ_resetbuffer(ls->buff); /* 'skip_sep' may dirty the buffer */ if (sep >= 0) { - read_long_string(ls, NULL, sep); /* long comment */ - luaZ_resetbuffer(ls->buff); - continue; + read_long_string(ls, NULL, sep); /* skip long comment */ + luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */ + break; } } /* else short comment */ while (!currIsNewline(ls) && ls->current != EOZ) - next(ls); - continue; + next(ls); /* skip until end of line (or end of file) */ + break; } - case '[': { + case '[': { /* long string or simply '[' */ int sep = skip_sep(ls); if (sep >= 0) { read_long_string(ls, seminfo, sep); return TK_STRING; } - else if (sep == -1) return '['; - else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING); + else if (sep != -1) /* '[=...' missing second bracket */ + lexerror(ls, "invalid long string delimiter", TK_STRING); + return '['; } case '=': { next(ls); - if (ls->current != '=') return '='; - else { next(ls); return TK_EQ; } + if (check_next1(ls, '=')) return TK_EQ; + else return '='; } case '<': { next(ls); - if (ls->current != '=') return '<'; - else { next(ls); return TK_LE; } + if (check_next1(ls, '=')) return TK_LE; + else if (check_next1(ls, '<')) return TK_SHL; + else return '<'; } case '>': { next(ls); - if (ls->current != '=') return '>'; - else { next(ls); return TK_GE; } + if (check_next1(ls, '=')) return TK_GE; + else if (check_next1(ls, '>')) return TK_SHR; + else return '>'; + } + case '/': { + next(ls); + if (check_next1(ls, '/')) return TK_IDIV; + else return '/'; } case '~': { next(ls); - if (ls->current != '=') return '~'; - else { next(ls); return TK_NE; } + if (check_next1(ls, '=')) return TK_NE; + else return '~'; + } + case ':': { + next(ls); + if (check_next1(ls, ':')) return TK_DBCOLON; + else return ':'; } - case '"': - case '\'': { + case '"': case '\'': { /* short literal strings */ read_string(ls, ls->current, seminfo); return TK_STRING; } - case '.': { + case '.': { /* '.', '..', '...', or number */ save_and_next(ls); - if (check_next(ls, ".")) { - if (check_next(ls, ".")) - return TK_DOTS; /* ... */ - else return TK_CONCAT; /* .. */ - } - else if (!isdigit(ls->current)) return '.'; - else { - read_numeral(ls, seminfo); - return TK_NUMBER; + if (check_next1(ls, '.')) { + if (check_next1(ls, '.')) + return TK_DOTS; /* '...' */ + else return TK_CONCAT; /* '..' */ } + else if (!lisdigit(ls->current)) return '.'; + else return read_numeral(ls, seminfo); + } + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { + return read_numeral(ls, seminfo); } case EOZ: { return TK_EOS; } default: { - if (isspace(ls->current)) { - lua_assert(!currIsNewline(ls)); - next(ls); - continue; - } - else if (isdigit(ls->current)) { - read_numeral(ls, seminfo); - return TK_NUMBER; - } - else if (isalpha(ls->current) || ls->current == '_') { - /* identifier or reserved word */ + if (lislalpha(ls->current)) { /* identifier or reserved word? */ TString *ts; do { save_and_next(ls); - } while (isalnum(ls->current) || ls->current == '_'); + } while (lislalnum(ls->current)); ts = luaX_newstring(ls, luaZ_buffer(ls->buff), luaZ_bufflen(ls->buff)); - if (ts->tsv.reserved > 0) /* reserved word? */ - return ts->tsv.reserved - 1 + FIRST_RESERVED; + seminfo->ts = ts; + if (isreserved(ts)) /* reserved word? */ + return ts->extra - 1 + FIRST_RESERVED; else { - seminfo->ts = ts; return TK_NAME; } } - else { + else { /* single-char tokens (+ - / ...) */ int c = ls->current; next(ls); - return c; /* single-char tokens (+ - / ...) */ + return c; } } } @@ -447,8 +557,9 @@ void luaX_next (LexState *ls) { } -void luaX_lookahead (LexState *ls) { +int luaX_lookahead (LexState *ls) { lua_assert(ls->lookahead.token == TK_EOS); ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); + return ls->lookahead.token; } diff --git a/app/src/main/jni/lua/llex.h b/app/src/main/jni/lua/llex.h index a9201ce..2363d87 100644 --- a/app/src/main/jni/lua/llex.h +++ b/app/src/main/jni/lua/llex.h @@ -1,5 +1,5 @@ /* -** $Id: llex.h,v 1.58.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: llex.h,v 1.79 2016/05/02 14:02:12 roberto Exp $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -13,8 +13,10 @@ #define FIRST_RESERVED 257 -/* maximum length of a reserved word */ -#define TOKEN_LEN (sizeof("function")/sizeof(char)) + +#if !defined(LUA_ENV) +#define LUA_ENV "_ENV" +#endif /* @@ -25,23 +27,22 @@ enum RESERVED { /* terminal symbols denoted by reserved words */ TK_AND = FIRST_RESERVED, TK_BREAK, TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, - TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, + TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, /* other terminal symbols */ - TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, - TK_NAME, TK_STRING, TK_EOS + TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, + TK_SHL, TK_SHR, + TK_DBCOLON, TK_EOS, + TK_FLT, TK_INT, TK_NAME, TK_STRING }; /* number of reserved words */ #define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) -/* array with token `names' */ -LUAI_DATA const char *const luaX_tokens []; - - typedef union { lua_Number r; + lua_Integer i; TString *ts; } SemInfo; /* semantics information */ @@ -52,29 +53,32 @@ typedef struct Token { } Token; +/* state of the lexer plus state of the parser when shared by all + functions */ typedef struct LexState { int current; /* current character (charint) */ int linenumber; /* input line counter */ - int lastline; /* line of last token `consumed' */ + int lastline; /* line of last token 'consumed' */ Token t; /* current token */ Token lookahead; /* look ahead token */ - struct FuncState *fs; /* `FuncState' is private to the parser */ + struct FuncState *fs; /* current function (parser) */ struct lua_State *L; ZIO *z; /* input stream */ Mbuffer *buff; /* buffer for tokens */ + Table *h; /* to avoid collection/reuse strings */ + struct Dyndata *dyd; /* dynamic structures used by the parser */ TString *source; /* current source name */ - char decpoint; /* locale decimal point */ + TString *envn; /* environment variable name */ } LexState; LUAI_FUNC void luaX_init (lua_State *L); LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, - TString *source); + TString *source, int firstchar); LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); LUAI_FUNC void luaX_next (LexState *ls); -LUAI_FUNC void luaX_lookahead (LexState *ls); -LUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token); -LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s); +LUAI_FUNC int luaX_lookahead (LexState *ls); +LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s); LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); diff --git a/app/src/main/jni/lua/llimits.h b/app/src/main/jni/lua/llimits.h index ca8dcb7..f21377f 100644 --- a/app/src/main/jni/lua/llimits.h +++ b/app/src/main/jni/lua/llimits.h @@ -1,6 +1,6 @@ /* -** $Id: llimits.h,v 1.69.1.1 2007/12/27 13:02:25 roberto Exp $ -** Limits, basic types, and some other `installation-dependent' definitions +** $Id: llimits.h,v 1.141 2015/11/19 19:16:22 roberto Exp $ +** Limits, basic types, and some other 'installation-dependent' definitions ** See Copyright Notice in lua.h */ @@ -14,115 +14,310 @@ #include "lua.h" +/* +** 'lu_mem' and 'l_mem' are unsigned/signed integers big enough to count +** the total memory used by Lua (in bytes). Usually, 'size_t' and +** 'ptrdiff_t' should work, but we use 'long' for 16-bit machines. +*/ +#if defined(LUAI_MEM) /* { external definitions? */ +typedef LUAI_UMEM lu_mem; +typedef LUAI_MEM l_mem; +#elif LUAI_BITSINT >= 32 /* }{ */ +typedef size_t lu_mem; +typedef ptrdiff_t l_mem; +#else /* 16-bit ints */ /* }{ */ +typedef unsigned long lu_mem; +typedef long l_mem; +#endif /* } */ -typedef LUAI_UINT32 lu_int32; -typedef LUAI_UMEM lu_mem; +/* chars used as small naturals (so that 'char' is reserved for characters) */ +typedef unsigned char lu_byte; -typedef LUAI_MEM l_mem; +/* maximum value for size_t */ +#define MAX_SIZET ((size_t)(~(size_t)0)) +/* maximum size visible for Lua (must be representable in a lua_Integer */ +#define MAX_SIZE (sizeof(size_t) < sizeof(lua_Integer) ? MAX_SIZET \ + : (size_t)(LUA_MAXINTEGER)) -/* chars used as small naturals (so that `char' is reserved for characters) */ -typedef unsigned char lu_byte; +#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)) -#define MAX_SIZET ((size_t)(~(size_t)0)-2) +#define MAX_LMEM ((l_mem)(MAX_LUMEM >> 1)) -#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) +#define MAX_INT INT_MAX /* maximum value of an int */ -#define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ /* -** conversion of pointer to integer +** conversion of pointer to unsigned integer: ** this is for hashing only; there is no problem if the integer ** cannot hold the whole pointer value */ -#define IntPoint(p) ((unsigned int)(lu_mem)(p)) +#define point2uint(p) ((unsigned int)((size_t)(p) & UINT_MAX)) /* type to ensure maximum alignment */ +#if defined(LUAI_USER_ALIGNMENT_T) typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; +#else +typedef union { + lua_Number n; + double u; + void *s; + lua_Integer i; + long l; +} L_Umaxalign; +#endif + -/* result of a `usual argument conversion' over lua_Number */ +/* types of 'usual argument conversions' for lua_Number and lua_Integer */ typedef LUAI_UACNUMBER l_uacNumber; +typedef LUAI_UACINT l_uacInt; /* internal assertions for in-house debugging */ -#ifdef lua_assert - +#if defined(lua_assert) #define check_exp(c,e) (lua_assert(c), (e)) -#define api_check(l,e) lua_assert(e) - +/* to avoid problems with conditions too long */ +#define lua_longassert(c) ((c) ? (void)0 : lua_assert(0)) #else - #define lua_assert(c) ((void)0) #define check_exp(c,e) (e) -#define api_check luai_apicheck +#define lua_longassert(c) ((void)0) +#endif +/* +** assertion for checking API calls +*/ +#if !defined(luai_apicheck) +#define luai_apicheck(l,e) lua_assert(e) #endif +#define api_check(l,e,msg) luai_apicheck(l,(e) && msg) + -#ifndef UNUSED -#define UNUSED(x) ((void)(x)) /* to avoid warnings */ +/* macro to avoid warnings about unused variables */ +#if !defined(UNUSED) +#define UNUSED(x) ((void)(x)) #endif -#ifndef cast +/* type casts (a macro highlights casts in the code) */ #define cast(t, exp) ((t)(exp)) -#endif +#define cast_void(i) cast(void, (i)) #define cast_byte(i) cast(lu_byte, (i)) #define cast_num(i) cast(lua_Number, (i)) #define cast_int(i) cast(int, (i)) +#define cast_uchar(i) cast(unsigned char, (i)) + + +/* cast a signed lua_Integer to lua_Unsigned */ +#if !defined(l_castS2U) +#define l_castS2U(i) ((lua_Unsigned)(i)) +#endif + +/* +** cast a lua_Unsigned to a signed lua_Integer; this cast is +** not strict ISO C, but two-complement architectures should +** work fine. +*/ +#if !defined(l_castU2S) +#define l_castU2S(i) ((lua_Integer)(i)) +#endif + + +/* +** non-return type +*/ +#if defined(__GNUC__) +#define l_noret void __attribute__((noreturn)) +#elif defined(_MSC_VER) && _MSC_VER >= 1200 +#define l_noret void __declspec(noreturn) +#else +#define l_noret void +#endif /* -** type for virtual-machine instructions +** maximum depth for nested C calls and syntactical nested non-terminals +** in a program. (Value must fit in an unsigned short int.) +*/ +#if !defined(LUAI_MAXCCALLS) +#define LUAI_MAXCCALLS 200 +#endif + + + +/* +** type for virtual-machine instructions; ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) */ -typedef lu_int32 Instruction; +#if LUAI_BITSINT >= 32 +typedef unsigned int Instruction; +#else +typedef unsigned long Instruction; +#endif -/* maximum stack for a Lua function */ -#define MAXSTACK 250 +/* +** Maximum length for short strings, that is, strings that are +** internalized. (Cannot be smaller than reserved words or tags for +** metamethods, as these strings must be internalized; +** #("function") = 8, #("__newindex") = 10.) +*/ +#if !defined(LUAI_MAXSHORTLEN) +#define LUAI_MAXSHORTLEN 40 +#endif + +/* +** Initial size for the string table (must be power of 2). +** The Lua core alone registers ~50 strings (reserved words + +** metaevent keys + a few others). Libraries would typically add +** a few dozens more. +*/ +#if !defined(MINSTRTABSIZE) +#define MINSTRTABSIZE 128 +#endif -/* minimum size for the string table (must be power of 2) */ -#ifndef MINSTRTABSIZE -#define MINSTRTABSIZE 32 +/* +** Size of cache for strings in the API. 'N' is the number of +** sets (better be a prime) and "M" is the size of each set (M == 1 +** makes a direct cache.) +*/ +#if !defined(STRCACHE_N) +#define STRCACHE_N 53 +#define STRCACHE_M 2 #endif /* minimum size for string buffer */ -#ifndef LUA_MINBUFFER +#if !defined(LUA_MINBUFFER) #define LUA_MINBUFFER 32 #endif -#ifndef lua_lock -#define lua_lock(L) ((void) 0) -#define lua_unlock(L) ((void) 0) +/* +** macros that are executed whenever program enters the Lua core +** ('lua_lock') and leaves the core ('lua_unlock') +*/ +#if !defined(lua_lock) +#define lua_lock(L) ((void) 0) +#define lua_unlock(L) ((void) 0) +#endif + +/* +** macro executed during Lua functions at points where the +** function can yield. +*/ +#if !defined(luai_threadyield) +#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} +#endif + + +/* +** these macros allow user-specific actions on threads when you defined +** LUAI_EXTRASPACE and need to do something extra when a thread is +** created/deleted/resumed/yielded. +*/ +#if !defined(luai_userstateopen) +#define luai_userstateopen(L) ((void)L) +#endif + +#if !defined(luai_userstateclose) +#define luai_userstateclose(L) ((void)L) +#endif + +#if !defined(luai_userstatethread) +#define luai_userstatethread(L,L1) ((void)L) +#endif + +#if !defined(luai_userstatefree) +#define luai_userstatefree(L,L1) ((void)L) +#endif + +#if !defined(luai_userstateresume) +#define luai_userstateresume(L,n) ((void)L) +#endif + +#if !defined(luai_userstateyield) +#define luai_userstateyield(L,n) ((void)L) #endif -#ifndef luai_threadyield -#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} + + +/* +** The luai_num* macros define the primitive operations over numbers. +*/ + +/* floor division (defined as 'floor(a/b)') */ +#if !defined(luai_numidiv) +#define luai_numidiv(L,a,b) ((void)L, l_floor(luai_numdiv(L,a,b))) #endif +/* float division */ +#if !defined(luai_numdiv) +#define luai_numdiv(L,a,b) ((a)/(b)) +#endif + +/* +** modulo: defined as 'a - floor(a/b)*b'; this definition gives NaN when +** 'b' is huge, but the result should be 'a'. 'fmod' gives the result of +** 'a - trunc(a/b)*b', and therefore must be corrected when 'trunc(a/b) +** ~= floor(a/b)'. That happens when the division has a non-integer +** negative result, which is equivalent to the test below. +*/ +#if !defined(luai_nummod) +#define luai_nummod(L,a,b,m) \ + { (m) = l_mathop(fmod)(a,b); if ((m)*(b) < 0) (m) += (b); } +#endif + +/* exponentiation */ +#if !defined(luai_numpow) +#define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b)) +#endif + +/* the others are quite standard operations */ +#if !defined(luai_numadd) +#define luai_numadd(L,a,b) ((a)+(b)) +#define luai_numsub(L,a,b) ((a)-(b)) +#define luai_nummul(L,a,b) ((a)*(b)) +#define luai_numunm(L,a) (-(a)) +#define luai_numeq(a,b) ((a)==(b)) +#define luai_numlt(a,b) ((a)<(b)) +#define luai_numle(a,b) ((a)<=(b)) +#define luai_numisnan(a) (!luai_numeq((a), (a))) +#endif + + + + /* ** macro to control inclusion of some hard tests on stack reallocation -*/ -#ifndef HARDSTACKTESTS -#define condhardstacktests(x) ((void)0) +*/ +#if !defined(HARDSTACKTESTS) +#define condmovestack(L,pre,pos) ((void)0) +#else +/* realloc stack keeping its size */ +#define condmovestack(L,pre,pos) \ + { int sz_ = (L)->stacksize; pre; luaD_reallocstack((L), sz_); pos; } +#endif + +#if !defined(HARDMEMTESTS) +#define condchangemem(L,pre,pos) ((void)0) #else -#define condhardstacktests(x) x +#define condchangemem(L,pre,pos) \ + { if (G(L)->gcrunning) { pre; luaC_fullgc(L, 0); pos; } } #endif #endif diff --git a/app/src/main/jni/lua/lmathlib.c b/app/src/main/jni/lua/lmathlib.c index 441fbf7..94815f1 100644 --- a/app/src/main/jni/lua/lmathlib.c +++ b/app/src/main/jni/lua/lmathlib.c @@ -1,16 +1,18 @@ /* -** $Id: lmathlib.c,v 1.67.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lmathlib.c,v 1.117 2015/10/02 15:39:23 roberto Exp $ ** Standard mathematical library ** See Copyright Notice in lua.h */ +#define lmathlib_c +#define LUA_LIB + +#include "lprefix.h" + #include #include -#define lmathlib_c -#define LUA_LIB - #include "lua.h" #include "lauxlib.h" @@ -18,229 +20,371 @@ #undef PI -#define PI (3.14159265358979323846) -#define RADIANS_PER_DEGREE (PI/180.0) - +#define PI (l_mathop(3.141592653589793238462643383279502884)) + + +#if !defined(l_rand) /* { */ +#if defined(LUA_USE_POSIX) +#define l_rand() random() +#define l_srand(x) srandom(x) +#define L_RANDMAX 2147483647 /* (2^31 - 1), following POSIX */ +#else +#define l_rand() rand() +#define l_srand(x) srand(x) +#define L_RANDMAX RAND_MAX +#endif +#endif /* } */ static int math_abs (lua_State *L) { - lua_pushnumber(L, fabs(luaL_checknumber(L, 1))); + if (lua_isinteger(L, 1)) { + lua_Integer n = lua_tointeger(L, 1); + if (n < 0) n = (lua_Integer)(0u - (lua_Unsigned)n); + lua_pushinteger(L, n); + } + else + lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1))); return 1; } static int math_sin (lua_State *L) { - lua_pushnumber(L, sin(luaL_checknumber(L, 1))); - return 1; -} - -static int math_sinh (lua_State *L) { - lua_pushnumber(L, sinh(luaL_checknumber(L, 1))); + lua_pushnumber(L, l_mathop(sin)(luaL_checknumber(L, 1))); return 1; } static int math_cos (lua_State *L) { - lua_pushnumber(L, cos(luaL_checknumber(L, 1))); - return 1; -} - -static int math_cosh (lua_State *L) { - lua_pushnumber(L, cosh(luaL_checknumber(L, 1))); + lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1))); return 1; } static int math_tan (lua_State *L) { - lua_pushnumber(L, tan(luaL_checknumber(L, 1))); - return 1; -} - -static int math_tanh (lua_State *L) { - lua_pushnumber(L, tanh(luaL_checknumber(L, 1))); + lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1))); return 1; } static int math_asin (lua_State *L) { - lua_pushnumber(L, asin(luaL_checknumber(L, 1))); + lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1))); return 1; } static int math_acos (lua_State *L) { - lua_pushnumber(L, acos(luaL_checknumber(L, 1))); + lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1))); return 1; } static int math_atan (lua_State *L) { - lua_pushnumber(L, atan(luaL_checknumber(L, 1))); + lua_Number y = luaL_checknumber(L, 1); + lua_Number x = luaL_optnumber(L, 2, 1); + lua_pushnumber(L, l_mathop(atan2)(y, x)); return 1; } -static int math_atan2 (lua_State *L) { - lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + +static int math_toint (lua_State *L) { + int valid; + lua_Integer n = lua_tointegerx(L, 1, &valid); + if (valid) + lua_pushinteger(L, n); + else { + luaL_checkany(L, 1); + lua_pushnil(L); /* value is not convertible to integer */ + } return 1; } -static int math_ceil (lua_State *L) { - lua_pushnumber(L, ceil(luaL_checknumber(L, 1))); - return 1; + +static void pushnumint (lua_State *L, lua_Number d) { + lua_Integer n; + if (lua_numbertointeger(d, &n)) /* does 'd' fit in an integer? */ + lua_pushinteger(L, n); /* result is integer */ + else + lua_pushnumber(L, d); /* result is float */ } + static int math_floor (lua_State *L) { - lua_pushnumber(L, floor(luaL_checknumber(L, 1))); + if (lua_isinteger(L, 1)) + lua_settop(L, 1); /* integer is its own floor */ + else { + lua_Number d = l_mathop(floor)(luaL_checknumber(L, 1)); + pushnumint(L, d); + } return 1; } + +static int math_ceil (lua_State *L) { + if (lua_isinteger(L, 1)) + lua_settop(L, 1); /* integer is its own ceil */ + else { + lua_Number d = l_mathop(ceil)(luaL_checknumber(L, 1)); + pushnumint(L, d); + } + return 1; +} + + static int math_fmod (lua_State *L) { - lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + if (lua_isinteger(L, 1) && lua_isinteger(L, 2)) { + lua_Integer d = lua_tointeger(L, 2); + if ((lua_Unsigned)d + 1u <= 1u) { /* special cases: -1 or 0 */ + luaL_argcheck(L, d != 0, 2, "zero"); + lua_pushinteger(L, 0); /* avoid overflow with 0x80000... / -1 */ + } + else + lua_pushinteger(L, lua_tointeger(L, 1) % d); + } + else + lua_pushnumber(L, l_mathop(fmod)(luaL_checknumber(L, 1), + luaL_checknumber(L, 2))); return 1; } + +/* +** next function does not use 'modf', avoiding problems with 'double*' +** (which is not compatible with 'float*') when lua_Number is not +** 'double'. +*/ static int math_modf (lua_State *L) { - double ip; - double fp = modf(luaL_checknumber(L, 1), &ip); - lua_pushnumber(L, ip); - lua_pushnumber(L, fp); + if (lua_isinteger(L ,1)) { + lua_settop(L, 1); /* number is its own integer part */ + lua_pushnumber(L, 0); /* no fractional part */ + } + else { + lua_Number n = luaL_checknumber(L, 1); + /* integer part (rounds toward zero) */ + lua_Number ip = (n < 0) ? l_mathop(ceil)(n) : l_mathop(floor)(n); + pushnumint(L, ip); + /* fractional part (test needed for inf/-inf) */ + lua_pushnumber(L, (n == ip) ? l_mathop(0.0) : (n - ip)); + } return 2; } + static int math_sqrt (lua_State *L) { - lua_pushnumber(L, sqrt(luaL_checknumber(L, 1))); + lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1))); return 1; } -static int math_pow (lua_State *L) { - lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); - return 1; -} -static int math_log (lua_State *L) { - lua_pushnumber(L, log(luaL_checknumber(L, 1))); +static int math_ult (lua_State *L) { + lua_Integer a = luaL_checkinteger(L, 1); + lua_Integer b = luaL_checkinteger(L, 2); + lua_pushboolean(L, (lua_Unsigned)a < (lua_Unsigned)b); return 1; } -static int math_log10 (lua_State *L) { - lua_pushnumber(L, log10(luaL_checknumber(L, 1))); +static int math_log (lua_State *L) { + lua_Number x = luaL_checknumber(L, 1); + lua_Number res; + if (lua_isnoneornil(L, 2)) + res = l_mathop(log)(x); + else { + lua_Number base = luaL_checknumber(L, 2); +#if !defined(LUA_USE_C89) + if (base == 2.0) res = l_mathop(log2)(x); else +#endif + if (base == 10.0) res = l_mathop(log10)(x); + else res = l_mathop(log)(x)/l_mathop(log)(base); + } + lua_pushnumber(L, res); return 1; } static int math_exp (lua_State *L) { - lua_pushnumber(L, exp(luaL_checknumber(L, 1))); + lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1))); return 1; } static int math_deg (lua_State *L) { - lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE); + lua_pushnumber(L, luaL_checknumber(L, 1) * (l_mathop(180.0) / PI)); return 1; } static int math_rad (lua_State *L) { - lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE); + lua_pushnumber(L, luaL_checknumber(L, 1) * (PI / l_mathop(180.0))); return 1; } -static int math_frexp (lua_State *L) { - int e; - lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e)); - lua_pushinteger(L, e); - return 2; -} - -static int math_ldexp (lua_State *L) { - lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2))); - return 1; -} - - static int math_min (lua_State *L) { int n = lua_gettop(L); /* number of arguments */ - lua_Number dmin = luaL_checknumber(L, 1); + int imin = 1; /* index of current minimum value */ int i; - for (i=2; i<=n; i++) { - lua_Number d = luaL_checknumber(L, i); - if (d < dmin) - dmin = d; + luaL_argcheck(L, n >= 1, 1, "value expected"); + for (i = 2; i <= n; i++) { + if (lua_compare(L, i, imin, LUA_OPLT)) + imin = i; } - lua_pushnumber(L, dmin); + lua_pushvalue(L, imin); return 1; } static int math_max (lua_State *L) { int n = lua_gettop(L); /* number of arguments */ - lua_Number dmax = luaL_checknumber(L, 1); + int imax = 1; /* index of current maximum value */ int i; - for (i=2; i<=n; i++) { - lua_Number d = luaL_checknumber(L, i); - if (d > dmax) - dmax = d; + luaL_argcheck(L, n >= 1, 1, "value expected"); + for (i = 2; i <= n; i++) { + if (lua_compare(L, imax, i, LUA_OPLT)) + imax = i; } - lua_pushnumber(L, dmax); + lua_pushvalue(L, imax); return 1; } - +/* +** This function uses 'double' (instead of 'lua_Number') to ensure that +** all bits from 'l_rand' can be represented, and that 'RANDMAX + 1.0' +** will keep full precision (ensuring that 'r' is always less than 1.0.) +*/ static int math_random (lua_State *L) { - /* the `%' avoids the (rare) case of r==1, and is needed also because on - some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */ - lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX; + lua_Integer low, up; + double r = (double)l_rand() * (1.0 / ((double)L_RANDMAX + 1.0)); switch (lua_gettop(L)) { /* check number of arguments */ case 0: { /* no arguments */ - lua_pushnumber(L, r); /* Number between 0 and 1 */ - break; + lua_pushnumber(L, (lua_Number)r); /* Number between 0 and 1 */ + return 1; } case 1: { /* only upper limit */ - int u = luaL_checkint(L, 1); - luaL_argcheck(L, 1<=u, 1, "interval is empty"); - lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */ + low = 1; + up = luaL_checkinteger(L, 1); break; } case 2: { /* lower and upper limits */ - int l = luaL_checkint(L, 1); - int u = luaL_checkint(L, 2); - luaL_argcheck(L, l<=u, 2, "interval is empty"); - lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */ + low = luaL_checkinteger(L, 1); + up = luaL_checkinteger(L, 2); break; } default: return luaL_error(L, "wrong number of arguments"); } + /* random integer in the interval [low, up] */ + luaL_argcheck(L, low <= up, 1, "interval is empty"); + luaL_argcheck(L, low >= 0 || up <= LUA_MAXINTEGER + low, 1, + "interval too large"); + r *= (double)(up - low) + 1.0; + lua_pushinteger(L, (lua_Integer)r + low); return 1; } static int math_randomseed (lua_State *L) { - srand(luaL_checkint(L, 1)); + l_srand((unsigned int)(lua_Integer)luaL_checknumber(L, 1)); + (void)l_rand(); /* discard first value to avoid undesirable correlations */ return 0; } +static int math_type (lua_State *L) { + if (lua_type(L, 1) == LUA_TNUMBER) { + if (lua_isinteger(L, 1)) + lua_pushliteral(L, "integer"); + else + lua_pushliteral(L, "float"); + } + else { + luaL_checkany(L, 1); + lua_pushnil(L); + } + return 1; +} + + +/* +** {================================================================== +** Deprecated functions (for compatibility only) +** =================================================================== +*/ +#if defined(LUA_COMPAT_MATHLIB) + +static int math_cosh (lua_State *L) { + lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_sinh (lua_State *L) { + lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_tanh (lua_State *L) { + lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_pow (lua_State *L) { + lua_Number x = luaL_checknumber(L, 1); + lua_Number y = luaL_checknumber(L, 2); + lua_pushnumber(L, l_mathop(pow)(x, y)); + return 1; +} + +static int math_frexp (lua_State *L) { + int e; + lua_pushnumber(L, l_mathop(frexp)(luaL_checknumber(L, 1), &e)); + lua_pushinteger(L, e); + return 2; +} + +static int math_ldexp (lua_State *L) { + lua_Number x = luaL_checknumber(L, 1); + int ep = (int)luaL_checkinteger(L, 2); + lua_pushnumber(L, l_mathop(ldexp)(x, ep)); + return 1; +} + +static int math_log10 (lua_State *L) { + lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1))); + return 1; +} + +#endif +/* }================================================================== */ + + + static const luaL_Reg mathlib[] = { {"abs", math_abs}, {"acos", math_acos}, {"asin", math_asin}, - {"atan2", math_atan2}, {"atan", math_atan}, {"ceil", math_ceil}, - {"cosh", math_cosh}, {"cos", math_cos}, {"deg", math_deg}, {"exp", math_exp}, + {"tointeger", math_toint}, {"floor", math_floor}, {"fmod", math_fmod}, - {"frexp", math_frexp}, - {"ldexp", math_ldexp}, - {"log10", math_log10}, + {"ult", math_ult}, {"log", math_log}, {"max", math_max}, {"min", math_min}, {"modf", math_modf}, - {"pow", math_pow}, {"rad", math_rad}, {"random", math_random}, {"randomseed", math_randomseed}, - {"sinh", math_sinh}, {"sin", math_sin}, {"sqrt", math_sqrt}, - {"tanh", math_tanh}, {"tan", math_tan}, + {"type", math_type}, +#if defined(LUA_COMPAT_MATHLIB) + {"atan2", math_atan}, + {"cosh", math_cosh}, + {"sinh", math_sinh}, + {"tanh", math_tanh}, + {"pow", math_pow}, + {"frexp", math_frexp}, + {"ldexp", math_ldexp}, + {"log10", math_log10}, +#endif + /* placeholders */ + {"pi", NULL}, + {"huge", NULL}, + {"maxinteger", NULL}, + {"mininteger", NULL}, {NULL, NULL} }; @@ -248,16 +392,16 @@ static const luaL_Reg mathlib[] = { /* ** Open math library */ -LUALIB_API int luaopen_math (lua_State *L) { - luaL_register(L, LUA_MATHLIBNAME, mathlib); +LUAMOD_API int luaopen_math (lua_State *L) { + luaL_newlib(L, mathlib); lua_pushnumber(L, PI); lua_setfield(L, -2, "pi"); - lua_pushnumber(L, HUGE_VAL); + lua_pushnumber(L, (lua_Number)HUGE_VAL); lua_setfield(L, -2, "huge"); -#if defined(LUA_COMPAT_MOD) - lua_getfield(L, -1, "fmod"); - lua_setfield(L, -2, "mod"); -#endif + lua_pushinteger(L, LUA_MAXINTEGER); + lua_setfield(L, -2, "maxinteger"); + lua_pushinteger(L, LUA_MININTEGER); + lua_setfield(L, -2, "mininteger"); return 1; } diff --git a/app/src/main/jni/lua/lmem.c b/app/src/main/jni/lua/lmem.c index ae7d8c9..0a0476c 100644 --- a/app/src/main/jni/lua/lmem.c +++ b/app/src/main/jni/lua/lmem.c @@ -1,19 +1,22 @@ /* -** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lmem.c,v 1.91 2015/03/06 19:45:54 roberto Exp $ ** Interface to Memory Manager ** See Copyright Notice in lua.h */ - -#include - #define lmem_c #define LUA_CORE +#include "lprefix.h" + + +#include + #include "lua.h" #include "ldebug.h" #include "ldo.h" +#include "lgc.h" #include "lmem.h" #include "lobject.h" #include "lstate.h" @@ -23,16 +26,15 @@ /* ** About the realloc function: ** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); -** (`osize' is the old size, `nsize' is the new size) -** -** Lua ensures that (ptr == NULL) iff (osize == 0). +** ('osize' is the old size, 'nsize' is the new size) ** -** * frealloc(ud, NULL, 0, x) creates a new block of size `x' +** * frealloc(ud, NULL, x, s) creates a new block of size 's' (no +** matter 'x'). ** -** * frealloc(ud, p, x, 0) frees the block `p' -** (in this specific case, frealloc must return NULL). +** * frealloc(ud, p, x, 0) frees the block 'p' +** (in this specific case, frealloc must return NULL); ** particularly, frealloc(ud, NULL, 0, 0) does nothing -** (which is equivalent to free(NULL) in ANSI C) +** (which is equivalent to free(NULL) in ISO C) ** ** frealloc returns NULL if it cannot create or reallocate the area ** (any reallocation to an equal or smaller size cannot fail!) @@ -44,12 +46,12 @@ void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, - int limit, const char *errormsg) { + int limit, const char *what) { void *newblock; int newsize; if (*size >= limit/2) { /* cannot double it? */ if (*size >= limit) /* cannot grow even a little? */ - luaG_runerror(L, errormsg); + luaG_runerror(L, "too many %s (limit is %d)", what, limit); newsize = limit; /* still have at least one free place */ } else { @@ -63,9 +65,8 @@ void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, } -void *luaM_toobig (lua_State *L) { +l_noret luaM_toobig (lua_State *L) { luaG_runerror(L, "memory allocation error: block too big"); - return NULL; /* to avoid warnings */ } @@ -74,13 +75,26 @@ void *luaM_toobig (lua_State *L) { ** generic allocation routine. */ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { + void *newblock; global_State *g = G(L); - lua_assert((osize == 0) == (block == NULL)); - block = (*g->frealloc)(g->ud, block, osize, nsize); - if (block == NULL && nsize > 0) - luaD_throw(L, LUA_ERRMEM); - lua_assert((nsize == 0) == (block == NULL)); - g->totalbytes = (g->totalbytes - osize) + nsize; - return block; + size_t realosize = (block) ? osize : 0; + lua_assert((realosize == 0) == (block == NULL)); +#if defined(HARDMEMTESTS) + if (nsize > realosize && g->gcrunning) + luaC_fullgc(L, 1); /* force a GC whenever possible */ +#endif + newblock = (*g->frealloc)(g->ud, block, osize, nsize); + if (newblock == NULL && nsize > 0) { + lua_assert(nsize > realosize); /* cannot fail when shrinking a block */ + if (g->version) { /* is state fully built? */ + luaC_fullgc(L, 1); /* try to free some memory... */ + newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ + } + if (newblock == NULL) + luaD_throw(L, LUA_ERRMEM); + } + lua_assert((nsize == 0) == (newblock == NULL)); + g->GCdebt = (g->GCdebt + nsize) - realosize; + return newblock; } diff --git a/app/src/main/jni/lua/lmem.h b/app/src/main/jni/lua/lmem.h index 7c2dcb3..30f4848 100644 --- a/app/src/main/jni/lua/lmem.h +++ b/app/src/main/jni/lua/lmem.h @@ -1,5 +1,5 @@ /* -** $Id: lmem.h,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lmem.h,v 1.43 2014/12/19 17:26:14 roberto Exp $ ** Interface to Memory Manager ** See Copyright Notice in lua.h */ @@ -13,23 +13,42 @@ #include "llimits.h" #include "lua.h" -#define MEMERRMSG "not enough memory" - +/* +** This macro reallocs a vector 'b' from 'on' to 'n' elements, where +** each element has size 'e'. In case of arithmetic overflow of the +** product 'n'*'e', it raises an error (calling 'luaM_toobig'). Because +** 'e' is always constant, it avoids the runtime division MAX_SIZET/(e). +** +** (The macro is somewhat complex to avoid warnings: The 'sizeof' +** comparison avoids a runtime comparison when overflow cannot occur. +** The compiler should be able to optimize the real test by itself, but +** when it does it, it may give a warning about "comparison is always +** false due to limited range of data type"; the +1 tricks the compiler, +** avoiding this warning but also this optimization.) +*/ #define luaM_reallocv(L,b,on,n,e) \ - ((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \ - luaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \ - luaM_toobig(L)) + (((sizeof(n) >= sizeof(size_t) && cast(size_t, (n)) + 1 > MAX_SIZET/(e)) \ + ? luaM_toobig(L) : cast_void(0)) , \ + luaM_realloc_(L, (b), (on)*(e), (n)*(e))) + +/* +** Arrays of chars do not need any test +*/ +#define luaM_reallocvchar(L,b,on,n) \ + cast(char *, luaM_realloc_(L, (b), (on)*sizeof(char), (n)*sizeof(char))) #define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) #define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) -#define luaM_freearray(L, b, n, t) luaM_reallocv(L, (b), n, 0, sizeof(t)) +#define luaM_freearray(L, b, n) luaM_realloc_(L, (b), (n)*sizeof(*(b)), 0) -#define luaM_malloc(L,t) luaM_realloc_(L, NULL, 0, (t)) +#define luaM_malloc(L,s) luaM_realloc_(L, NULL, 0, (s)) #define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) #define luaM_newvector(L,n,t) \ cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) +#define luaM_newobject(L,tag,s) luaM_realloc_(L, NULL, tag, (s)) + #define luaM_growvector(L,v,nelems,size,t,limit,e) \ if ((nelems)+1 > (size)) \ ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) @@ -37,13 +56,14 @@ #define luaM_reallocvector(L, v,oldn,n,t) \ ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) +LUAI_FUNC l_noret luaM_toobig (lua_State *L); +/* not to be called directly */ LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, size_t size); -LUAI_FUNC void *luaM_toobig (lua_State *L); LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elem, int limit, - const char *errormsg); + const char *what); #endif diff --git a/app/src/main/jni/lua/loadlib.c b/app/src/main/jni/lua/loadlib.c index 6158c53..7911928 100644 --- a/app/src/main/jni/lua/loadlib.c +++ b/app/src/main/jni/lua/loadlib.c @@ -1,20 +1,22 @@ /* -** $Id: loadlib.c,v 1.52.1.4 2009/09/09 13:17:16 roberto Exp $ +** $Id: loadlib.c,v 1.127 2015/11/23 11:30:45 roberto Exp $ ** Dynamic library loader for Lua ** See Copyright Notice in lua.h ** ** This module contains an implementation of loadlib for Unix systems -** that have dlfcn, an implementation for Darwin (Mac OS X), an -** implementation for Windows, and a stub for other systems. +** that have dlfcn, an implementation for Windows, and a stub for other +** systems. */ +#define loadlib_c +#define LUA_LIB -#include -#include +#include "lprefix.h" -#define loadlib_c -#define LUA_LIB +#include +#include +#include #include "lua.h" @@ -22,6 +24,61 @@ #include "lualib.h" +/* +** LUA_PATH_VAR and LUA_CPATH_VAR are the names of the environment +** variables that Lua check to set its paths. +*/ +#if !defined(LUA_PATH_VAR) +#define LUA_PATH_VAR "LUA_PATH" +#endif + +#if !defined(LUA_CPATH_VAR) +#define LUA_CPATH_VAR "LUA_CPATH" +#endif + +#define LUA_PATHSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR + +#define LUA_PATHVARVERSION LUA_PATH_VAR LUA_PATHSUFFIX +#define LUA_CPATHVARVERSION LUA_CPATH_VAR LUA_PATHSUFFIX + +/* +** LUA_PATH_SEP is the character that separates templates in a path. +** LUA_PATH_MARK is the string that marks the substitution points in a +** template. +** LUA_EXEC_DIR in a Windows path is replaced by the executable's +** directory. +** LUA_IGMARK is a mark to ignore all before it when building the +** luaopen_ function name. +*/ +#if !defined (LUA_PATH_SEP) +#define LUA_PATH_SEP ";" +#endif +#if !defined (LUA_PATH_MARK) +#define LUA_PATH_MARK "?" +#endif +#if !defined (LUA_EXEC_DIR) +#define LUA_EXEC_DIR "!" +#endif +#if !defined (LUA_IGMARK) +#define LUA_IGMARK "-" +#endif + + +/* +** LUA_CSUBSEP is the character that replaces dots in submodule names +** when searching for a C loader. +** LUA_LSUBSEP is the character that replaces dots in submodule names +** when searching for a Lua loader. +*/ +#if !defined(LUA_CSUBSEP) +#define LUA_CSUBSEP LUA_DIRSEP +#endif + +#if !defined(LUA_LSUBSEP) +#define LUA_LSUBSEP LUA_DIRSEP +#endif + + /* prefix for open functions in C libraries */ #define LUA_POF "luaopen_" @@ -29,26 +86,45 @@ #define LUA_OFSEP "_" -#define LIBPREFIX "LOADLIB: " +/* +** unique key for table in the registry that keeps handles +** for all loaded C libraries +*/ +static const int CLIBS = 0; -#define POF LUA_POF #define LIB_FAIL "open" +#define setprogdir(L) ((void)0) -/* error codes for ll_loadfunc */ -#define ERRLIB 1 -#define ERRFUNC 2 -#define setprogdir(L) ((void)0) +/* +** system-dependent functions +*/ +/* +** unload library 'lib' +*/ +static void lsys_unloadlib (void *lib); -static void ll_unloadlib (void *lib); -static void *ll_load (lua_State *L, const char *path); -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); +/* +** load C library in file 'path'. If 'seeglb', load with all names in +** the library global. +** Returns the library; in case of error, returns NULL plus an +** error string in the stack. +*/ +static void *lsys_load (lua_State *L, const char *path, int seeglb); +/* +** Try to find a function named 'sym' in library 'lib'. +** Returns the function; in case of error, returns NULL plus an +** error string in the stack. +*/ +static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym); -#if defined(LUA_DL_DLOPEN) + + +#if defined(LUA_USE_DLOPEN) /* { */ /* ** {======================================================================== ** This is an implementation of loadlib based on the dlfcn interface. @@ -60,20 +136,32 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); #include -static void ll_unloadlib (void *lib) { +/* +** Macro to convert pointer-to-void* to pointer-to-function. This cast +** is undefined according to ISO C, but POSIX assumes that it works. +** (The '__extension__' in gnu compilers is only to avoid warnings.) +*/ +#if defined(__GNUC__) +#define cast_func(p) (__extension__ (lua_CFunction)(p)) +#else +#define cast_func(p) ((lua_CFunction)(p)) +#endif + + +static void lsys_unloadlib (void *lib) { dlclose(lib); } -static void *ll_load (lua_State *L, const char *path) { - void *lib = dlopen(path, RTLD_NOW); +static void *lsys_load (lua_State *L, const char *path, int seeglb) { + void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL)); if (lib == NULL) lua_pushstring(L, dlerror()); return lib; } -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { - lua_CFunction f = (lua_CFunction)dlsym(lib, sym); +static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { + lua_CFunction f = cast_func(dlsym(lib, sym)); if (f == NULL) lua_pushstring(L, dlerror()); return f; } @@ -82,7 +170,7 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { -#elif defined(LUA_DL_DLL) +#elif defined(LUA_DL_DLL) /* }{ */ /* ** {====================================================================== ** This is an implementation of loadlib for Windows using native functions. @@ -91,9 +179,16 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { #include - #undef setprogdir +/* +** optional flags for LoadLibraryEx +*/ +#if !defined(LUA_LLE_FLAGS) +#define LUA_LLE_FLAGS 0 +#endif + + static void setprogdir (lua_State *L) { char buff[MAX_PATH + 1]; char *lb; @@ -103,7 +198,7 @@ static void setprogdir (lua_State *L) { luaL_error(L, "unable to get ModuleFileName"); else { *lb = '\0'; - luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff); + luaL_gsub(L, lua_tostring(L, -1), LUA_EXEC_DIR, buff); lua_remove(L, -2); /* remove original string */ } } @@ -113,26 +208,27 @@ static void pusherror (lua_State *L) { int error = GetLastError(); char buffer[128]; if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, error, 0, buffer, sizeof(buffer), NULL)) + NULL, error, 0, buffer, sizeof(buffer)/sizeof(char), NULL)) lua_pushstring(L, buffer); else lua_pushfstring(L, "system error %d\n", error); } -static void ll_unloadlib (void *lib) { - FreeLibrary((HINSTANCE)lib); +static void lsys_unloadlib (void *lib) { + FreeLibrary((HMODULE)lib); } -static void *ll_load (lua_State *L, const char *path) { - HINSTANCE lib = LoadLibraryA(path); +static void *lsys_load (lua_State *L, const char *path, int seeglb) { + HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS); + (void)(seeglb); /* not used: symbols are 'global' by default */ if (lib == NULL) pusherror(L); return lib; } -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { - lua_CFunction f = (lua_CFunction)GetProcAddress((HINSTANCE)lib, sym); +static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { + lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym); if (f == NULL) pusherror(L); return f; } @@ -140,89 +236,7 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { /* }====================================================== */ - -#elif defined(LUA_DL_DYLD) -/* -** {====================================================================== -** Native Mac OS X / Darwin Implementation -** ======================================================================= -*/ - -#include - - -/* Mac appends a `_' before C function names */ -#undef POF -#define POF "_" LUA_POF - - -static void pusherror (lua_State *L) { - const char *err_str; - const char *err_file; - NSLinkEditErrors err; - int err_num; - NSLinkEditError(&err, &err_num, &err_file, &err_str); - lua_pushstring(L, err_str); -} - - -static const char *errorfromcode (NSObjectFileImageReturnCode ret) { - switch (ret) { - case NSObjectFileImageInappropriateFile: - return "file is not a bundle"; - case NSObjectFileImageArch: - return "library is for wrong CPU type"; - case NSObjectFileImageFormat: - return "bad format"; - case NSObjectFileImageAccess: - return "cannot access file"; - case NSObjectFileImageFailure: - default: - return "unable to load library"; - } -} - - -static void ll_unloadlib (void *lib) { - NSUnLinkModule((NSModule)lib, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES); -} - - -static void *ll_load (lua_State *L, const char *path) { - NSObjectFileImage img; - NSObjectFileImageReturnCode ret; - /* this would be a rare case, but prevents crashing if it happens */ - if(!_dyld_present()) { - lua_pushliteral(L, "dyld not present"); - return NULL; - } - ret = NSCreateObjectFileImageFromFile(path, &img); - if (ret == NSObjectFileImageSuccess) { - NSModule mod = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE | - NSLINKMODULE_OPTION_RETURN_ON_ERROR); - NSDestroyObjectFileImage(img); - if (mod == NULL) pusherror(L); - return mod; - } - lua_pushstring(L, errorfromcode(ret)); - return NULL; -} - - -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { - NSSymbol nss = NSLookupSymbolInModule((NSModule)lib, sym); - if (nss == NULL) { - lua_pushfstring(L, "symbol " LUA_QS " not found", sym); - return NULL; - } - return (lua_CFunction)NSAddressOfSymbol(nss); -} - -/* }====================================================== */ - - - -#else +#else /* }{ */ /* ** {====================================================== ** Fallback for other systems @@ -236,72 +250,103 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { #define DLMSG "dynamic libraries not enabled; check your Lua installation" -static void ll_unloadlib (void *lib) { - (void)lib; /* to avoid warnings */ +static void lsys_unloadlib (void *lib) { + (void)(lib); /* not used */ } -static void *ll_load (lua_State *L, const char *path) { - (void)path; /* to avoid warnings */ +static void *lsys_load (lua_State *L, const char *path, int seeglb) { + (void)(path); (void)(seeglb); /* not used */ lua_pushliteral(L, DLMSG); return NULL; } -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { - (void)lib; (void)sym; /* to avoid warnings */ +static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { + (void)(lib); (void)(sym); /* not used */ lua_pushliteral(L, DLMSG); return NULL; } /* }====================================================== */ -#endif +#endif /* } */ - -static void **ll_register (lua_State *L, const char *path) { - void **plib; - lua_pushfstring(L, "%s%s", LIBPREFIX, path); - lua_gettable(L, LUA_REGISTRYINDEX); /* check library in registry? */ - if (!lua_isnil(L, -1)) /* is there an entry? */ - plib = (void **)lua_touserdata(L, -1); - else { /* no entry yet; create one */ - lua_pop(L, 1); - plib = (void **)lua_newuserdata(L, sizeof(const void *)); - *plib = NULL; - luaL_getmetatable(L, "_LOADLIB"); - lua_setmetatable(L, -2); - lua_pushfstring(L, "%s%s", LIBPREFIX, path); - lua_pushvalue(L, -2); - lua_settable(L, LUA_REGISTRYINDEX); - } +/* +** return registry.CLIBS[path] +*/ +static void *checkclib (lua_State *L, const char *path) { + void *plib; + lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS); + lua_getfield(L, -1, path); + plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */ + lua_pop(L, 2); /* pop CLIBS table and 'plib' */ return plib; } /* -** __gc tag method: calls library's `ll_unloadlib' function with the lib -** handle +** registry.CLIBS[path] = plib -- for queries +** registry.CLIBS[#CLIBS + 1] = plib -- also keep a list of all libraries +*/ +static void addtoclib (lua_State *L, const char *path, void *plib) { + lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS); + lua_pushlightuserdata(L, plib); + lua_pushvalue(L, -1); + lua_setfield(L, -3, path); /* CLIBS[path] = plib */ + lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */ + lua_pop(L, 1); /* pop CLIBS table */ +} + + +/* +** __gc tag method for CLIBS table: calls 'lsys_unloadlib' for all lib +** handles in list CLIBS */ static int gctm (lua_State *L) { - void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB"); - if (*lib) ll_unloadlib(*lib); - *lib = NULL; /* mark library as closed */ + lua_Integer n = luaL_len(L, 1); + for (; n >= 1; n--) { /* for each handle, in reverse order */ + lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */ + lsys_unloadlib(lua_touserdata(L, -1)); + lua_pop(L, 1); /* pop handle */ + } return 0; } -static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { - void **reg = ll_register(L, path); - if (*reg == NULL) *reg = ll_load(L, path); - if (*reg == NULL) - return ERRLIB; /* unable to load library */ + +/* error codes for 'lookforfunc' */ +#define ERRLIB 1 +#define ERRFUNC 2 + +/* +** Look for a C function named 'sym' in a dynamically loaded library +** 'path'. +** First, check whether the library is already loaded; if not, try +** to load it. +** Then, if 'sym' is '*', return true (as library has been loaded). +** Otherwise, look for symbol 'sym' in the library and push a +** C function with that symbol. +** Return 0 and 'true' or a function in the stack; in case of +** errors, return an error code and an error message in the stack. +*/ +static int lookforfunc (lua_State *L, const char *path, const char *sym) { + void *reg = checkclib(L, path); /* check loaded C libraries */ + if (reg == NULL) { /* must load library? */ + reg = lsys_load(L, path, *sym == '*'); /* global symbols if 'sym'=='*' */ + if (reg == NULL) return ERRLIB; /* unable to load library */ + addtoclib(L, path, reg); + } + if (*sym == '*') { /* loading only library (no function)? */ + lua_pushboolean(L, 1); /* return 'true' */ + return 0; /* no errors */ + } else { - lua_CFunction f = ll_sym(L, *reg, sym); + lua_CFunction f = lsys_sym(L, reg, sym); if (f == NULL) return ERRFUNC; /* unable to find function */ - lua_pushcfunction(L, f); - return 0; /* return function */ + lua_pushcfunction(L, f); /* else create new function */ + return 0; /* no errors */ } } @@ -309,7 +354,7 @@ static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { static int ll_loadlib (lua_State *L) { const char *path = luaL_checkstring(L, 1); const char *init = luaL_checkstring(L, 2); - int stat = ll_loadfunc(L, path, init); + int stat = lookforfunc(L, path, init); if (stat == 0) /* no errors? */ return 1; /* return the loaded function */ else { /* error; error message is on stack top */ @@ -339,153 +384,193 @@ static int readable (const char *filename) { static const char *pushnexttemplate (lua_State *L, const char *path) { const char *l; - while (*path == *LUA_PATHSEP) path++; /* skip separators */ + while (*path == *LUA_PATH_SEP) path++; /* skip separators */ if (*path == '\0') return NULL; /* no more templates */ - l = strchr(path, *LUA_PATHSEP); /* find next separator */ + l = strchr(path, *LUA_PATH_SEP); /* find next separator */ if (l == NULL) l = path + strlen(path); lua_pushlstring(L, path, l - path); /* template */ return l; } -static const char *findfile (lua_State *L, const char *name, - const char *pname) { - const char *path; - name = luaL_gsub(L, name, ".", LUA_DIRSEP); - lua_getfield(L, LUA_ENVIRONINDEX, pname); - path = lua_tostring(L, -1); - if (path == NULL) - luaL_error(L, LUA_QL("package.%s") " must be a string", pname); - lua_pushliteral(L, ""); /* error accumulator */ +static const char *searchpath (lua_State *L, const char *name, + const char *path, + const char *sep, + const char *dirsep) { + luaL_Buffer msg; /* to build error message */ + luaL_buffinit(L, &msg); + if (*sep != '\0') /* non-empty separator? */ + name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */ while ((path = pushnexttemplate(L, path)) != NULL) { - const char *filename; - filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); + const char *filename = luaL_gsub(L, lua_tostring(L, -1), + LUA_PATH_MARK, name); lua_remove(L, -2); /* remove path template */ if (readable(filename)) /* does file exist and is readable? */ return filename; /* return that file name */ - lua_pushfstring(L, "\n\tno file " LUA_QS, filename); + lua_pushfstring(L, "\n\tno file '%s'", filename); lua_remove(L, -2); /* remove file name */ - lua_concat(L, 2); /* add entry to possible error message */ + luaL_addvalue(&msg); /* concatenate error msg. entry */ } + luaL_pushresult(&msg); /* create error message */ return NULL; /* not found */ } -static void loaderror (lua_State *L, const char *filename) { - luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s", - lua_tostring(L, 1), filename, lua_tostring(L, -1)); +static int ll_searchpath (lua_State *L) { + const char *f = searchpath(L, luaL_checkstring(L, 1), + luaL_checkstring(L, 2), + luaL_optstring(L, 3, "."), + luaL_optstring(L, 4, LUA_DIRSEP)); + if (f != NULL) return 1; + else { /* error message is on top of the stack */ + lua_pushnil(L); + lua_insert(L, -2); + return 2; /* return nil + error message */ + } +} + + +static const char *findfile (lua_State *L, const char *name, + const char *pname, + const char *dirsep) { + const char *path; + lua_getfield(L, lua_upvalueindex(1), pname); + path = lua_tostring(L, -1); + if (path == NULL) + luaL_error(L, "'package.%s' must be a string", pname); + return searchpath(L, name, path, ".", dirsep); +} + + +static int checkload (lua_State *L, int stat, const char *filename) { + if (stat) { /* module loaded successfully? */ + lua_pushstring(L, filename); /* will be 2nd argument to module */ + return 2; /* return open function and file name */ + } + else + return luaL_error(L, "error loading module '%s' from file '%s':\n\t%s", + lua_tostring(L, 1), filename, lua_tostring(L, -1)); } -static int loader_Lua (lua_State *L) { +static int searcher_Lua (lua_State *L) { const char *filename; const char *name = luaL_checkstring(L, 1); - filename = findfile(L, name, "path"); - if (filename == NULL) return 1; /* library not found in this path */ - if (luaL_loadfile(L, filename) != 0) - loaderror(L, filename); - return 1; /* library loaded successfully */ + filename = findfile(L, name, "path", LUA_LSUBSEP); + if (filename == NULL) return 1; /* module not found in this path */ + return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename); } -static const char *mkfuncname (lua_State *L, const char *modname) { - const char *funcname; - const char *mark = strchr(modname, *LUA_IGMARK); - if (mark) modname = mark + 1; - funcname = luaL_gsub(L, modname, ".", LUA_OFSEP); - funcname = lua_pushfstring(L, POF"%s", funcname); - lua_remove(L, -2); /* remove 'gsub' result */ - return funcname; +/* +** Try to find a load function for module 'modname' at file 'filename'. +** First, change '.' to '_' in 'modname'; then, if 'modname' has +** the form X-Y (that is, it has an "ignore mark"), build a function +** name "luaopen_X" and look for it. (For compatibility, if that +** fails, it also tries "luaopen_Y".) If there is no ignore mark, +** look for a function named "luaopen_modname". +*/ +static int loadfunc (lua_State *L, const char *filename, const char *modname) { + const char *openfunc; + const char *mark; + modname = luaL_gsub(L, modname, ".", LUA_OFSEP); + mark = strchr(modname, *LUA_IGMARK); + if (mark) { + int stat; + openfunc = lua_pushlstring(L, modname, mark - modname); + openfunc = lua_pushfstring(L, LUA_POF"%s", openfunc); + stat = lookforfunc(L, filename, openfunc); + if (stat != ERRFUNC) return stat; + modname = mark + 1; /* else go ahead and try old-style name */ + } + openfunc = lua_pushfstring(L, LUA_POF"%s", modname); + return lookforfunc(L, filename, openfunc); } -static int loader_C (lua_State *L) { - const char *funcname; +static int searcher_C (lua_State *L) { const char *name = luaL_checkstring(L, 1); - const char *filename = findfile(L, name, "cpath"); - if (filename == NULL) return 1; /* library not found in this path */ - funcname = mkfuncname(L, name); - if (ll_loadfunc(L, filename, funcname) != 0) - loaderror(L, filename); - return 1; /* library loaded successfully */ + const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP); + if (filename == NULL) return 1; /* module not found in this path */ + return checkload(L, (loadfunc(L, filename, name) == 0), filename); } -static int loader_Croot (lua_State *L) { - const char *funcname; +static int searcher_Croot (lua_State *L) { const char *filename; const char *name = luaL_checkstring(L, 1); const char *p = strchr(name, '.'); int stat; if (p == NULL) return 0; /* is root */ lua_pushlstring(L, name, p - name); - filename = findfile(L, lua_tostring(L, -1), "cpath"); + filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP); if (filename == NULL) return 1; /* root not found */ - funcname = mkfuncname(L, name); - if ((stat = ll_loadfunc(L, filename, funcname)) != 0) { - if (stat != ERRFUNC) loaderror(L, filename); /* real error */ - lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS, - name, filename); - return 1; /* function not found */ + if ((stat = loadfunc(L, filename, name)) != 0) { + if (stat != ERRFUNC) + return checkload(L, 0, filename); /* real error */ + else { /* open function not found */ + lua_pushfstring(L, "\n\tno module '%s' in file '%s'", name, filename); + return 1; + } } - return 1; + lua_pushstring(L, filename); /* will be 2nd argument to module */ + return 2; } -static int loader_preload (lua_State *L) { +static int searcher_preload (lua_State *L) { const char *name = luaL_checkstring(L, 1); - lua_getfield(L, LUA_ENVIRONINDEX, "preload"); - if (!lua_istable(L, -1)) - luaL_error(L, LUA_QL("package.preload") " must be a table"); - lua_getfield(L, -1, name); - if (lua_isnil(L, -1)) /* not found? */ + lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD"); + if (lua_getfield(L, -1, name) == LUA_TNIL) /* not found? */ lua_pushfstring(L, "\n\tno field package.preload['%s']", name); return 1; } -static const int sentinel_ = 0; -#define sentinel ((void *)&sentinel_) +static void findloader (lua_State *L, const char *name) { + int i; + luaL_Buffer msg; /* to build error message */ + luaL_buffinit(L, &msg); + /* push 'package.searchers' to index 3 in the stack */ + if (lua_getfield(L, lua_upvalueindex(1), "searchers") != LUA_TTABLE) + luaL_error(L, "'package.searchers' must be a table"); + /* iterate over available searchers to find a loader */ + for (i = 1; ; i++) { + if (lua_rawgeti(L, 3, i) == LUA_TNIL) { /* no more searchers? */ + lua_pop(L, 1); /* remove nil */ + luaL_pushresult(&msg); /* create error message */ + luaL_error(L, "module '%s' not found:%s", name, lua_tostring(L, -1)); + } + lua_pushstring(L, name); + lua_call(L, 1, 2); /* call it */ + if (lua_isfunction(L, -2)) /* did it find a loader? */ + return; /* module loader found */ + else if (lua_isstring(L, -2)) { /* searcher returned error message? */ + lua_pop(L, 1); /* remove extra return */ + luaL_addvalue(&msg); /* concatenate error message */ + } + else + lua_pop(L, 2); /* remove both returns */ + } +} static int ll_require (lua_State *L) { const char *name = luaL_checkstring(L, 1); - int i; lua_settop(L, 1); /* _LOADED table will be at index 2 */ lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); - lua_getfield(L, 2, name); - if (lua_toboolean(L, -1)) { /* is it there? */ - if (lua_touserdata(L, -1) == sentinel) /* check loops */ - luaL_error(L, "loop or previous error loading module " LUA_QS, name); + lua_getfield(L, 2, name); /* _LOADED[name] */ + if (lua_toboolean(L, -1)) /* is it there? */ return 1; /* package is already loaded */ - } - /* else must load it; iterate over available loaders */ - lua_getfield(L, LUA_ENVIRONINDEX, "loaders"); - if (!lua_istable(L, -1)) - luaL_error(L, LUA_QL("package.loaders") " must be a table"); - lua_pushliteral(L, ""); /* error message accumulator */ - for (i=1; ; i++) { - lua_rawgeti(L, -2, i); /* get a loader */ - if (lua_isnil(L, -1)) - luaL_error(L, "module " LUA_QS " not found:%s", - name, lua_tostring(L, -2)); - lua_pushstring(L, name); - lua_call(L, 1, 1); /* call it */ - if (lua_isfunction(L, -1)) /* did it find module? */ - break; /* module loaded successfully */ - else if (lua_isstring(L, -1)) /* loader returned error message? */ - lua_concat(L, 2); /* accumulate it */ - else - lua_pop(L, 1); - } - lua_pushlightuserdata(L, sentinel); - lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */ - lua_pushstring(L, name); /* pass name as argument to module */ - lua_call(L, 1, 1); /* run loaded module */ + /* else must load package */ + lua_pop(L, 1); /* remove 'getfield' result */ + findloader(L, name); + lua_pushstring(L, name); /* pass name as argument to module loader */ + lua_insert(L, -2); /* name is 1st argument (before search data) */ + lua_call(L, 2, 1); /* run loader to load module */ if (!lua_isnil(L, -1)) /* non-nil return? */ lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ - lua_getfield(L, 2, name); - if (lua_touserdata(L, -1) == sentinel) { /* module did not set a value? */ + if (lua_getfield(L, 2, name) == LUA_TNIL) { /* module set no value? */ lua_pushboolean(L, 1); /* use true as result */ lua_pushvalue(L, -1); /* extra copy to be returned */ lua_setfield(L, 2, name); /* _LOADED[name] = true */ @@ -502,26 +587,31 @@ static int ll_require (lua_State *L) { ** 'module' function ** ======================================================= */ - +#if defined(LUA_COMPAT_MODULE) -static void setfenv (lua_State *L) { +/* +** changes the environment variable of calling function +*/ +static void set_env (lua_State *L) { lua_Debug ar; if (lua_getstack(L, 1, &ar) == 0 || lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ lua_iscfunction(L, -1)) - luaL_error(L, LUA_QL("module") " not called from a Lua function"); - lua_pushvalue(L, -2); - lua_setfenv(L, -2); - lua_pop(L, 1); + luaL_error(L, "'module' not called from a Lua function"); + lua_pushvalue(L, -2); /* copy new environment table to top */ + lua_setupvalue(L, -2, 1); + lua_pop(L, 1); /* remove function */ } static void dooptions (lua_State *L, int n) { int i; for (i = 2; i <= n; i++) { - lua_pushvalue(L, i); /* get option (a function) */ - lua_pushvalue(L, -2); /* module */ - lua_call(L, 1, 0); + if (lua_isfunction(L, i)) { /* avoid 'calling' extra info. */ + lua_pushvalue(L, i); /* get option (a function) */ + lua_pushvalue(L, -2); /* module */ + lua_call(L, 1, 0); + } } } @@ -543,29 +633,19 @@ static void modinit (lua_State *L, const char *modname) { static int ll_module (lua_State *L) { const char *modname = luaL_checkstring(L, 1); - int loaded = lua_gettop(L) + 1; /* index of _LOADED table */ - lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); - lua_getfield(L, loaded, modname); /* get _LOADED[modname] */ - if (!lua_istable(L, -1)) { /* not found? */ - lua_pop(L, 1); /* remove previous result */ - /* try global variable (and create one if it does not exist) */ - if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL) - return luaL_error(L, "name conflict for module " LUA_QS, modname); - lua_pushvalue(L, -1); - lua_setfield(L, loaded, modname); /* _LOADED[modname] = new table */ - } + int lastarg = lua_gettop(L); /* last parameter */ + luaL_pushmodule(L, modname, 1); /* get/create module table */ /* check whether table already has a _NAME field */ - lua_getfield(L, -1, "_NAME"); - if (!lua_isnil(L, -1)) /* is table an initialized module? */ - lua_pop(L, 1); + if (lua_getfield(L, -1, "_NAME") != LUA_TNIL) + lua_pop(L, 1); /* table is an initialized module */ else { /* no; initialize it */ lua_pop(L, 1); modinit(L, modname); } lua_pushvalue(L, -1); - setfenv(L); - dooptions(L, loaded - 1); - return 0; + set_env(L); + dooptions(L, lastarg); + return 1; } @@ -576,12 +656,12 @@ static int ll_seeall (lua_State *L) { lua_pushvalue(L, -1); lua_setmetatable(L, 1); } - lua_pushvalue(L, LUA_GLOBALSINDEX); + lua_pushglobaltable(L); lua_setfield(L, -2, "__index"); /* mt.__index = _G */ return 0; } - +#endif /* }====================================================== */ @@ -589,15 +669,30 @@ static int ll_seeall (lua_State *L) { /* auxiliary mark (for internal use) */ #define AUXMARK "\1" -static void setpath (lua_State *L, const char *fieldname, const char *envname, - const char *def) { - const char *path = getenv(envname); + +/* +** return registry.LUA_NOENV as a boolean +*/ +static int noenv (lua_State *L) { + int b; + lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); + b = lua_toboolean(L, -1); + lua_pop(L, 1); /* remove value */ + return b; +} + + +static void setpath (lua_State *L, const char *fieldname, const char *envname1, + const char *envname2, const char *def) { + const char *path = getenv(envname1); if (path == NULL) /* no environment variable? */ + path = getenv(envname2); /* try alternative name */ + if (path == NULL || noenv(L)) /* no environment variable? */ lua_pushstring(L, def); /* use default */ else { /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ - path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP, - LUA_PATHSEP AUXMARK LUA_PATHSEP); + path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP, + LUA_PATH_SEP AUXMARK LUA_PATH_SEP); luaL_gsub(L, path, AUXMARK, def); lua_remove(L, -2); } @@ -608,59 +703,85 @@ static void setpath (lua_State *L, const char *fieldname, const char *envname, static const luaL_Reg pk_funcs[] = { {"loadlib", ll_loadlib}, + {"searchpath", ll_searchpath}, +#if defined(LUA_COMPAT_MODULE) {"seeall", ll_seeall}, +#endif + /* placeholders */ + {"preload", NULL}, + {"cpath", NULL}, + {"path", NULL}, + {"searchers", NULL}, + {"loaded", NULL}, {NULL, NULL} }; static const luaL_Reg ll_funcs[] = { +#if defined(LUA_COMPAT_MODULE) {"module", ll_module}, +#endif {"require", ll_require}, {NULL, NULL} }; -static const lua_CFunction loaders[] = - {loader_preload, loader_Lua, loader_C, loader_Croot, NULL}; - - -LUALIB_API int luaopen_package (lua_State *L) { +static void createsearcherstable (lua_State *L) { + static const lua_CFunction searchers[] = + {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL}; int i; - /* create new type _LOADLIB */ - luaL_newmetatable(L, "_LOADLIB"); - lua_pushcfunction(L, gctm); - lua_setfield(L, -2, "__gc"); - /* create `package' table */ - luaL_register(L, LUA_LOADLIBNAME, pk_funcs); -#if defined(LUA_COMPAT_LOADLIB) - lua_getfield(L, -1, "loadlib"); - lua_setfield(L, LUA_GLOBALSINDEX, "loadlib"); -#endif - lua_pushvalue(L, -1); - lua_replace(L, LUA_ENVIRONINDEX); - /* create `loaders' table */ - lua_createtable(L, sizeof(loaders)/sizeof(loaders[0]) - 1, 0); - /* fill it with pre-defined loaders */ - for (i=0; loaders[i] != NULL; i++) { - lua_pushcfunction(L, loaders[i]); + /* create 'searchers' table */ + lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0); + /* fill it with predefined searchers */ + for (i=0; searchers[i] != NULL; i++) { + lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */ + lua_pushcclosure(L, searchers[i], 1); lua_rawseti(L, -2, i+1); } - lua_setfield(L, -2, "loaders"); /* put it in field `loaders' */ - setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT); /* set field `path' */ - setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT); /* set field `cpath' */ +#if defined(LUA_COMPAT_LOADERS) + lua_pushvalue(L, -1); /* make a copy of 'searchers' table */ + lua_setfield(L, -3, "loaders"); /* put it in field 'loaders' */ +#endif + lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ +} + + +/* +** create table CLIBS to keep track of loaded C libraries, +** setting a finalizer to close all libraries when closing state. +*/ +static void createclibstable (lua_State *L) { + lua_newtable(L); /* create CLIBS table */ + lua_createtable(L, 0, 1); /* create metatable for CLIBS */ + lua_pushcfunction(L, gctm); + lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */ + lua_setmetatable(L, -2); + lua_rawsetp(L, LUA_REGISTRYINDEX, &CLIBS); /* set CLIBS table in registry */ +} + + +LUAMOD_API int luaopen_package (lua_State *L) { + createclibstable(L); + luaL_newlib(L, pk_funcs); /* create 'package' table */ + createsearcherstable(L); + /* set field 'path' */ + setpath(L, "path", LUA_PATHVARVERSION, LUA_PATH_VAR, LUA_PATH_DEFAULT); + /* set field 'cpath' */ + setpath(L, "cpath", LUA_CPATHVARVERSION, LUA_CPATH_VAR, LUA_CPATH_DEFAULT); /* store config information */ - lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" - LUA_EXECDIR "\n" LUA_IGMARK); + lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n" + LUA_EXEC_DIR "\n" LUA_IGMARK "\n"); lua_setfield(L, -2, "config"); - /* set field `loaded' */ - luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2); + /* set field 'loaded' */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); lua_setfield(L, -2, "loaded"); - /* set field `preload' */ - lua_newtable(L); + /* set field 'preload' */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD"); lua_setfield(L, -2, "preload"); - lua_pushvalue(L, LUA_GLOBALSINDEX); - luaL_register(L, NULL, ll_funcs); /* open lib into global table */ - lua_pop(L, 1); + lua_pushglobaltable(L); + lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */ + luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */ + lua_pop(L, 1); /* pop global table */ return 1; /* return 'package' table */ } diff --git a/app/src/main/jni/lua/lobject.c b/app/src/main/jni/lua/lobject.c index 4ff5073..a44b385 100644 --- a/app/src/main/jni/lua/lobject.c +++ b/app/src/main/jni/lua/lobject.c @@ -1,20 +1,26 @@ /* -** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lobject.c,v 2.111 2016/05/20 14:07:48 roberto Exp $ ** Some generic functions over Lua objects ** See Copyright Notice in lua.h */ -#include +#define lobject_c +#define LUA_CORE + +#include "lprefix.h" + + +#include +#include #include #include #include #include -#define lobject_c -#define LUA_CORE - #include "lua.h" +#include "lctype.h" +#include "ldebug.h" #include "ldo.h" #include "lmem.h" #include "lobject.h" @@ -24,7 +30,7 @@ -const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; +LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT}; /* @@ -33,26 +39,31 @@ const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; ** eeeee != 0 and (xxx) otherwise. */ int luaO_int2fb (unsigned int x) { - int e = 0; /* expoent */ - while (x >= 16) { - x = (x+1) >> 1; + int e = 0; /* exponent */ + if (x < 8) return x; + while (x >= (8 << 4)) { /* coarse steps */ + x = (x + 0xf) >> 4; /* x = ceil(x / 16) */ + e += 4; + } + while (x >= (8 << 1)) { /* fine steps */ + x = (x + 1) >> 1; /* x = ceil(x / 2) */ e++; } - if (x < 8) return x; - else return ((e+1) << 3) | (cast_int(x) - 8); + return ((e+1) << 3) | (cast_int(x) - 8); } /* converts back */ int luaO_fb2int (int x) { - int e = (x >> 3) & 31; - if (e == 0) return x; - else return ((x & 7)+8) << (e - 1); + return (x < 8) ? x : ((x & 7) + 8) << ((x >> 3) - 1); } -int luaO_log2 (unsigned int x) { - static const lu_byte log_2[256] = { +/* +** Computes ceil(log2(x)) +*/ +int luaO_ceillog2 (unsigned int x) { + static const lu_byte log_2[256] = { /* log_2[i] = ceil(log2(i - 1)) */ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, @@ -62,109 +73,393 @@ int luaO_log2 (unsigned int x) { 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 }; - int l = -1; + int l = 0; + x--; while (x >= 256) { l += 8; x >>= 8; } return l + log_2[x]; +} + + +static lua_Integer intarith (lua_State *L, int op, lua_Integer v1, + lua_Integer v2) { + switch (op) { + case LUA_OPADD: return intop(+, v1, v2); + case LUA_OPSUB:return intop(-, v1, v2); + case LUA_OPMUL:return intop(*, v1, v2); + case LUA_OPMOD: return luaV_mod(L, v1, v2); + case LUA_OPIDIV: return luaV_div(L, v1, v2); + case LUA_OPBAND: return intop(&, v1, v2); + case LUA_OPBOR: return intop(|, v1, v2); + case LUA_OPBXOR: return intop(^, v1, v2); + case LUA_OPSHL: return luaV_shiftl(v1, v2); + case LUA_OPSHR: return luaV_shiftl(v1, -v2); + case LUA_OPUNM: return intop(-, 0, v1); + case LUA_OPBNOT: return intop(^, ~l_castS2U(0), v1); + default: lua_assert(0); return 0; + } +} + +static lua_Number numarith (lua_State *L, int op, lua_Number v1, + lua_Number v2) { + switch (op) { + case LUA_OPADD: return luai_numadd(L, v1, v2); + case LUA_OPSUB: return luai_numsub(L, v1, v2); + case LUA_OPMUL: return luai_nummul(L, v1, v2); + case LUA_OPDIV: return luai_numdiv(L, v1, v2); + case LUA_OPPOW: return luai_numpow(L, v1, v2); + case LUA_OPIDIV: return luai_numidiv(L, v1, v2); + case LUA_OPUNM: return luai_numunm(L, v1); + case LUA_OPMOD: { + lua_Number m; + luai_nummod(L, v1, v2, m); + return m; + } + default: lua_assert(0); return 0; + } } -int luaO_rawequalObj (const TValue *t1, const TValue *t2) { - if (ttype(t1) != ttype(t2)) return 0; - else switch (ttype(t1)) { - case LUA_TNIL: - return 1; - case LUA_TNUMBER: - return luai_numeq(nvalue(t1), nvalue(t2)); - case LUA_TBOOLEAN: - return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ - case LUA_TLIGHTUSERDATA: - return pvalue(t1) == pvalue(t2); - default: - lua_assert(iscollectable(t1)); - return gcvalue(t1) == gcvalue(t2); +void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2, + TValue *res) { + switch (op) { + case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: + case LUA_OPSHL: case LUA_OPSHR: + case LUA_OPBNOT: { /* operate only on integers */ + lua_Integer i1; lua_Integer i2; + if (tointeger(p1, &i1) && tointeger(p2, &i2)) { + setivalue(res, intarith(L, op, i1, i2)); + return; + } + else break; /* go to the end */ + } + case LUA_OPDIV: case LUA_OPPOW: { /* operate only on floats */ + lua_Number n1; lua_Number n2; + if (tonumber(p1, &n1) && tonumber(p2, &n2)) { + setfltvalue(res, numarith(L, op, n1, n2)); + return; + } + else break; /* go to the end */ + } + default: { /* other operations */ + lua_Number n1; lua_Number n2; + if (ttisinteger(p1) && ttisinteger(p2)) { + setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2))); + return; + } + else if (tonumber(p1, &n1) && tonumber(p2, &n2)) { + setfltvalue(res, numarith(L, op, n1, n2)); + return; + } + else break; /* go to the end */ + } + } + /* could not perform raw operation; try metamethod */ + lua_assert(L != NULL); /* should not fail when folding (compile time) */ + luaT_trybinTM(L, p1, p2, res, cast(TMS, (op - LUA_OPADD) + TM_ADD)); +} + + +int luaO_hexavalue (int c) { + if (lisdigit(c)) return c - '0'; + else return (ltolower(c) - 'a') + 10; +} + + +static int isneg (const char **s) { + if (**s == '-') { (*s)++; return 1; } + else if (**s == '+') (*s)++; + return 0; +} + + + +/* +** {================================================================== +** Lua's implementation for 'lua_strx2number' +** =================================================================== +*/ + +#if !defined(lua_strx2number) + +/* maximum number of significant digits to read (to avoid overflows + even with single floats) */ +#define MAXSIGDIG 30 + +/* +** convert an hexadecimal numeric string to a number, following +** C99 specification for 'strtod' +*/ +static lua_Number lua_strx2number (const char *s, char **endptr) { + int dot = lua_getlocaledecpoint(); + lua_Number r = 0.0; /* result (accumulator) */ + int sigdig = 0; /* number of significant digits */ + int nosigdig = 0; /* number of non-significant digits */ + int e = 0; /* exponent correction */ + int neg; /* 1 if number is negative */ + int hasdot = 0; /* true after seen a dot */ + *endptr = cast(char *, s); /* nothing is valid yet */ + while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ + neg = isneg(&s); /* check signal */ + if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ + return 0.0; /* invalid format (no '0x') */ + for (s += 2; ; s++) { /* skip '0x' and read numeral */ + if (*s == dot) { + if (hasdot) break; /* second dot? stop loop */ + else hasdot = 1; + } + else if (lisxdigit(cast_uchar(*s))) { + if (sigdig == 0 && *s == '0') /* non-significant digit (zero)? */ + nosigdig++; + else if (++sigdig <= MAXSIGDIG) /* can read it without overflow? */ + r = (r * cast_num(16.0)) + luaO_hexavalue(*s); + else e++; /* too many digits; ignore, but still count for exponent */ + if (hasdot) e--; /* decimal digit? correct exponent */ + } + else break; /* neither a dot nor a digit */ + } + if (nosigdig + sigdig == 0) /* no digits? */ + return 0.0; /* invalid format */ + *endptr = cast(char *, s); /* valid up to here */ + e *= 4; /* each digit multiplies/divides value by 2^4 */ + if (*s == 'p' || *s == 'P') { /* exponent part? */ + int exp1 = 0; /* exponent value */ + int neg1; /* exponent signal */ + s++; /* skip 'p' */ + neg1 = isneg(&s); /* signal */ + if (!lisdigit(cast_uchar(*s))) + return 0.0; /* invalid; must have at least one digit */ + while (lisdigit(cast_uchar(*s))) /* read exponent */ + exp1 = exp1 * 10 + *(s++) - '0'; + if (neg1) exp1 = -exp1; + e += exp1; + *endptr = cast(char *, s); /* valid up to here */ } + if (neg) r = -r; + return l_mathop(ldexp)(r, e); } +#endif +/* }====================================================== */ -int luaO_str2d (const char *s, lua_Number *result) { + +/* maximum length of a numeral */ +#if !defined (L_MAXLENNUM) +#define L_MAXLENNUM 200 +#endif + +static const char *l_str2dloc (const char *s, lua_Number *result, int mode) { char *endptr; - *result = lua_str2number(s, &endptr); - if (endptr == s) return 0; /* conversion failed */ - if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */ - *result = cast_num(strtoul(s, &endptr, 16)); - if (*endptr == '\0') return 1; /* most common case */ - while (isspace(cast(unsigned char, *endptr))) endptr++; - if (*endptr != '\0') return 0; /* invalid trailing characters? */ - return 1; + *result = (mode == 'x') ? lua_strx2number(s, &endptr) /* try to convert */ + : lua_str2number(s, &endptr); + if (endptr == s) return NULL; /* nothing recognized? */ + while (lisspace(cast_uchar(*endptr))) endptr++; /* skip trailing spaces */ + return (*endptr == '\0') ? endptr : NULL; /* OK if no trailing characters */ } +/* +** Convert string 's' to a Lua number (put in 'result'). Return NULL +** on fail or the address of the ending '\0' on success. +** 'pmode' points to (and 'mode' contains) special things in the string: +** - 'x'/'X' means an hexadecimal numeral +** - 'n'/'N' means 'inf' or 'nan' (which should be rejected) +** - '.' just optimizes the search for the common case (nothing special) +** This function accepts both the current locale or a dot as the radix +** mark. If the convertion fails, it may mean number has a dot but +** locale accepts something else. In that case, the code copies 's' +** to a buffer (because 's' is read-only), changes the dot to the +** current locale radix mark, and tries to convert again. +*/ +static const char *l_str2d (const char *s, lua_Number *result) { + const char *endptr; + const char *pmode = strpbrk(s, ".xXnN"); + int mode = pmode ? ltolower(cast_uchar(*pmode)) : 0; + if (mode == 'n') /* reject 'inf' and 'nan' */ + return NULL; + endptr = l_str2dloc(s, result, mode); /* try to convert */ + if (endptr == NULL) { /* failed? may be a different locale */ + char buff[L_MAXLENNUM + 1]; + char *pdot = strchr(s, '.'); + if (strlen(s) > L_MAXLENNUM || pdot == NULL) + return NULL; /* string too long or no dot; fail */ + strcpy(buff, s); /* copy string to buffer */ + buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */ + endptr = l_str2dloc(buff, result, mode); /* try again */ + if (endptr != NULL) + endptr = s + (endptr - buff); /* make relative to 's' */ + } + return endptr; +} + -static void pushstr (lua_State *L, const char *str) { - setsvalue2s(L, L->top, luaS_new(L, str)); - incr_top(L); +#define MAXBY10 cast(lua_Unsigned, LUA_MAXINTEGER / 10) +#define MAXLASTD cast_int(LUA_MAXINTEGER % 10) + +static const char *l_str2int (const char *s, lua_Integer *result) { + lua_Unsigned a = 0; + int empty = 1; + int neg; + while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ + neg = isneg(&s); + if (s[0] == '0' && + (s[1] == 'x' || s[1] == 'X')) { /* hex? */ + s += 2; /* skip '0x' */ + for (; lisxdigit(cast_uchar(*s)); s++) { + a = a * 16 + luaO_hexavalue(*s); + empty = 0; + } + } + else { /* decimal */ + for (; lisdigit(cast_uchar(*s)); s++) { + int d = *s - '0'; + if (a >= MAXBY10 && (a > MAXBY10 || d > MAXLASTD + neg)) /* overflow? */ + return NULL; /* do not accept it (as integer) */ + a = a * 10 + d; + empty = 0; + } + } + while (lisspace(cast_uchar(*s))) s++; /* skip trailing spaces */ + if (empty || *s != '\0') return NULL; /* something wrong in the numeral */ + else { + *result = l_castU2S((neg) ? 0u - a : a); + return s; + } } -/* this function handles only `%d', `%c', %f, %p, and `%s' formats */ +size_t luaO_str2num (const char *s, TValue *o) { + lua_Integer i; lua_Number n; + const char *e; + if ((e = l_str2int(s, &i)) != NULL) { /* try as an integer */ + setivalue(o, i); + } + else if ((e = l_str2d(s, &n)) != NULL) { /* else try as a float */ + setfltvalue(o, n); + } + else + return 0; /* conversion failed */ + return (e - s) + 1; /* success; return string size */ +} + + +int luaO_utf8esc (char *buff, unsigned long x) { + int n = 1; /* number of bytes put in buffer (backwards) */ + lua_assert(x <= 0x10FFFF); + if (x < 0x80) /* ascii? */ + buff[UTF8BUFFSZ - 1] = cast(char, x); + else { /* need continuation bytes */ + unsigned int mfb = 0x3f; /* maximum that fits in first byte */ + do { /* add continuation bytes */ + buff[UTF8BUFFSZ - (n++)] = cast(char, 0x80 | (x & 0x3f)); + x >>= 6; /* remove added bits */ + mfb >>= 1; /* now there is one less bit available in first byte */ + } while (x > mfb); /* still needs continuation byte? */ + buff[UTF8BUFFSZ - n] = cast(char, (~mfb << 1) | x); /* add first byte */ + } + return n; +} + + +/* maximum length of the conversion of a number to a string */ +#define MAXNUMBER2STR 50 + + +/* +** Convert a number object to a string +*/ +void luaO_tostring (lua_State *L, StkId obj) { + char buff[MAXNUMBER2STR]; + size_t len; + lua_assert(ttisnumber(obj)); + if (ttisinteger(obj)) + len = lua_integer2str(buff, sizeof(buff), ivalue(obj)); + else { + len = lua_number2str(buff, sizeof(buff), fltvalue(obj)); +#if !defined(LUA_COMPAT_FLOATSTRING) + if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */ + buff[len++] = lua_getlocaledecpoint(); + buff[len++] = '0'; /* adds '.0' to result */ + } +#endif + } + setsvalue2s(L, obj, luaS_newlstr(L, buff, len)); +} + + +static void pushstr (lua_State *L, const char *str, size_t l) { + setsvalue2s(L, L->top, luaS_newlstr(L, str, l)); + luaD_inctop(L); +} + + +/* +** this function handles only '%d', '%c', '%f', '%p', and '%s' + conventional formats, plus Lua-specific '%I' and '%U' +*/ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { - int n = 1; - pushstr(L, ""); + int n = 0; for (;;) { const char *e = strchr(fmt, '%'); if (e == NULL) break; - setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt)); - incr_top(L); + pushstr(L, fmt, e - fmt); switch (*(e+1)) { - case 's': { + case 's': { /* zero-terminated string */ const char *s = va_arg(argp, char *); if (s == NULL) s = "(null)"; - pushstr(L, s); + pushstr(L, s, strlen(s)); break; } - case 'c': { - char buff[2]; - buff[0] = cast(char, va_arg(argp, int)); - buff[1] = '\0'; - pushstr(L, buff); + case 'c': { /* an 'int' as a character */ + char buff = cast(char, va_arg(argp, int)); + if (lisprint(cast_uchar(buff))) + pushstr(L, &buff, 1); + else /* non-printable character; print its code */ + luaO_pushfstring(L, "<\\%d>", cast_uchar(buff)); break; } - case 'd': { - setnvalue(L->top, cast_num(va_arg(argp, int))); - incr_top(L); + case 'd': { /* an 'int' */ + setivalue(L->top, va_arg(argp, int)); + goto top2str; + } + case 'I': { /* a 'lua_Integer' */ + setivalue(L->top, cast(lua_Integer, va_arg(argp, l_uacInt))); + goto top2str; + } + case 'f': { /* a 'lua_Number' */ + setfltvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); + top2str: /* convert the top element to a string */ + luaD_inctop(L); + luaO_tostring(L, L->top - 1); break; } - case 'f': { - setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); - incr_top(L); + case 'p': { /* a pointer */ + char buff[4*sizeof(void *) + 8]; /* should be enough space for a '%p' */ + int l = l_sprintf(buff, sizeof(buff), "%p", va_arg(argp, void *)); + pushstr(L, buff, l); break; } - case 'p': { - char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ - sprintf(buff, "%p", va_arg(argp, void *)); - pushstr(L, buff); + case 'U': { /* an 'int' as a UTF-8 sequence */ + char buff[UTF8BUFFSZ]; + int l = luaO_utf8esc(buff, cast(long, va_arg(argp, long))); + pushstr(L, buff + UTF8BUFFSZ - l, l); break; } case '%': { - pushstr(L, "%"); + pushstr(L, "%", 1); break; } default: { - char buff[3]; - buff[0] = '%'; - buff[1] = *(e+1); - buff[2] = '\0'; - pushstr(L, buff); - break; + luaG_runerror(L, "invalid option '%%%c' to 'lua_pushfstring'", + *(e + 1)); } } n += 2; fmt = e+2; } - pushstr(L, fmt); - luaV_concat(L, n+1, cast_int(L->top - L->base) - 1); - L->top -= n; + luaD_checkstack(L, 1); + pushstr(L, fmt, strlen(fmt)); + if (n > 0) luaV_concat(L, n + 1); return svalue(L->top - 1); } @@ -179,36 +474,48 @@ const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { } +/* number of chars of a literal string without the ending \0 */ +#define LL(x) (sizeof(x)/sizeof(char) - 1) + +#define RETS "..." +#define PRE "[string \"" +#define POS "\"]" + +#define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) ) + void luaO_chunkid (char *out, const char *source, size_t bufflen) { - if (*source == '=') { - strncpy(out, source+1, bufflen); /* remove first char */ - out[bufflen-1] = '\0'; /* ensures null termination */ - } - else { /* out = "source", or "...source" */ - if (*source == '@') { - size_t l; - source++; /* skip the `@' */ - bufflen -= sizeof(" '...' "); - l = strlen(source); - strcpy(out, ""); - if (l > bufflen) { - source += (l-bufflen); /* get last part of file name */ - strcat(out, "..."); - } - strcat(out, source); + size_t l = strlen(source); + if (*source == '=') { /* 'literal' source */ + if (l <= bufflen) /* small enough? */ + memcpy(out, source + 1, l * sizeof(char)); + else { /* truncate it */ + addstr(out, source + 1, bufflen - 1); + *out = '\0'; } - else { /* out = [string "string"] */ - size_t len = strcspn(source, "\n\r"); /* stop at first newline */ - bufflen -= sizeof(" [string \"...\"] "); - if (len > bufflen) len = bufflen; - strcpy(out, "[string \""); - if (source[len] != '\0') { /* must truncate? */ - strncat(out, source, len); - strcat(out, "..."); - } - else - strcat(out, source); - strcat(out, "\"]"); + } + else if (*source == '@') { /* file name */ + if (l <= bufflen) /* small enough? */ + memcpy(out, source + 1, l * sizeof(char)); + else { /* add '...' before rest of name */ + addstr(out, RETS, LL(RETS)); + bufflen -= LL(RETS); + memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char)); + } + } + else { /* string; format as [string "source"] */ + const char *nl = strchr(source, '\n'); /* find first new line (if any) */ + addstr(out, PRE, LL(PRE)); /* add prefix */ + bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */ + if (l < bufflen && nl == NULL) { /* small one-line source? */ + addstr(out, source, l); /* keep it */ + } + else { + if (nl != NULL) l = nl - source; /* stop at first newline */ + if (l > bufflen) l = bufflen; + addstr(out, source, l); + addstr(out, RETS, LL(RETS)); } + memcpy(out, POS, (LL(POS) + 1) * sizeof(char)); } } + diff --git a/app/src/main/jni/lua/lobject.h b/app/src/main/jni/lua/lobject.h index f1e447e..2d52b41 100644 --- a/app/src/main/jni/lua/lobject.h +++ b/app/src/main/jni/lua/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 2.20.1.2 2008/08/06 13:29:48 roberto Exp $ +** $Id: lobject.h,v 2.116 2015/11/03 18:33:10 roberto Exp $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -16,24 +16,60 @@ #include "lua.h" -/* tags for values visible from Lua */ -#define LAST_TAG LUA_TTHREAD +/* +** Extra tags for non-values +*/ +#define LUA_TPROTO LUA_NUMTAGS /* function prototypes */ +#define LUA_TDEADKEY (LUA_NUMTAGS+1) /* removed keys in tables */ -#define NUM_TAGS (LAST_TAG+1) +/* +** number of all possible tags (including LUA_TNONE but excluding DEADKEY) +*/ +#define LUA_TOTALTAGS (LUA_TPROTO + 2) /* -** Extra tags for non-values +** tags for Tagged Values have the following use of bits: +** bits 0-3: actual tag (a LUA_T* value) +** bits 4-5: variant bits +** bit 6: whether value is collectable */ -#define LUA_TPROTO (LAST_TAG+1) -#define LUA_TUPVAL (LAST_TAG+2) -#define LUA_TDEADKEY (LAST_TAG+3) /* -** Union of all collectable objects +** LUA_TFUNCTION variants: +** 0 - Lua function +** 1 - light C function +** 2 - regular C function (closure) +*/ + +/* Variant tags for functions */ +#define LUA_TLCL (LUA_TFUNCTION | (0 << 4)) /* Lua closure */ +#define LUA_TLCF (LUA_TFUNCTION | (1 << 4)) /* light C function */ +#define LUA_TCCL (LUA_TFUNCTION | (2 << 4)) /* C closure */ + + +/* Variant tags for strings */ +#define LUA_TSHRSTR (LUA_TSTRING | (0 << 4)) /* short strings */ +#define LUA_TLNGSTR (LUA_TSTRING | (1 << 4)) /* long strings */ + + +/* Variant tags for numbers */ +#define LUA_TNUMFLT (LUA_TNUMBER | (0 << 4)) /* float numbers */ +#define LUA_TNUMINT (LUA_TNUMBER | (1 << 4)) /* integer numbers */ + + +/* Bit mark for collectable types */ +#define BIT_ISCOLLECTABLE (1 << 6) + +/* mark a tag as collectable */ +#define ctb(t) ((t) | BIT_ISCOLLECTABLE) + + +/* +** Common type for all collectable objects */ -typedef union GCObject GCObject; +typedef struct GCObject GCObject; /* @@ -44,128 +80,189 @@ typedef union GCObject GCObject; /* -** Common header in struct form +** Common type has only the common header */ -typedef struct GCheader { +struct GCObject { CommonHeader; -} GCheader; +}; + +/* +** Tagged Values. This is the basic representation of values in Lua, +** an actual value plus a tag with its type. +*/ /* ** Union of all Lua values */ -typedef union { - GCObject *gc; - void *p; - lua_Number n; - int b; +typedef union Value { + GCObject *gc; /* collectable objects */ + void *p; /* light userdata */ + int b; /* booleans */ + lua_CFunction f; /* light C functions */ + lua_Integer i; /* integer numbers */ + lua_Number n; /* float numbers */ } Value; -/* -** Tagged Values -*/ +#define TValuefields Value value_; int tt_ -#define TValuefields Value value; int tt typedef struct lua_TValue { TValuefields; } TValue; + +/* macro defining a nil value */ +#define NILCONSTANT {NULL}, LUA_TNIL + + +#define val_(o) ((o)->value_) + + +/* raw type tag of a TValue */ +#define rttype(o) ((o)->tt_) + +/* tag with no variants (bits 0-3) */ +#define novariant(x) ((x) & 0x0F) + +/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */ +#define ttype(o) (rttype(o) & 0x3F) + +/* type tag of a TValue with no variants (bits 0-3) */ +#define ttnov(o) (novariant(rttype(o))) + + /* Macros to test type */ -#define ttisnil(o) (ttype(o) == LUA_TNIL) -#define ttisnumber(o) (ttype(o) == LUA_TNUMBER) -#define ttisstring(o) (ttype(o) == LUA_TSTRING) -#define ttistable(o) (ttype(o) == LUA_TTABLE) -#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) -#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN) -#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA) -#define ttisthread(o) (ttype(o) == LUA_TTHREAD) -#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) +#define checktag(o,t) (rttype(o) == (t)) +#define checktype(o,t) (ttnov(o) == (t)) +#define ttisnumber(o) checktype((o), LUA_TNUMBER) +#define ttisfloat(o) checktag((o), LUA_TNUMFLT) +#define ttisinteger(o) checktag((o), LUA_TNUMINT) +#define ttisnil(o) checktag((o), LUA_TNIL) +#define ttisboolean(o) checktag((o), LUA_TBOOLEAN) +#define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA) +#define ttisstring(o) checktype((o), LUA_TSTRING) +#define ttisshrstring(o) checktag((o), ctb(LUA_TSHRSTR)) +#define ttislngstring(o) checktag((o), ctb(LUA_TLNGSTR)) +#define ttistable(o) checktag((o), ctb(LUA_TTABLE)) +#define ttisfunction(o) checktype(o, LUA_TFUNCTION) +#define ttisclosure(o) ((rttype(o) & 0x1F) == LUA_TFUNCTION) +#define ttisCclosure(o) checktag((o), ctb(LUA_TCCL)) +#define ttisLclosure(o) checktag((o), ctb(LUA_TLCL)) +#define ttislcf(o) checktag((o), LUA_TLCF) +#define ttisfulluserdata(o) checktag((o), ctb(LUA_TUSERDATA)) +#define ttisthread(o) checktag((o), ctb(LUA_TTHREAD)) +#define ttisdeadkey(o) checktag((o), LUA_TDEADKEY) + /* Macros to access values */ -#define ttype(o) ((o)->tt) -#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) -#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) -#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) -#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) -#define tsvalue(o) (&rawtsvalue(o)->tsv) -#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) -#define uvalue(o) (&rawuvalue(o)->uv) -#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl) -#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h) -#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b) -#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th) +#define ivalue(o) check_exp(ttisinteger(o), val_(o).i) +#define fltvalue(o) check_exp(ttisfloat(o), val_(o).n) +#define nvalue(o) check_exp(ttisnumber(o), \ + (ttisinteger(o) ? cast_num(ivalue(o)) : fltvalue(o))) +#define gcvalue(o) check_exp(iscollectable(o), val_(o).gc) +#define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p) +#define tsvalue(o) check_exp(ttisstring(o), gco2ts(val_(o).gc)) +#define uvalue(o) check_exp(ttisfulluserdata(o), gco2u(val_(o).gc)) +#define clvalue(o) check_exp(ttisclosure(o), gco2cl(val_(o).gc)) +#define clLvalue(o) check_exp(ttisLclosure(o), gco2lcl(val_(o).gc)) +#define clCvalue(o) check_exp(ttisCclosure(o), gco2ccl(val_(o).gc)) +#define fvalue(o) check_exp(ttislcf(o), val_(o).f) +#define hvalue(o) check_exp(ttistable(o), gco2t(val_(o).gc)) +#define bvalue(o) check_exp(ttisboolean(o), val_(o).b) +#define thvalue(o) check_exp(ttisthread(o), gco2th(val_(o).gc)) +/* a dead value may get the 'gc' field, but cannot access its contents */ +#define deadvalue(o) check_exp(ttisdeadkey(o), cast(void *, val_(o).gc)) #define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) -/* -** for internal debug only -*/ -#define checkconsistency(obj) \ - lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt)) -#define checkliveness(g,obj) \ - lua_assert(!iscollectable(obj) || \ - ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc))) +#define iscollectable(o) (rttype(o) & BIT_ISCOLLECTABLE) + + +/* Macros for internal tests */ +#define righttt(obj) (ttype(obj) == gcvalue(obj)->tt) + +#define checkliveness(L,obj) \ + lua_longassert(!iscollectable(obj) || \ + (righttt(obj) && (L == NULL || !isdead(G(L),gcvalue(obj))))) /* Macros to set values */ -#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) +#define settt_(o,t) ((o)->tt_=(t)) + +#define setfltvalue(obj,x) \ + { TValue *io=(obj); val_(io).n=(x); settt_(io, LUA_TNUMFLT); } + +#define chgfltvalue(obj,x) \ + { TValue *io=(obj); lua_assert(ttisfloat(io)); val_(io).n=(x); } + +#define setivalue(obj,x) \ + { TValue *io=(obj); val_(io).i=(x); settt_(io, LUA_TNUMINT); } -#define setnvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; } +#define chgivalue(obj,x) \ + { TValue *io=(obj); lua_assert(ttisinteger(io)); val_(io).i=(x); } + +#define setnilvalue(obj) settt_(obj, LUA_TNIL) + +#define setfvalue(obj,x) \ + { TValue *io=(obj); val_(io).f=(x); settt_(io, LUA_TLCF); } #define setpvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } + { TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_TLIGHTUSERDATA); } #define setbvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } + { TValue *io=(obj); val_(io).b=(x); settt_(io, LUA_TBOOLEAN); } + +#define setgcovalue(L,obj,x) \ + { TValue *io = (obj); GCObject *i_g=(x); \ + val_(io).gc = i_g; settt_(io, ctb(i_g->tt)); } #define setsvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \ - checkliveness(G(L),i_o); } + { TValue *io = (obj); TString *x_ = (x); \ + val_(io).gc = obj2gco(x_); settt_(io, ctb(x_->tt)); \ + checkliveness(L,io); } #define setuvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \ - checkliveness(G(L),i_o); } + { TValue *io = (obj); Udata *x_ = (x); \ + val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TUSERDATA)); \ + checkliveness(L,io); } #define setthvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \ - checkliveness(G(L),i_o); } + { TValue *io = (obj); lua_State *x_ = (x); \ + val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTHREAD)); \ + checkliveness(L,io); } -#define setclvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \ - checkliveness(G(L),i_o); } +#define setclLvalue(L,obj,x) \ + { TValue *io = (obj); LClosure *x_ = (x); \ + val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TLCL)); \ + checkliveness(L,io); } -#define sethvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \ - checkliveness(G(L),i_o); } +#define setclCvalue(L,obj,x) \ + { TValue *io = (obj); CClosure *x_ = (x); \ + val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TCCL)); \ + checkliveness(L,io); } -#define setptvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ - checkliveness(G(L),i_o); } +#define sethvalue(L,obj,x) \ + { TValue *io = (obj); Table *x_ = (x); \ + val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTABLE)); \ + checkliveness(L,io); } +#define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY) #define setobj(L,obj1,obj2) \ - { const TValue *o2=(obj2); TValue *o1=(obj1); \ - o1->value = o2->value; o1->tt=o2->tt; \ - checkliveness(G(L),o1); } + { TValue *io1=(obj1); *io1 = *(obj2); \ + (void)L; checkliveness(L,io1); } /* -** different types of sets, according to destination +** different types of assignments, according to destination */ /* from stack to (same) stack */ @@ -177,88 +274,126 @@ typedef struct lua_TValue { #define setptvalue2s setptvalue /* from table to same table */ #define setobjt2t setobj -/* to table */ -#define setobj2t setobj /* to new object */ #define setobj2n setobj #define setsvalue2n setsvalue -#define setttype(obj, tt) (ttype(obj) = (tt)) +/* to table (define it as an expression to be used in macros) */ +#define setobj2t(L,o1,o2) ((void)L, *(o1)=*(o2), checkliveness(L,(o1))) -#define iscollectable(o) (ttype(o) >= LUA_TSTRING) +/* +** {====================================================== +** types and prototypes +** ======================================================= +*/ + typedef TValue *StkId; /* index to stack elements */ + + /* -** String headers for string table +** Header for string value; string bytes follow the end of this structure +** (aligned according to 'UTString'; see next). */ -typedef union TString { - L_Umaxalign dummy; /* ensures maximum alignment for strings */ - struct { - CommonHeader; - lu_byte reserved; - unsigned int hash; - size_t len; - } tsv; +typedef struct TString { + CommonHeader; + lu_byte extra; /* reserved words for short strings; "has hash" for longs */ + lu_byte shrlen; /* length for short strings */ + unsigned int hash; + union { + size_t lnglen; /* length for long strings */ + struct TString *hnext; /* linked list for hash table */ + } u; } TString; -#define getstr(ts) cast(const char *, (ts) + 1) -#define svalue(o) getstr(rawtsvalue(o)) +/* +** Ensures that address after this type is always fully aligned. +*/ +typedef union UTString { + L_Umaxalign dummy; /* ensures maximum alignment for strings */ + TString tsv; +} UTString; +/* +** Get the actual string (array of bytes) from a 'TString'. +** (Access to 'extra' ensures that value is really a 'TString'.) +*/ +#define getstr(ts) \ + check_exp(sizeof((ts)->extra), cast(char *, (ts)) + sizeof(UTString)) -typedef union Udata { - L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ - struct { - CommonHeader; - struct Table *metatable; - struct Table *env; - size_t len; - } uv; -} Udata; +/* get the actual string (array of bytes) from a Lua value */ +#define svalue(o) getstr(tsvalue(o)) + +/* get string length from 'TString *s' */ +#define tsslen(s) ((s)->tt == LUA_TSHRSTR ? (s)->shrlen : (s)->u.lnglen) +/* get string length from 'TValue *o' */ +#define vslen(o) tsslen(tsvalue(o)) /* -** Function Prototypes +** Header for userdata; memory area follows the end of this structure +** (aligned according to 'UUdata'; see next). */ -typedef struct Proto { +typedef struct Udata { CommonHeader; - TValue *k; /* constants used by the function */ - Instruction *code; - struct Proto **p; /* functions defined inside the function */ - int *lineinfo; /* map from opcodes to source lines */ - struct LocVar *locvars; /* information about local variables */ - TString **upvalues; /* upvalue names */ - TString *source; - int sizeupvalues; - int sizek; /* size of `k' */ - int sizecode; - int sizelineinfo; - int sizep; /* size of `p' */ - int sizelocvars; - int linedefined; - int lastlinedefined; - GCObject *gclist; - lu_byte nups; /* number of upvalues */ - lu_byte numparams; - lu_byte is_vararg; - lu_byte maxstacksize; -} Proto; + lu_byte ttuv_; /* user value's tag */ + struct Table *metatable; + size_t len; /* number of bytes */ + union Value user_; /* user value */ +} Udata; + + +/* +** Ensures that address after this type is always fully aligned. +*/ +typedef union UUdata { + L_Umaxalign dummy; /* ensures maximum alignment for 'local' udata */ + Udata uv; +} UUdata; + + +/* +** Get the address of memory block inside 'Udata'. +** (Access to 'ttuv_' ensures that value is really a 'Udata'.) +*/ +#define getudatamem(u) \ + check_exp(sizeof((u)->ttuv_), (cast(char*, (u)) + sizeof(UUdata))) + +#define setuservalue(L,u,o) \ + { const TValue *io=(o); Udata *iu = (u); \ + iu->user_ = io->value_; iu->ttuv_ = rttype(io); \ + checkliveness(L,io); } -/* masks for new-style vararg */ -#define VARARG_HASARG 1 -#define VARARG_ISVARARG 2 -#define VARARG_NEEDSARG 4 +#define getuservalue(L,u,o) \ + { TValue *io=(o); const Udata *iu = (u); \ + io->value_ = iu->user_; settt_(io, iu->ttuv_); \ + checkliveness(L,io); } + + +/* +** Description of an upvalue for function prototypes +*/ +typedef struct Upvaldesc { + TString *name; /* upvalue name (for debug information) */ + lu_byte instack; /* whether it is in stack (register) */ + lu_byte idx; /* index of upvalue (in stack or in outer function's list) */ +} Upvaldesc; +/* +** Description of a local variable for function prototypes +** (used for debug information) +*/ typedef struct LocVar { TString *varname; int startpc; /* first point where variable is active */ @@ -266,22 +401,39 @@ typedef struct LocVar { } LocVar; - /* -** Upvalues +** Function Prototypes */ - -typedef struct UpVal { +typedef struct Proto { CommonHeader; - TValue *v; /* points to stack or to its own value */ - union { - TValue value; /* the value (when closed) */ - struct { /* double linked list (when open) */ - struct UpVal *prev; - struct UpVal *next; - } l; - } u; -} UpVal; + lu_byte numparams; /* number of fixed parameters */ + lu_byte is_vararg; /* 2: declared vararg; 1: uses vararg */ + lu_byte maxstacksize; /* number of registers needed by this function */ + int sizeupvalues; /* size of 'upvalues' */ + int sizek; /* size of 'k' */ + int sizecode; + int sizelineinfo; + int sizep; /* size of 'p' */ + int sizelocvars; + int linedefined; /* debug information */ + int lastlinedefined; /* debug information */ + TValue *k; /* constants used by the function */ + Instruction *code; /* opcodes */ + struct Proto **p; /* functions defined inside the function */ + int *lineinfo; /* map from opcodes to source lines (debug information) */ + LocVar *locvars; /* information about local variables (debug information) */ + Upvaldesc *upvalues; /* upvalue information */ + struct LClosure *cache; /* last-created closure with this prototype */ + TString *source; /* used for debug information */ + GCObject *gclist; +} Proto; + + + +/* +** Lua Upvalues +*/ +typedef struct UpVal UpVal; /* @@ -289,20 +441,19 @@ typedef struct UpVal { */ #define ClosureHeader \ - CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \ - struct Table *env + CommonHeader; lu_byte nupvalues; GCObject *gclist typedef struct CClosure { ClosureHeader; lua_CFunction f; - TValue upvalue[1]; + TValue upvalue[1]; /* list of upvalues */ } CClosure; typedef struct LClosure { ClosureHeader; struct Proto *p; - UpVal *upvals[1]; + UpVal *upvals[1]; /* list of upvalues */ } LClosure; @@ -312,8 +463,9 @@ typedef union Closure { } Closure; -#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC) -#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC) +#define isLfunction(o) ttisLclosure(o) + +#define getproto(o) (clLvalue(o)->p) /* @@ -323,12 +475,19 @@ typedef union Closure { typedef union TKey { struct { TValuefields; - struct Node *next; /* for chaining */ + int next; /* for chaining (offset for next node) */ } nk; TValue tvk; } TKey; +/* copy a value into a key without messing up field 'next' */ +#define setnodekey(L,key,obj) \ + { TKey *k_=(key); const TValue *io_=(obj); \ + k_->nk.value_ = io_->value_; k_->nk.tt_ = io_->tt_; \ + (void)L; checkliveness(L,io_); } + + typedef struct Node { TValue i_val; TKey i_key; @@ -337,20 +496,20 @@ typedef struct Node { typedef struct Table { CommonHeader; - lu_byte flags; /* 1<

lsizenode)) +/* +** (address of) a fixed nil value +*/ #define luaO_nilobject (&luaO_nilobject_) -LUAI_DATA const TValue luaO_nilobject_; -#define ceillog2(x) (luaO_log2((x)-1) + 1) +LUAI_DDEC const TValue luaO_nilobject_; + +/* size of buffer for 'luaO_utf8esc' function */ +#define UTF8BUFFSZ 8 -LUAI_FUNC int luaO_log2 (unsigned int x); LUAI_FUNC int luaO_int2fb (unsigned int x); LUAI_FUNC int luaO_fb2int (int x); -LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2); -LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result); +LUAI_FUNC int luaO_utf8esc (char *buff, unsigned long x); +LUAI_FUNC int luaO_ceillog2 (unsigned int x); +LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1, + const TValue *p2, TValue *res); +LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o); +LUAI_FUNC int luaO_hexavalue (int c); +LUAI_FUNC void luaO_tostring (lua_State *L, StkId obj); LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp); LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); diff --git a/app/src/main/jni/lua/lopcodes.c b/app/src/main/jni/lua/lopcodes.c index 4cc7452..a1cbef8 100644 --- a/app/src/main/jni/lua/lopcodes.c +++ b/app/src/main/jni/lua/lopcodes.c @@ -1,27 +1,32 @@ /* -** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lopcodes.c,v 1.55 2015/01/05 13:48:33 roberto Exp $ +** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ - #define lopcodes_c #define LUA_CORE +#include "lprefix.h" + + +#include #include "lopcodes.h" /* ORDER OP */ -const char *const luaP_opnames[NUM_OPCODES+1] = { +LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { "MOVE", "LOADK", + "LOADKX", "LOADBOOL", "LOADNIL", "GETUPVAL", - "GETGLOBAL", + "GETTABUP", "GETTABLE", - "SETGLOBAL", + "SETTABUP", "SETUPVAL", "SETTABLE", "NEWTABLE", @@ -29,10 +34,17 @@ const char *const luaP_opnames[NUM_OPCODES+1] = { "ADD", "SUB", "MUL", - "DIV", "MOD", "POW", + "DIV", + "IDIV", + "BAND", + "BOR", + "BXOR", + "SHL", + "SHR", "UNM", + "BNOT", "NOT", "LEN", "CONCAT", @@ -47,27 +59,29 @@ const char *const luaP_opnames[NUM_OPCODES+1] = { "RETURN", "FORLOOP", "FORPREP", + "TFORCALL", "TFORLOOP", "SETLIST", - "CLOSE", "CLOSURE", "VARARG", + "EXTRAARG", NULL }; #define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) -const lu_byte luaP_opmodes[NUM_OPCODES] = { +LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { /* T A B C mode opcode */ - opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ + opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ + ,opmode(0, 1, OpArgN, OpArgN, iABx) /* OP_LOADKX */ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_LOADNIL */ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ - ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */ + ,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ - ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */ + ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ @@ -75,10 +89,17 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = { ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_IDIV */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BAND */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BOR */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BXOR */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SHL */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SHR */ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_BNOT */ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ @@ -86,17 +107,18 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = { ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ - ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */ + ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TEST */ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ - ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */ + ,opmode(0, 0, OpArgN, OpArgU, iABC) /* OP_TFORCALL */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_TFORLOOP */ ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ - ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */ ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ + ,opmode(0, 0, OpArgU, OpArgU, iAx) /* OP_EXTRAARG */ }; diff --git a/app/src/main/jni/lua/lopcodes.h b/app/src/main/jni/lua/lopcodes.h index 41224d6..864b8e4 100644 --- a/app/src/main/jni/lua/lopcodes.h +++ b/app/src/main/jni/lua/lopcodes.h @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lopcodes.h,v 1.148 2014/10/25 11:50:46 roberto Exp $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -14,11 +14,12 @@ We assume that instructions are unsigned numbers. All instructions have an opcode in the first 6 bits. Instructions can have the following fields: - `A' : 8 bits - `B' : 9 bits - `C' : 9 bits - `Bx' : 18 bits (`B' and `C' together) - `sBx' : signed Bx + 'A' : 8 bits + 'B' : 9 bits + 'C' : 9 bits + 'Ax' : 26 bits ('A', 'B', and 'C' together) + 'Bx' : 18 bits ('B' and 'C' together) + 'sBx' : signed Bx A signed argument is represented in excess K; that is, the number value is the unsigned value minus K. K is exactly the maximum value @@ -28,7 +29,7 @@ ===========================================================================*/ -enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ +enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ /* @@ -38,6 +39,7 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ #define SIZE_B 9 #define SIZE_Bx (SIZE_C + SIZE_B) #define SIZE_A 8 +#define SIZE_Ax (SIZE_C + SIZE_B + SIZE_A) #define SIZE_OP 6 @@ -46,6 +48,7 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ #define POS_C (POS_A + SIZE_A) #define POS_B (POS_C + SIZE_C) #define POS_Bx POS_C +#define POS_Ax POS_A /* @@ -55,22 +58,28 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ */ #if SIZE_Bx < LUAI_BITSINT-1 #define MAXARG_Bx ((1<>1) /* `sBx' is signed */ +#define MAXARG_sBx (MAXARG_Bx>>1) /* 'sBx' is signed */ #else #define MAXARG_Bx MAX_INT #define MAXARG_sBx MAX_INT #endif +#if SIZE_Ax < LUAI_BITSINT-1 +#define MAXARG_Ax ((1<>POS_A) & MASK1(SIZE_A,0))) -#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ - ((cast(Instruction, u)<>pos) & MASK1(size,0))) +#define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \ + ((cast(Instruction, v)<>POS_B) & MASK1(SIZE_B,0))) -#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ - ((cast(Instruction, b)<>POS_C) & MASK1(SIZE_C,0))) -#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ - ((cast(Instruction, b)<>POS_Bx) & MASK1(SIZE_Bx,0))) -#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \ - ((cast(Instruction, b)<> RK(C) */ OP_UNM,/* A B R(A) := -R(B) */ +OP_BNOT,/* A B R(A) := ~R(B) */ OP_NOT,/* A B R(A) := not R(B) */ OP_LEN,/* A B R(A) := length of R(B) */ OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */ -OP_JMP,/* sBx pc+=sBx */ - +OP_JMP,/* A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) */ OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ -OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ -OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ +OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ +OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ -OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ -OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ +OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ +OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ @@ -197,39 +219,44 @@ OP_FORLOOP,/* A sBx R(A)+=R(A+2); if R(A) =) R(A)*/ -OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ +OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx]) */ + +OP_VARARG,/* A B R(A), R(A+1), ..., R(A+B-2) = vararg */ -OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ +OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ } OpCode; -#define NUM_OPCODES (cast(int, OP_VARARG) + 1) +#define NUM_OPCODES (cast(int, OP_EXTRAARG) + 1) /*=========================================================================== Notes: - (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, - and can be 0: OP_CALL then sets `top' to last_result+1, so - next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. + (*) In OP_CALL, if (B == 0) then B = top. If (C == 0), then 'top' is + set to last_result+1, so next open instruction (OP_CALL, OP_RETURN, + OP_SETLIST) may use 'top'. (*) In OP_VARARG, if (B == 0) then use actual number of varargs and - set top (like in OP_CALL with C == 0). + set top (like in OP_CALL with C == 0). - (*) In OP_RETURN, if (B == 0) then return up to `top' + (*) In OP_RETURN, if (B == 0) then return up to 'top'. - (*) In OP_SETLIST, if (B == 0) then B = `top'; - if (C == 0) then next `instruction' is real C + (*) In OP_SETLIST, if (B == 0) then B = 'top'; if (C == 0) then next + 'instruction' is EXTRAARG(real C). + + (*) In OP_LOADKX, the next 'instruction' is always EXTRAARG. (*) For comparisons, A specifies what condition the test should accept - (true or false). + (true or false). + + (*) All 'skips' (pc++) assume that next instruction is a jump. - (*) All `skips' (pc++) assume that next instruction is a jump ===========================================================================*/ @@ -239,8 +266,8 @@ OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ ** bits 2-3: C arg mode ** bits 4-5: B arg mode ** bit 6: instruction set register A -** bit 7: operator is a test -*/ +** bit 7: operator is a test (next instruction must be a jump) +*/ enum OpArgMask { OpArgN, /* argument is not used */ @@ -249,7 +276,7 @@ enum OpArgMask { OpArgK /* argument is a constant or register/constant */ }; -LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES]; +LUAI_DDEC const lu_byte luaP_opmodes[NUM_OPCODES]; #define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) #define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) @@ -258,7 +285,7 @@ LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES]; #define testTMode(m) (luaP_opmodes[m] & (1 << 7)) -LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ +LUAI_DDEC const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ /* number of list items to accumulate before a SETLIST instruction */ diff --git a/app/src/main/jni/lua/loslib.c b/app/src/main/jni/lua/loslib.c index da06a57..4810655 100644 --- a/app/src/main/jni/lua/loslib.c +++ b/app/src/main/jni/lua/loslib.c @@ -1,9 +1,14 @@ /* -** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $ +** $Id: loslib.c,v 1.64 2016/04/18 13:06:55 roberto Exp $ ** Standard Operating System library ** See Copyright Notice in lua.h */ +#define loslib_c +#define LUA_LIB + +#include "lprefix.h" + #include #include @@ -11,46 +16,150 @@ #include #include -#define loslib_c -#define LUA_LIB - #include "lua.h" #include "lauxlib.h" #include "lualib.h" -static int os_pushresult (lua_State *L, int i, const char *filename) { - int en = errno; /* calls to Lua API may change this value */ - if (i) { - lua_pushboolean(L, 1); - return 1; - } - else { - lua_pushnil(L); - lua_pushfstring(L, "%s: %s", filename, strerror(en)); - lua_pushinteger(L, en); - return 3; - } +/* +** {================================================================== +** List of valid conversion specifiers for the 'strftime' function; +** options are grouped by length; group of length 2 start with '||'. +** =================================================================== +*/ +#if !defined(LUA_STRFTIMEOPTIONS) /* { */ + +/* options for ANSI C 89 */ +#define L_STRFTIMEC89 "aAbBcdHIjmMpSUwWxXyYZ%" + +/* options for ISO C 99 and POSIX */ +#define L_STRFTIMEC99 "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \ + "||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy" + +/* options for Windows */ +#define L_STRFTIMEWIN "aAbBcdHIjmMpSUwWxXyYzZ%" \ + "||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" + +#if defined(LUA_USE_WINDOWS) +#define LUA_STRFTIMEOPTIONS L_STRFTIMEWIN +#elif defined(LUA_USE_C89) +#define LUA_STRFTIMEOPTIONS L_STRFTIMEC89 +#else /* C99 specification */ +#define LUA_STRFTIMEOPTIONS L_STRFTIMEC99 +#endif + +#endif /* } */ +/* }================================================================== */ + + +/* +** {================================================================== +** Configuration for time-related stuff +** =================================================================== +*/ + +#if !defined(l_time_t) /* { */ +/* +** type to represent time_t in Lua +*/ +#define l_timet lua_Integer +#define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t)) + +static time_t l_checktime (lua_State *L, int arg) { + lua_Integer t = luaL_checkinteger(L, arg); + luaL_argcheck(L, (time_t)t == t, arg, "time out-of-bounds"); + return (time_t)t; } +#endif /* } */ + + +#if !defined(l_gmtime) /* { */ +/* +** By default, Lua uses gmtime/localtime, except when POSIX is available, +** where it uses gmtime_r/localtime_r +*/ + +#if defined(LUA_USE_POSIX) /* { */ + +#define l_gmtime(t,r) gmtime_r(t,r) +#define l_localtime(t,r) localtime_r(t,r) + +#else /* }{ */ + +/* ISO C definitions */ +#define l_gmtime(t,r) ((void)(r)->tm_sec, gmtime(t)) +#define l_localtime(t,r) ((void)(r)->tm_sec, localtime(t)) + +#endif /* } */ + +#endif /* } */ + +/* }================================================================== */ + + +/* +** {================================================================== +** Configuration for 'tmpnam': +** By default, Lua uses tmpnam except when POSIX is available, where +** it uses mkstemp. +** =================================================================== +*/ +#if !defined(lua_tmpnam) /* { */ + +#if defined(LUA_USE_POSIX) /* { */ + +#include + +#define LUA_TMPNAMBUFSIZE 32 + +#if !defined(LUA_TMPNAMTEMPLATE) +#define LUA_TMPNAMTEMPLATE "/tmp/lua_XXXXXX" +#endif + +#define lua_tmpnam(b,e) { \ + strcpy(b, LUA_TMPNAMTEMPLATE); \ + e = mkstemp(b); \ + if (e != -1) close(e); \ + e = (e == -1); } + +#else /* }{ */ + +/* ISO C definitions */ +#define LUA_TMPNAMBUFSIZE L_tmpnam +#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } + +#endif /* } */ + +#endif /* } */ +/* }================================================================== */ + + + static int os_execute (lua_State *L) { - lua_pushinteger(L, system(luaL_optstring(L, 1, NULL))); - return 1; + const char *cmd = luaL_optstring(L, 1, NULL); + int stat = system(cmd); + if (cmd != NULL) + return luaL_execresult(L, stat); + else { + lua_pushboolean(L, stat); /* true if there is a shell */ + return 1; + } } static int os_remove (lua_State *L) { const char *filename = luaL_checkstring(L, 1); - return os_pushresult(L, remove(filename) == 0, filename); + return luaL_fileresult(L, remove(filename) == 0, filename); } static int os_rename (lua_State *L) { const char *fromname = luaL_checkstring(L, 1); const char *toname = luaL_checkstring(L, 2); - return os_pushresult(L, rename(fromname, toname) == 0, fromname); + return luaL_fileresult(L, rename(fromname, toname) == 0, NULL); } @@ -97,68 +206,109 @@ static void setboolfield (lua_State *L, const char *key, int value) { lua_setfield(L, -2, key); } + +/* +** Set all fields from structure 'tm' in the table on top of the stack +*/ +static void setallfields (lua_State *L, struct tm *stm) { + setfield(L, "sec", stm->tm_sec); + setfield(L, "min", stm->tm_min); + setfield(L, "hour", stm->tm_hour); + setfield(L, "day", stm->tm_mday); + setfield(L, "month", stm->tm_mon + 1); + setfield(L, "year", stm->tm_year + 1900); + setfield(L, "wday", stm->tm_wday + 1); + setfield(L, "yday", stm->tm_yday + 1); + setboolfield(L, "isdst", stm->tm_isdst); +} + + static int getboolfield (lua_State *L, const char *key) { int res; - lua_getfield(L, -1, key); - res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1); + res = (lua_getfield(L, -1, key) == LUA_TNIL) ? -1 : lua_toboolean(L, -1); lua_pop(L, 1); return res; } -static int getfield (lua_State *L, const char *key, int d) { - int res; - lua_getfield(L, -1, key); - if (lua_isnumber(L, -1)) - res = (int)lua_tointeger(L, -1); - else { - if (d < 0) - return luaL_error(L, "field " LUA_QS " missing in date table", key); +/* maximum value for date fields (to avoid arithmetic overflows with 'int') */ +#if !defined(L_MAXDATEFIELD) +#define L_MAXDATEFIELD (INT_MAX / 2) +#endif + +static int getfield (lua_State *L, const char *key, int d, int delta) { + int isnum; + int t = lua_getfield(L, -1, key); /* get field and its type */ + lua_Integer res = lua_tointegerx(L, -1, &isnum); + if (!isnum) { /* field is not an integer? */ + if (t != LUA_TNIL) /* some other value? */ + return luaL_error(L, "field '%s' is not an integer", key); + else if (d < 0) /* absent field; no default? */ + return luaL_error(L, "field '%s' missing in date table", key); res = d; } + else { + if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD)) + return luaL_error(L, "field '%s' is out-of-bound", key); + res -= delta; + } lua_pop(L, 1); - return res; + return (int)res; } +static const char *checkoption (lua_State *L, const char *conv, char *buff) { + const char *option; + int oplen = 1; + for (option = LUA_STRFTIMEOPTIONS; *option != '\0'; option += oplen) { + if (*option == '|') /* next block? */ + oplen++; /* next length */ + else if (memcmp(conv, option, oplen) == 0) { /* match? */ + memcpy(buff, conv, oplen); /* copy valid option to buffer */ + buff[oplen] = '\0'; + return conv + oplen; /* return next item */ + } + } + luaL_argerror(L, 1, + lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv)); + return conv; /* to avoid warnings */ +} + + +/* maximum size for an individual 'strftime' item */ +#define SIZETIMEFMT 250 + + static int os_date (lua_State *L) { const char *s = luaL_optstring(L, 1, "%c"); - time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); - struct tm *stm; + time_t t = luaL_opt(L, l_checktime, 2, time(NULL)); + struct tm tmr, *stm; if (*s == '!') { /* UTC? */ - stm = gmtime(&t); - s++; /* skip `!' */ + stm = l_gmtime(&t, &tmr); + s++; /* skip '!' */ } else - stm = localtime(&t); + stm = l_localtime(&t, &tmr); if (stm == NULL) /* invalid date? */ - lua_pushnil(L); - else if (strcmp(s, "*t") == 0) { + luaL_error(L, "time result cannot be represented in this installation"); + if (strcmp(s, "*t") == 0) { lua_createtable(L, 0, 9); /* 9 = number of fields */ - setfield(L, "sec", stm->tm_sec); - setfield(L, "min", stm->tm_min); - setfield(L, "hour", stm->tm_hour); - setfield(L, "day", stm->tm_mday); - setfield(L, "month", stm->tm_mon+1); - setfield(L, "year", stm->tm_year+1900); - setfield(L, "wday", stm->tm_wday+1); - setfield(L, "yday", stm->tm_yday+1); - setboolfield(L, "isdst", stm->tm_isdst); + setallfields(L, stm); } else { - char cc[3]; + char cc[4]; /* buffer for individual conversion specifiers */ luaL_Buffer b; - cc[0] = '%'; cc[2] = '\0'; + cc[0] = '%'; luaL_buffinit(L, &b); - for (; *s; s++) { - if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */ - luaL_addchar(&b, *s); + while (*s) { + if (*s != '%') /* not a conversion specifier? */ + luaL_addchar(&b, *s++); else { size_t reslen; - char buff[200]; /* should be big enough for any conversion result */ - cc[1] = *(++s); - reslen = strftime(buff, sizeof(buff), cc, stm); - luaL_addlstring(&b, buff, reslen); + char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT); + s = checkoption(L, s + 1, cc + 1); /* copy specifier to 'cc' */ + reslen = strftime(buff, SIZETIMEFMT, cc, stm); + luaL_addsize(&b, reslen); } } luaL_pushresult(&b); @@ -175,26 +325,27 @@ static int os_time (lua_State *L) { struct tm ts; luaL_checktype(L, 1, LUA_TTABLE); lua_settop(L, 1); /* make sure table is at the top */ - ts.tm_sec = getfield(L, "sec", 0); - ts.tm_min = getfield(L, "min", 0); - ts.tm_hour = getfield(L, "hour", 12); - ts.tm_mday = getfield(L, "day", -1); - ts.tm_mon = getfield(L, "month", -1) - 1; - ts.tm_year = getfield(L, "year", -1) - 1900; + ts.tm_sec = getfield(L, "sec", 0, 0); + ts.tm_min = getfield(L, "min", 0, 0); + ts.tm_hour = getfield(L, "hour", 12, 0); + ts.tm_mday = getfield(L, "day", -1, 0); + ts.tm_mon = getfield(L, "month", -1, 1); + ts.tm_year = getfield(L, "year", -1, 1900); ts.tm_isdst = getboolfield(L, "isdst"); t = mktime(&ts); + setallfields(L, &ts); /* update fields with normalized values */ } - if (t == (time_t)(-1)) - lua_pushnil(L); - else - lua_pushnumber(L, (lua_Number)t); + if (t != (time_t)(l_timet)t || t == (time_t)(-1)) + luaL_error(L, "time result cannot be represented in this installation"); + l_pushtime(L, t); return 1; } static int os_difftime (lua_State *L) { - lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), - (time_t)(luaL_optnumber(L, 2, 0)))); + time_t t1 = l_checktime(L, 1); + time_t t2 = l_checktime(L, 2); + lua_pushnumber(L, (lua_Number)difftime(t1, t2)); return 1; } @@ -214,9 +365,18 @@ static int os_setlocale (lua_State *L) { static int os_exit (lua_State *L) { - exit(luaL_optint(L, 1, EXIT_SUCCESS)); + int status; + if (lua_isboolean(L, 1)) + status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE); + else + status = (int)luaL_optinteger(L, 1, EXIT_SUCCESS); + if (lua_toboolean(L, 2)) + lua_close(L); + if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */ + return 0; } + static const luaL_Reg syslib[] = { {"clock", os_clock}, {"date", os_date}, @@ -236,8 +396,8 @@ static const luaL_Reg syslib[] = { -LUALIB_API int luaopen_os (lua_State *L) { - luaL_register(L, LUA_OSLIBNAME, syslib); +LUAMOD_API int luaopen_os (lua_State *L) { + luaL_newlib(L, syslib); return 1; } diff --git a/app/src/main/jni/lua/lparser.c b/app/src/main/jni/lua/lparser.c index dda7488..22530a5 100644 --- a/app/src/main/jni/lua/lparser.c +++ b/app/src/main/jni/lua/lparser.c @@ -1,15 +1,17 @@ /* -** $Id: lparser.c,v 2.42.1.4 2011/10/21 19:31:42 roberto Exp $ +** $Id: lparser.c,v 2.153 2016/05/13 19:10:16 roberto Exp $ ** Lua Parser ** See Copyright Notice in lua.h */ - -#include - #define lparser_c #define LUA_CORE +#include "lprefix.h" + + +#include + #include "lua.h" #include "lcode.h" @@ -27,11 +29,17 @@ +/* maximum number of local variables per function (must be smaller + than 250, due to the bytecode format) */ +#define MAXVARS 200 + + #define hasmultret(k) ((k) == VCALL || (k) == VVARARG) -#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) -#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m) +/* because all strings are unified by the scanner, the parser + can use pointer equality for string equality */ +#define eqstr(a,b) ((a) == (b)) /* @@ -39,10 +47,11 @@ */ typedef struct BlockCnt { struct BlockCnt *previous; /* chain */ - int breaklist; /* list of jumps out of this loop */ - lu_byte nactvar; /* # active locals outside the breakable structure */ + int firstlabel; /* index of first label in this block */ + int firstgoto; /* index of first pending goto in this block */ + lu_byte nactvar; /* # active locals outside the block */ lu_byte upval; /* true if some variable in the block is an upvalue */ - lu_byte isbreakable; /* true if `block' is a loop */ + lu_byte isloop; /* true if 'block' is a loop */ } BlockCnt; @@ -50,30 +59,38 @@ typedef struct BlockCnt { /* ** prototypes for recursive non-terminal functions */ -static void chunk (LexState *ls); +static void statement (LexState *ls); static void expr (LexState *ls, expdesc *v); -static void anchor_token (LexState *ls) { - if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { - TString *ts = ls->t.seminfo.ts; - luaX_newstring(ls, getstr(ts), ts->tsv.len); - } +/* semantic error */ +static l_noret semerror (LexState *ls, const char *msg) { + ls->t.token = 0; /* remove "near " from final message */ + luaX_syntaxerror(ls, msg); } -static void error_expected (LexState *ls, int token) { +static l_noret error_expected (LexState *ls, int token) { luaX_syntaxerror(ls, - luaO_pushfstring(ls->L, LUA_QS " expected", luaX_token2str(ls, token))); + luaO_pushfstring(ls->L, "%s expected", luaX_token2str(ls, token))); } -static void errorlimit (FuncState *fs, int limit, const char *what) { - const char *msg = (fs->f->linedefined == 0) ? - luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) : - luaO_pushfstring(fs->L, "function at line %d has more than %d %s", - fs->f->linedefined, limit, what); - luaX_lexerror(fs->ls, msg, 0); +static l_noret errorlimit (FuncState *fs, int limit, const char *what) { + lua_State *L = fs->ls->L; + const char *msg; + int line = fs->f->linedefined; + const char *where = (line == 0) + ? "main function" + : luaO_pushfstring(L, "function at line %d", line); + msg = luaO_pushfstring(L, "too many %s (limit is %d) in %s", + what, limit, where); + luaX_syntaxerror(fs->ls, msg); +} + + +static void checklimit (FuncState *fs, int v, int l, const char *what) { + if (v > l) errorlimit(fs, l, what); } @@ -91,6 +108,7 @@ static void check (LexState *ls, int c) { error_expected(ls, c); } + static void checknext (LexState *ls, int c) { check(ls, c); luaX_next(ls); @@ -107,7 +125,7 @@ static void check_match (LexState *ls, int what, int who, int where) { error_expected(ls, what); else { luaX_syntaxerror(ls, luaO_pushfstring(ls->L, - LUA_QS " expected (to close " LUA_QS " at line %d)", + "%s expected (to close %s at line %d)", luaX_token2str(ls, what), luaX_token2str(ls, who), where)); } } @@ -126,7 +144,7 @@ static TString *str_checkname (LexState *ls) { static void init_exp (expdesc *e, expkind k, int i) { e->f = e->t = NO_JUMP; e->k = k; - e->u.s.info = i; + e->u.info = i; } @@ -135,7 +153,7 @@ static void codestring (LexState *ls, expdesc *e, TString *s) { } -static void checkname(LexState *ls, expdesc *e) { +static void checkname (LexState *ls, expdesc *e) { codestring(ls, e, str_checkname(ls)); } @@ -145,22 +163,39 @@ static int registerlocalvar (LexState *ls, TString *varname) { Proto *f = fs->f; int oldsize = f->sizelocvars; luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, - LocVar, SHRT_MAX, "too many local variables"); - while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; + LocVar, SHRT_MAX, "local variables"); + while (oldsize < f->sizelocvars) + f->locvars[oldsize++].varname = NULL; f->locvars[fs->nlocvars].varname = varname; luaC_objbarrier(ls->L, f, varname); return fs->nlocvars++; } -#define new_localvarliteral(ls,v,n) \ - new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n) +static void new_localvar (LexState *ls, TString *name) { + FuncState *fs = ls->fs; + Dyndata *dyd = ls->dyd; + int reg = registerlocalvar(ls, name); + checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, + MAXVARS, "local variables"); + luaM_growvector(ls->L, dyd->actvar.arr, dyd->actvar.n + 1, + dyd->actvar.size, Vardesc, MAX_INT, "local variables"); + dyd->actvar.arr[dyd->actvar.n++].idx = cast(short, reg); +} -static void new_localvar (LexState *ls, TString *name, int n) { - FuncState *fs = ls->fs; - luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables"); - fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name)); +static void new_localvarliteral_ (LexState *ls, const char *name, size_t sz) { + new_localvar(ls, luaX_newstring(ls, name, sz)); +} + +#define new_localvarliteral(ls,v) \ + new_localvarliteral_(ls, "" v, (sizeof(v)/sizeof(char))-1) + + +static LocVar *getlocvar (FuncState *fs, int i) { + int idx = fs->ls->dyd->actvar.arr[fs->firstlocal + i].idx; + lua_assert(idx < fs->nlocvars); + return &fs->f->locvars[idx]; } @@ -168,78 +203,90 @@ static void adjustlocalvars (LexState *ls, int nvars) { FuncState *fs = ls->fs; fs->nactvar = cast_byte(fs->nactvar + nvars); for (; nvars; nvars--) { - getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc; + getlocvar(fs, fs->nactvar - nvars)->startpc = fs->pc; } } -static void removevars (LexState *ls, int tolevel) { - FuncState *fs = ls->fs; +static void removevars (FuncState *fs, int tolevel) { + fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel); while (fs->nactvar > tolevel) - getlocvar(fs, --fs->nactvar).endpc = fs->pc; + getlocvar(fs, --fs->nactvar)->endpc = fs->pc; } -static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { +static int searchupvalue (FuncState *fs, TString *name) { int i; + Upvaldesc *up = fs->f->upvalues; + for (i = 0; i < fs->nups; i++) { + if (eqstr(up[i].name, name)) return i; + } + return -1; /* not found */ +} + + +static int newupvalue (FuncState *fs, TString *name, expdesc *v) { Proto *f = fs->f; int oldsize = f->sizeupvalues; - for (i=0; inups; i++) { - if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) { - lua_assert(f->upvalues[i] == name); - return i; - } - } - /* new one */ - luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, "upvalues"); - luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues, - TString *, MAX_INT, ""); - while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL; - f->upvalues[f->nups] = name; - luaC_objbarrier(fs->L, f, name); - lua_assert(v->k == VLOCAL || v->k == VUPVAL); - fs->upvalues[f->nups].k = cast_byte(v->k); - fs->upvalues[f->nups].info = cast_byte(v->u.s.info); - return f->nups++; + checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues"); + luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues, + Upvaldesc, MAXUPVAL, "upvalues"); + while (oldsize < f->sizeupvalues) + f->upvalues[oldsize++].name = NULL; + f->upvalues[fs->nups].instack = (v->k == VLOCAL); + f->upvalues[fs->nups].idx = cast_byte(v->u.info); + f->upvalues[fs->nups].name = name; + luaC_objbarrier(fs->ls->L, f, name); + return fs->nups++; } static int searchvar (FuncState *fs, TString *n) { int i; - for (i=fs->nactvar-1; i >= 0; i--) { - if (n == getlocvar(fs, i).varname) + for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { + if (eqstr(n, getlocvar(fs, i)->varname)) return i; } return -1; /* not found */ } +/* + Mark block where variable at given level was defined + (to emit close instructions later). +*/ static void markupval (FuncState *fs, int level) { BlockCnt *bl = fs->bl; - while (bl && bl->nactvar > level) bl = bl->previous; - if (bl) bl->upval = 1; + while (bl->nactvar > level) + bl = bl->previous; + bl->upval = 1; } -static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { - if (fs == NULL) { /* no more levels? */ - init_exp(var, VGLOBAL, NO_REG); /* default is global variable */ - return VGLOBAL; - } +/* + Find variable with given name 'n'. If it is an upvalue, add this + upvalue into all intermediate functions. +*/ +static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { + if (fs == NULL) /* no more levels? */ + init_exp(var, VVOID, 0); /* default is global */ else { - int v = searchvar(fs, n); /* look up at current level */ - if (v >= 0) { - init_exp(var, VLOCAL, v); + int v = searchvar(fs, n); /* look up locals at current level */ + if (v >= 0) { /* found? */ + init_exp(var, VLOCAL, v); /* variable is local */ if (!base) markupval(fs, v); /* local will be used as an upval */ - return VLOCAL; } - else { /* not found at current level; try upper one */ - if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL) - return VGLOBAL; - var->u.s.info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */ - var->k = VUPVAL; /* upvalue in this level */ - return VUPVAL; + else { /* not found as local at current level; try upvalues */ + int idx = searchupvalue(fs, n); /* try existing upvalues */ + if (idx < 0) { /* not found? */ + singlevaraux(fs->prev, n, var, 0); /* try upper levels */ + if (var->k == VVOID) /* not found? */ + return; /* it is a global */ + /* else was LOCAL or UPVAL */ + idx = newupvalue(fs, n, var); /* will be a new upvalue */ + } + init_exp(var, VUPVAL, idx); /* new or old upvalue */ } } } @@ -248,8 +295,14 @@ static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { static void singlevar (LexState *ls, expdesc *var) { TString *varname = str_checkname(ls); FuncState *fs = ls->fs; - if (singlevaraux(fs, varname, var, 1) == VGLOBAL) - var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */ + singlevaraux(fs, varname, var, 1); + if (var->k == VVOID) { /* global name? */ + expdesc key; + singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ + lua_assert(var->k != VVOID); /* this one must exist */ + codestring(ls, &key, varname); /* key is variable name */ + luaK_indexed(fs, var, &key); /* env[varname] */ + } } @@ -274,18 +327,118 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { static void enterlevel (LexState *ls) { - if (++ls->L->nCcalls > LUAI_MAXCCALLS) - luaX_lexerror(ls, "chunk has too many syntax levels", 0); + lua_State *L = ls->L; + ++L->nCcalls; + checklimit(ls->fs, L->nCcalls, LUAI_MAXCCALLS, "C levels"); } #define leavelevel(ls) ((ls)->L->nCcalls--) -static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { - bl->breaklist = NO_JUMP; - bl->isbreakable = isbreakable; +static void closegoto (LexState *ls, int g, Labeldesc *label) { + int i; + FuncState *fs = ls->fs; + Labellist *gl = &ls->dyd->gt; + Labeldesc *gt = &gl->arr[g]; + lua_assert(eqstr(gt->name, label->name)); + if (gt->nactvar < label->nactvar) { + TString *vname = getlocvar(fs, gt->nactvar)->varname; + const char *msg = luaO_pushfstring(ls->L, + " at line %d jumps into the scope of local '%s'", + getstr(gt->name), gt->line, getstr(vname)); + semerror(ls, msg); + } + luaK_patchlist(fs, gt->pc, label->pc); + /* remove goto from pending list */ + for (i = g; i < gl->n - 1; i++) + gl->arr[i] = gl->arr[i + 1]; + gl->n--; +} + + +/* +** try to close a goto with existing labels; this solves backward jumps +*/ +static int findlabel (LexState *ls, int g) { + int i; + BlockCnt *bl = ls->fs->bl; + Dyndata *dyd = ls->dyd; + Labeldesc *gt = &dyd->gt.arr[g]; + /* check labels in current block for a match */ + for (i = bl->firstlabel; i < dyd->label.n; i++) { + Labeldesc *lb = &dyd->label.arr[i]; + if (eqstr(lb->name, gt->name)) { /* correct label? */ + if (gt->nactvar > lb->nactvar && + (bl->upval || dyd->label.n > bl->firstlabel)) + luaK_patchclose(ls->fs, gt->pc, lb->nactvar); + closegoto(ls, g, lb); /* close it */ + return 1; + } + } + return 0; /* label not found; cannot close goto */ +} + + +static int newlabelentry (LexState *ls, Labellist *l, TString *name, + int line, int pc) { + int n = l->n; + luaM_growvector(ls->L, l->arr, n, l->size, + Labeldesc, SHRT_MAX, "labels/gotos"); + l->arr[n].name = name; + l->arr[n].line = line; + l->arr[n].nactvar = ls->fs->nactvar; + l->arr[n].pc = pc; + l->n = n + 1; + return n; +} + + +/* +** check whether new label 'lb' matches any pending gotos in current +** block; solves forward jumps +*/ +static void findgotos (LexState *ls, Labeldesc *lb) { + Labellist *gl = &ls->dyd->gt; + int i = ls->fs->bl->firstgoto; + while (i < gl->n) { + if (eqstr(gl->arr[i].name, lb->name)) + closegoto(ls, i, lb); + else + i++; + } +} + + +/* +** export pending gotos to outer level, to check them against +** outer labels; if the block being exited has upvalues, and +** the goto exits the scope of any variable (which can be the +** upvalue), close those variables being exited. +*/ +static void movegotosout (FuncState *fs, BlockCnt *bl) { + int i = bl->firstgoto; + Labellist *gl = &fs->ls->dyd->gt; + /* correct pending gotos to current block and try to close it + with visible labels */ + while (i < gl->n) { + Labeldesc *gt = &gl->arr[i]; + if (gt->nactvar > bl->nactvar) { + if (bl->upval) + luaK_patchclose(fs, gt->pc, bl->nactvar); + gt->nactvar = bl->nactvar; + } + if (!findlabel(fs->ls, i)) + i++; /* move to next one */ + } +} + + +static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { + bl->isloop = isloop; bl->nactvar = fs->nactvar; + bl->firstlabel = fs->ls->dyd->label.n; + bl->firstgoto = fs->ls->dyd->gt.n; bl->upval = 0; bl->previous = fs->bl; fs->bl = bl; @@ -293,63 +446,104 @@ static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { } +/* +** create a label named 'break' to resolve break statements +*/ +static void breaklabel (LexState *ls) { + TString *n = luaS_new(ls->L, "break"); + int l = newlabelentry(ls, &ls->dyd->label, n, 0, ls->fs->pc); + findgotos(ls, &ls->dyd->label.arr[l]); +} + +/* +** generates an error for an undefined 'goto'; choose appropriate +** message when label name is a reserved word (which can only be 'break') +*/ +static l_noret undefgoto (LexState *ls, Labeldesc *gt) { + const char *msg = isreserved(gt->name) + ? "<%s> at line %d not inside a loop" + : "no visible label '%s' for at line %d"; + msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line); + semerror(ls, msg); +} + + static void leaveblock (FuncState *fs) { BlockCnt *bl = fs->bl; + LexState *ls = fs->ls; + if (bl->previous && bl->upval) { + /* create a 'jump to here' to close upvalues */ + int j = luaK_jump(fs); + luaK_patchclose(fs, j, bl->nactvar); + luaK_patchtohere(fs, j); + } + if (bl->isloop) + breaklabel(ls); /* close pending breaks */ fs->bl = bl->previous; - removevars(fs->ls, bl->nactvar); - if (bl->upval) - luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); - /* a block either controls scope or breaks (never both) */ - lua_assert(!bl->isbreakable || !bl->upval); + removevars(fs, bl->nactvar); lua_assert(bl->nactvar == fs->nactvar); fs->freereg = fs->nactvar; /* free registers */ - luaK_patchtohere(fs, bl->breaklist); + ls->dyd->label.n = bl->firstlabel; /* remove local labels */ + if (bl->previous) /* inner block? */ + movegotosout(fs, bl); /* update pending gotos to outer block */ + else if (bl->firstgoto < ls->dyd->gt.n) /* pending gotos in outer block? */ + undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]); /* error */ } -static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { +/* +** adds a new prototype into list of prototypes +*/ +static Proto *addprototype (LexState *ls) { + Proto *clp; + lua_State *L = ls->L; FuncState *fs = ls->fs; - Proto *f = fs->f; - int oldsize = f->sizep; - int i; - luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, - MAXARG_Bx, "constant table overflow"); - while (oldsize < f->sizep) f->p[oldsize++] = NULL; - f->p[fs->np++] = func->f; - luaC_objbarrier(ls->L, f, func->f); - init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); - for (i=0; if->nups; i++) { - OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; - luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0); + Proto *f = fs->f; /* prototype of current function */ + if (fs->np >= f->sizep) { + int oldsize = f->sizep; + luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions"); + while (oldsize < f->sizep) + f->p[oldsize++] = NULL; } + f->p[fs->np++] = clp = luaF_newproto(L); + luaC_objbarrier(L, f, clp); + return clp; } -static void open_func (LexState *ls, FuncState *fs) { - lua_State *L = ls->L; - Proto *f = luaF_newproto(L); - fs->f = f; +/* +** codes instruction to create new closure in parent function. +** The OP_CLOSURE instruction must use the last available register, +** so that, if it invokes the GC, the GC knows which registers +** are in use at that time. +*/ +static void codeclosure (LexState *ls, expdesc *v) { + FuncState *fs = ls->fs->prev; + init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1)); + luaK_exp2nextreg(fs, v); /* fix it at the last register */ +} + + +static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { + Proto *f; fs->prev = ls->fs; /* linked list of funcstates */ fs->ls = ls; - fs->L = L; ls->fs = fs; fs->pc = 0; - fs->lasttarget = -1; + fs->lasttarget = 0; fs->jpc = NO_JUMP; fs->freereg = 0; fs->nk = 0; fs->np = 0; + fs->nups = 0; fs->nlocvars = 0; fs->nactvar = 0; + fs->firstlocal = ls->dyd->actvar.n; fs->bl = NULL; + f = fs->f; f->source = ls->source; f->maxstacksize = 2; /* registers 0/1 are always valid */ - fs->h = luaH_new(L, 0, 0); - /* anchor table of constants and prototype (to avoid being collected) */ - sethvalue2s(L, L->top, fs->h); - incr_top(L); - setptvalue2s(L, L->top, f); - incr_top(L); + enterblock(fs, bl, 0); } @@ -357,8 +551,8 @@ static void close_func (LexState *ls) { lua_State *L = ls->L; FuncState *fs = ls->fs; Proto *f = fs->f; - removevars(ls, 0); luaK_ret(fs, 0, 0); /* final return */ + leaveblock(fs); luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); f->sizecode = fs->pc; luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); @@ -369,32 +563,11 @@ static void close_func (LexState *ls) { f->sizep = fs->np; luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); f->sizelocvars = fs->nlocvars; - luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *); - f->sizeupvalues = f->nups; - lua_assert(luaG_checkcode(f)); + luaM_reallocvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); + f->sizeupvalues = fs->nups; lua_assert(fs->bl == NULL); ls->fs = fs->prev; - /* last token read was anchored in defunct function; must reanchor it */ - if (fs) anchor_token(ls); - L->top -= 2; /* remove table and prototype from the stack */ -} - - -Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { - struct LexState lexstate; - struct FuncState funcstate; - lexstate.buff = buff; - luaX_setinput(L, &lexstate, z, luaS_new(L, name)); - open_func(&lexstate, &funcstate); - funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */ - luaX_next(&lexstate); /* read first token */ - chunk(&lexstate); - check(&lexstate, TK_EOS); - close_func(&lexstate); - lua_assert(funcstate.prev == NULL); - lua_assert(funcstate.f->nups == 0); - lua_assert(lexstate.fs == NULL); - return funcstate.f; + luaC_checkGC(L); } @@ -404,11 +577,39 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { /*============================================================*/ -static void field (LexState *ls, expdesc *v) { - /* field -> ['.' | ':'] NAME */ +/* +** check whether current token is in the follow set of a block. +** 'until' closes syntactical blocks, but do not close scope, +** so it is handled in separate. +*/ +static int block_follow (LexState *ls, int withuntil) { + switch (ls->t.token) { + case TK_ELSE: case TK_ELSEIF: + case TK_END: case TK_EOS: + return 1; + case TK_UNTIL: return withuntil; + default: return 0; + } +} + + +static void statlist (LexState *ls) { + /* statlist -> { stat [';'] } */ + while (!block_follow(ls, 1)) { + if (ls->t.token == TK_RETURN) { + statement(ls); + return; /* 'return' must be last statement */ + } + statement(ls); + } +} + + +static void fieldsel (LexState *ls, expdesc *v) { + /* fieldsel -> ['.' | ':'] NAME */ FuncState *fs = ls->fs; expdesc key; - luaK_exp2anyreg(fs, v); + luaK_exp2anyregup(fs, v); luaX_next(ls); /* skip the dot or colon */ checkname(ls, &key); luaK_indexed(fs, v, &key); @@ -434,20 +635,20 @@ static void yindex (LexState *ls, expdesc *v) { struct ConsControl { expdesc v; /* last list item read */ expdesc *t; /* table descriptor */ - int nh; /* total number of `record' elements */ + int nh; /* total number of 'record' elements */ int na; /* total number of array elements */ int tostore; /* number of array elements pending to be stored */ }; static void recfield (LexState *ls, struct ConsControl *cc) { - /* recfield -> (NAME | `['exp1`]') = exp1 */ + /* recfield -> (NAME | '['exp1']') = exp1 */ FuncState *fs = ls->fs; int reg = ls->fs->freereg; expdesc key, val; int rkkey; if (ls->t.token == TK_NAME) { - luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); + checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); checkname(ls, &key); } else /* ls->t.token == '[' */ @@ -456,7 +657,7 @@ static void recfield (LexState *ls, struct ConsControl *cc) { checknext(ls, '='); rkkey = luaK_exp2RK(fs, &key); expr(ls, &val); - luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val)); + luaK_codeABC(fs, OP_SETTABLE, cc->t->u.info, rkkey, luaK_exp2RK(fs, &val)); fs->freereg = reg; /* free registers */ } @@ -466,7 +667,7 @@ static void closelistfield (FuncState *fs, struct ConsControl *cc) { luaK_exp2nextreg(fs, &cc->v); cc->v.k = VVOID; if (cc->tostore == LFIELDS_PER_FLUSH) { - luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); /* flush */ + luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */ cc->tostore = 0; /* no more items pending */ } } @@ -476,27 +677,51 @@ static void lastlistfield (FuncState *fs, struct ConsControl *cc) { if (cc->tostore == 0) return; if (hasmultret(cc->v.k)) { luaK_setmultret(fs, &cc->v); - luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET); + luaK_setlist(fs, cc->t->u.info, cc->na, LUA_MULTRET); cc->na--; /* do not count last expression (unknown number of elements) */ } else { if (cc->v.k != VVOID) luaK_exp2nextreg(fs, &cc->v); - luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); + luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); } } static void listfield (LexState *ls, struct ConsControl *cc) { + /* listfield -> exp */ expr(ls, &cc->v); - luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); + checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); cc->na++; cc->tostore++; } +static void field (LexState *ls, struct ConsControl *cc) { + /* field -> listfield | recfield */ + switch(ls->t.token) { + case TK_NAME: { /* may be 'listfield' or 'recfield' */ + if (luaX_lookahead(ls) != '=') /* expression? */ + listfield(ls, cc); + else + recfield(ls, cc); + break; + } + case '[': { + recfield(ls, cc); + break; + } + default: { + listfield(ls, cc); + break; + } + } +} + + static void constructor (LexState *ls, expdesc *t) { - /* constructor -> ?? */ + /* constructor -> '{' [ field { sep field } [sep] ] '}' + sep -> ',' | ';' */ FuncState *fs = ls->fs; int line = ls->linenumber; int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); @@ -505,30 +730,13 @@ static void constructor (LexState *ls, expdesc *t) { cc.t = t; init_exp(t, VRELOCABLE, pc); init_exp(&cc.v, VVOID, 0); /* no value (yet) */ - luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ + luaK_exp2nextreg(ls->fs, t); /* fix it at stack top */ checknext(ls, '{'); do { lua_assert(cc.v.k == VVOID || cc.tostore > 0); if (ls->t.token == '}') break; closelistfield(fs, &cc); - switch(ls->t.token) { - case TK_NAME: { /* may be listfields or recfields */ - luaX_lookahead(ls); - if (ls->lookahead.token != '=') /* expression? */ - listfield(ls, &cc); - else - recfield(ls, &cc); - break; - } - case '[': { /* constructor_item -> recfield */ - recfield(ls, &cc); - break; - } - default: { /* constructor_part -> listfield */ - listfield(ls, &cc); - break; - } - } + field(ls, &cc); } while (testnext(ls, ',') || testnext(ls, ';')); check_match(ls, '}', '{', line); lastlistfield(fs, &cc); @@ -541,60 +749,58 @@ static void constructor (LexState *ls, expdesc *t) { static void parlist (LexState *ls) { - /* parlist -> [ param { `,' param } ] */ + /* parlist -> [ param { ',' param } ] */ FuncState *fs = ls->fs; Proto *f = fs->f; int nparams = 0; f->is_vararg = 0; - if (ls->t.token != ')') { /* is `parlist' not empty? */ + if (ls->t.token != ')') { /* is 'parlist' not empty? */ do { switch (ls->t.token) { case TK_NAME: { /* param -> NAME */ - new_localvar(ls, str_checkname(ls), nparams++); + new_localvar(ls, str_checkname(ls)); + nparams++; break; } - case TK_DOTS: { /* param -> `...' */ + case TK_DOTS: { /* param -> '...' */ luaX_next(ls); -#if defined(LUA_COMPAT_VARARG) - /* use `arg' as default name */ - new_localvarliteral(ls, "arg", nparams++); - f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG; -#endif - f->is_vararg |= VARARG_ISVARARG; + f->is_vararg = 2; /* declared vararg */ break; } - default: luaX_syntaxerror(ls, " or " LUA_QL("...") " expected"); + default: luaX_syntaxerror(ls, " or '...' expected"); } } while (!f->is_vararg && testnext(ls, ',')); } adjustlocalvars(ls, nparams); - f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG)); + f->numparams = cast_byte(fs->nactvar); luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ } -static void body (LexState *ls, expdesc *e, int needself, int line) { - /* body -> `(' parlist `)' chunk END */ +static void body (LexState *ls, expdesc *e, int ismethod, int line) { + /* body -> '(' parlist ')' block END */ FuncState new_fs; - open_func(ls, &new_fs); + BlockCnt bl; + new_fs.f = addprototype(ls); new_fs.f->linedefined = line; + open_func(ls, &new_fs, &bl); checknext(ls, '('); - if (needself) { - new_localvarliteral(ls, "self", 0); + if (ismethod) { + new_localvarliteral(ls, "self"); /* create 'self' parameter */ adjustlocalvars(ls, 1); } parlist(ls); checknext(ls, ')'); - chunk(ls); + statlist(ls); new_fs.f->lastlinedefined = ls->linenumber; check_match(ls, TK_END, TK_FUNCTION, line); + codeclosure(ls, e); close_func(ls); - pushclosure(ls, &new_fs, e); } -static int explist1 (LexState *ls, expdesc *v) { - /* explist1 -> expr { `,' expr } */ +static int explist (LexState *ls, expdesc *v) { + /* explist -> expr { ',' expr } */ int n = 1; /* at least one expression */ expr(ls, v); while (testnext(ls, ',')) { @@ -606,20 +812,17 @@ static int explist1 (LexState *ls, expdesc *v) { } -static void funcargs (LexState *ls, expdesc *f) { +static void funcargs (LexState *ls, expdesc *f, int line) { FuncState *fs = ls->fs; expdesc args; int base, nparams; - int line = ls->linenumber; switch (ls->t.token) { - case '(': { /* funcargs -> `(' [ explist1 ] `)' */ - if (line != ls->lastline) - luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)"); + case '(': { /* funcargs -> '(' [ explist ] ')' */ luaX_next(ls); if (ls->t.token == ')') /* arg list is empty? */ args.k = VVOID; else { - explist1(ls, &args); + explist(ls, &args); luaK_setmultret(fs, &args); } check_match(ls, ')', '(', line); @@ -631,16 +834,15 @@ static void funcargs (LexState *ls, expdesc *f) { } case TK_STRING: { /* funcargs -> STRING */ codestring(ls, &args, ls->t.seminfo.ts); - luaX_next(ls); /* must use `seminfo' before `next' */ + luaX_next(ls); /* must use 'seminfo' before 'next' */ break; } default: { luaX_syntaxerror(ls, "function arguments expected"); - return; } } lua_assert(f->k == VNONRELOC); - base = f->u.s.info; /* base register for call */ + base = f->u.info; /* base register for call */ if (hasmultret(args.k)) nparams = LUA_MULTRET; /* open call */ else { @@ -664,8 +866,8 @@ static void funcargs (LexState *ls, expdesc *f) { */ -static void prefixexp (LexState *ls, expdesc *v) { - /* prefixexp -> NAME | '(' expr ')' */ +static void primaryexp (LexState *ls, expdesc *v) { + /* primaryexp -> NAME | '(' expr ')' */ switch (ls->t.token) { case '(': { int line = ls->linenumber; @@ -681,41 +883,41 @@ static void prefixexp (LexState *ls, expdesc *v) { } default: { luaX_syntaxerror(ls, "unexpected symbol"); - return; } } } -static void primaryexp (LexState *ls, expdesc *v) { - /* primaryexp -> - prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ +static void suffixedexp (LexState *ls, expdesc *v) { + /* suffixedexp -> + primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */ FuncState *fs = ls->fs; - prefixexp(ls, v); + int line = ls->linenumber; + primaryexp(ls, v); for (;;) { switch (ls->t.token) { - case '.': { /* field */ - field(ls, v); + case '.': { /* fieldsel */ + fieldsel(ls, v); break; } - case '[': { /* `[' exp1 `]' */ + case '[': { /* '[' exp1 ']' */ expdesc key; - luaK_exp2anyreg(fs, v); + luaK_exp2anyregup(fs, v); yindex(ls, &key); luaK_indexed(fs, v, &key); break; } - case ':': { /* `:' NAME funcargs */ + case ':': { /* ':' NAME funcargs */ expdesc key; luaX_next(ls); checkname(ls, &key); luaK_self(fs, v, &key); - funcargs(ls, v); + funcargs(ls, v, line); break; } case '(': case TK_STRING: case '{': { /* funcargs */ luaK_exp2nextreg(fs, v); - funcargs(ls, v); + funcargs(ls, v, line); break; } default: return; @@ -725,14 +927,19 @@ static void primaryexp (LexState *ls, expdesc *v) { static void simpleexp (LexState *ls, expdesc *v) { - /* simpleexp -> NUMBER | STRING | NIL | true | false | ... | - constructor | FUNCTION body | primaryexp */ + /* simpleexp -> FLT | INT | STRING | NIL | TRUE | FALSE | ... | + constructor | FUNCTION body | suffixedexp */ switch (ls->t.token) { - case TK_NUMBER: { - init_exp(v, VKNUM, 0); + case TK_FLT: { + init_exp(v, VKFLT, 0); v->u.nval = ls->t.seminfo.r; break; } + case TK_INT: { + init_exp(v, VKINT, 0); + v->u.ival = ls->t.seminfo.i; + break; + } case TK_STRING: { codestring(ls, v, ls->t.seminfo.ts); break; @@ -752,8 +959,8 @@ static void simpleexp (LexState *ls, expdesc *v) { case TK_DOTS: { /* vararg */ FuncState *fs = ls->fs; check_condition(ls, fs->f->is_vararg, - "cannot use " LUA_QL("...") " outside a vararg function"); - fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */ + "cannot use '...' outside a vararg function"); + fs->f->is_vararg = 1; /* function actually uses vararg */ init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); break; } @@ -767,7 +974,7 @@ static void simpleexp (LexState *ls, expdesc *v) { return; } default: { - primaryexp(ls, v); + suffixedexp(ls, v); return; } } @@ -779,6 +986,7 @@ static UnOpr getunopr (int op) { switch (op) { case TK_NOT: return OPR_NOT; case '-': return OPR_MINUS; + case '~': return OPR_BNOT; case '#': return OPR_LEN; default: return OPR_NOUNOPR; } @@ -790,9 +998,15 @@ static BinOpr getbinopr (int op) { case '+': return OPR_ADD; case '-': return OPR_SUB; case '*': return OPR_MUL; - case '/': return OPR_DIV; case '%': return OPR_MOD; case '^': return OPR_POW; + case '/': return OPR_DIV; + case TK_IDIV: return OPR_IDIV; + case '&': return OPR_BAND; + case '|': return OPR_BOR; + case '~': return OPR_BXOR; + case TK_SHL: return OPR_SHL; + case TK_SHR: return OPR_SHR; case TK_CONCAT: return OPR_CONCAT; case TK_NE: return OPR_NE; case TK_EQ: return OPR_EQ; @@ -811,41 +1025,48 @@ static const struct { lu_byte left; /* left priority for each binary operator */ lu_byte right; /* right priority */ } priority[] = { /* ORDER OPR */ - {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `/' `%' */ - {10, 9}, {5, 4}, /* power and concat (right associative) */ - {3, 3}, {3, 3}, /* equality and inequality */ - {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */ - {2, 2}, {1, 1} /* logical (and/or) */ + {10, 10}, {10, 10}, /* '+' '-' */ + {11, 11}, {11, 11}, /* '*' '%' */ + {14, 13}, /* '^' (right associative) */ + {11, 11}, {11, 11}, /* '/' '//' */ + {6, 6}, {4, 4}, {5, 5}, /* '&' '|' '~' */ + {7, 7}, {7, 7}, /* '<<' '>>' */ + {9, 8}, /* '..' (right associative) */ + {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */ + {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */ + {2, 2}, {1, 1} /* and, or */ }; -#define UNARY_PRIORITY 8 /* priority for unary operators */ +#define UNARY_PRIORITY 12 /* priority for unary operators */ /* ** subexpr -> (simpleexp | unop subexpr) { binop subexpr } -** where `binop' is any binary operator with a priority higher than `limit' +** where 'binop' is any binary operator with a priority higher than 'limit' */ -static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) { +static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { BinOpr op; UnOpr uop; enterlevel(ls); uop = getunopr(ls->t.token); if (uop != OPR_NOUNOPR) { + int line = ls->linenumber; luaX_next(ls); subexpr(ls, v, UNARY_PRIORITY); - luaK_prefix(ls->fs, uop, v); + luaK_prefix(ls->fs, uop, v, line); } else simpleexp(ls, v); - /* expand while operators have priorities higher than `limit' */ + /* expand while operators have priorities higher than 'limit' */ op = getbinopr(ls->t.token); while (op != OPR_NOBINOPR && priority[op].left > limit) { expdesc v2; BinOpr nextop; + int line = ls->linenumber; luaX_next(ls); luaK_infix(ls->fs, op, v); /* read sub-expression with higher priority */ nextop = subexpr(ls, &v2, priority[op].right); - luaK_posfix(ls->fs, op, v, &v2); + luaK_posfix(ls->fs, op, v, &v2, line); op = nextop; } leavelevel(ls); @@ -868,23 +1089,12 @@ static void expr (LexState *ls, expdesc *v) { */ -static int block_follow (int token) { - switch (token) { - case TK_ELSE: case TK_ELSEIF: case TK_END: - case TK_UNTIL: case TK_EOS: - return 1; - default: return 0; - } -} - - static void block (LexState *ls) { - /* block -> chunk */ + /* block -> statlist */ FuncState *fs = ls->fs; BlockCnt bl; enterblock(fs, &bl, 0); - chunk(ls); - lua_assert(bl.breaklist == NO_JUMP); + statlist(ls); leaveblock(fs); } @@ -900,29 +1110,34 @@ struct LHS_assign { /* -** check whether, in an assignment to a local variable, the local variable -** is needed in a previous assignment (to a table). If so, save original -** local value in a safe place and use this safe copy in the previous -** assignment. +** check whether, in an assignment to an upvalue/local variable, the +** upvalue/local variable is begin used in a previous assignment to a +** table. If so, save original upvalue/local value in a safe place and +** use this safe copy in the previous assignment. */ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { FuncState *fs = ls->fs; int extra = fs->freereg; /* eventual position to save local variable */ int conflict = 0; - for (; lh; lh = lh->prev) { - if (lh->v.k == VINDEXED) { - if (lh->v.u.s.info == v->u.s.info) { /* conflict? */ + for (; lh; lh = lh->prev) { /* check all previous assignments */ + if (lh->v.k == VINDEXED) { /* assigning to a table? */ + /* table is the upvalue/local being assigned now? */ + if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) { conflict = 1; - lh->v.u.s.info = extra; /* previous assignment will use safe copy */ + lh->v.u.ind.vt = VLOCAL; + lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ } - if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */ + /* index is the local being assigned? (index cannot be upvalue) */ + if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { conflict = 1; - lh->v.u.s.aux = extra; /* previous assignment will use safe copy */ + lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ } } } if (conflict) { - luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */ + /* copy upvalue/local value to a temporary (in position 'extra') */ + OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; + luaK_codeABC(fs, op, extra, v->u.info, 0); luaK_reserveregs(fs, 1); } } @@ -930,22 +1145,21 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { expdesc e; - check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, - "syntax error"); - if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ + check_condition(ls, vkisvar(lh->v.k), "syntax error"); + if (testnext(ls, ',')) { /* assignment -> ',' suffixedexp assignment */ struct LHS_assign nv; nv.prev = lh; - primaryexp(ls, &nv.v); - if (nv.v.k == VLOCAL) + suffixedexp(ls, &nv.v); + if (nv.v.k != VINDEXED) check_conflict(ls, lh, &nv.v); - luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, - "variables in assignment"); + checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS, + "C levels"); assignment(ls, &nv, nvars+1); } - else { /* assignment -> `=' explist1 */ + else { /* assignment -> '=' explist */ int nexps; checknext(ls, '='); - nexps = explist1(ls, &e); + nexps = explist(ls, &e); if (nexps != nvars) { adjust_assign(ls, nvars, nexps, &e); if (nexps > nvars) @@ -966,25 +1180,63 @@ static int cond (LexState *ls) { /* cond -> exp */ expdesc v; expr(ls, &v); /* read condition */ - if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */ + if (v.k == VNIL) v.k = VFALSE; /* 'falses' are all equal here */ luaK_goiftrue(ls->fs, &v); return v.f; } -static void breakstat (LexState *ls) { +static void gotostat (LexState *ls, int pc) { + int line = ls->linenumber; + TString *label; + int g; + if (testnext(ls, TK_GOTO)) + label = str_checkname(ls); + else { + luaX_next(ls); /* skip break */ + label = luaS_new(ls->L, "break"); + } + g = newlabelentry(ls, &ls->dyd->gt, label, line, pc); + findlabel(ls, g); /* close it if label already defined */ +} + + +/* check for repeated labels on the same block */ +static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) { + int i; + for (i = fs->bl->firstlabel; i < ll->n; i++) { + if (eqstr(label, ll->arr[i].name)) { + const char *msg = luaO_pushfstring(fs->ls->L, + "label '%s' already defined on line %d", + getstr(label), ll->arr[i].line); + semerror(fs->ls, msg); + } + } +} + + +/* skip no-op statements */ +static void skipnoopstat (LexState *ls) { + while (ls->t.token == ';' || ls->t.token == TK_DBCOLON) + statement(ls); +} + + +static void labelstat (LexState *ls, TString *label, int line) { + /* label -> '::' NAME '::' */ FuncState *fs = ls->fs; - BlockCnt *bl = fs->bl; - int upval = 0; - while (bl && !bl->isbreakable) { - upval |= bl->upval; - bl = bl->previous; + Labellist *ll = &ls->dyd->label; + int l; /* index of new label being created */ + checkrepeated(fs, ll, label); /* check for repeated labels */ + checknext(ls, TK_DBCOLON); /* skip double colon */ + /* create new entry for this label */ + l = newlabelentry(ls, ll, label, line, luaK_getlabel(fs)); + skipnoopstat(ls); /* skip other no-op statements */ + if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */ + /* assume that locals are already out of scope */ + ll->arr[l].nactvar = fs->bl->nactvar; } - if (!bl) - luaX_syntaxerror(ls, "no loop to break"); - if (upval) - luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); - luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); + findgotos(ls, &ll->arr[l]); } @@ -1000,7 +1252,7 @@ static void whilestat (LexState *ls, int line) { enterblock(fs, &bl, 1); checknext(ls, TK_DO); block(ls); - luaK_patchlist(fs, luaK_jump(fs), whileinit); + luaK_jumpto(fs, whileinit); check_match(ls, TK_END, TK_WHILE, line); leaveblock(fs); luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ @@ -1016,30 +1268,25 @@ static void repeatstat (LexState *ls, int line) { enterblock(fs, &bl1, 1); /* loop block */ enterblock(fs, &bl2, 0); /* scope block */ luaX_next(ls); /* skip REPEAT */ - chunk(ls); + statlist(ls); check_match(ls, TK_UNTIL, TK_REPEAT, line); condexit = cond(ls); /* read condition (inside scope block) */ - if (!bl2.upval) { /* no upvalues? */ - leaveblock(fs); /* finish scope */ - luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */ - } - else { /* complete semantics when there are upvalues */ - breakstat(ls); /* if condition then break */ - luaK_patchtohere(ls->fs, condexit); /* else... */ - leaveblock(fs); /* finish scope... */ - luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */ - } + if (bl2.upval) /* upvalues? */ + luaK_patchclose(fs, condexit, bl2.nactvar); + leaveblock(fs); /* finish scope */ + luaK_patchlist(fs, condexit, repeat_init); /* close the loop */ leaveblock(fs); /* finish loop */ } static int exp1 (LexState *ls) { expdesc e; - int k; + int reg; expr(ls, &e); - k = e.k; luaK_exp2nextreg(ls->fs, &e); - return k; + lua_assert(e.k == VNONRELOC); + reg = e.u.info; + return reg; } @@ -1057,10 +1304,15 @@ static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { block(ls); leaveblock(fs); /* end of scope for declared variables */ luaK_patchtohere(fs, prep); - endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : - luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); - luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ - luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1); + if (isnum) /* numeric for? */ + endfor = luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP); + else { /* generic for */ + luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars); + luaK_fixline(fs, line); + endfor = luaK_codeAsBx(fs, OP_TFORLOOP, base + 2, NO_JUMP); + } + luaK_patchlist(fs, endfor, prep + 1); + luaK_fixline(fs, line); } @@ -1068,10 +1320,10 @@ static void fornum (LexState *ls, TString *varname, int line) { /* fornum -> NAME = exp1,exp1[,exp1] forbody */ FuncState *fs = ls->fs; int base = fs->freereg; - new_localvarliteral(ls, "(for index)", 0); - new_localvarliteral(ls, "(for limit)", 1); - new_localvarliteral(ls, "(for step)", 2); - new_localvar(ls, varname, 3); + new_localvarliteral(ls, "(for index)"); + new_localvarliteral(ls, "(for limit)"); + new_localvarliteral(ls, "(for step)"); + new_localvar(ls, varname); checknext(ls, '='); exp1(ls); /* initial value */ checknext(ls, ','); @@ -1079,7 +1331,7 @@ static void fornum (LexState *ls, TString *varname, int line) { if (testnext(ls, ',')) exp1(ls); /* optional step */ else { /* default step = 1 */ - luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); + luaK_codek(fs, fs->freereg, luaK_intK(fs, 1)); luaK_reserveregs(fs, 1); } forbody(ls, base, line, 1, 1); @@ -1087,23 +1339,25 @@ static void fornum (LexState *ls, TString *varname, int line) { static void forlist (LexState *ls, TString *indexname) { - /* forlist -> NAME {,NAME} IN explist1 forbody */ + /* forlist -> NAME {,NAME} IN explist forbody */ FuncState *fs = ls->fs; expdesc e; - int nvars = 0; + int nvars = 4; /* gen, state, control, plus at least one declared var */ int line; int base = fs->freereg; /* create control variables */ - new_localvarliteral(ls, "(for generator)", nvars++); - new_localvarliteral(ls, "(for state)", nvars++); - new_localvarliteral(ls, "(for control)", nvars++); + new_localvarliteral(ls, "(for generator)"); + new_localvarliteral(ls, "(for state)"); + new_localvarliteral(ls, "(for control)"); /* create declared variables */ - new_localvar(ls, indexname, nvars++); - while (testnext(ls, ',')) - new_localvar(ls, str_checkname(ls), nvars++); + new_localvar(ls, indexname); + while (testnext(ls, ',')) { + new_localvar(ls, str_checkname(ls)); + nvars++; + } checknext(ls, TK_IN); line = ls->linenumber; - adjust_assign(ls, 3, explist1(ls, &e), &e); + adjust_assign(ls, 3, explist(ls, &e), &e); luaK_checkstack(fs, 3); /* extra space to call generator */ forbody(ls, base, line, nvars - 3, 0); } @@ -1115,77 +1369,89 @@ static void forstat (LexState *ls, int line) { TString *varname; BlockCnt bl; enterblock(fs, &bl, 1); /* scope for loop and control variables */ - luaX_next(ls); /* skip `for' */ + luaX_next(ls); /* skip 'for' */ varname = str_checkname(ls); /* first variable name */ switch (ls->t.token) { case '=': fornum(ls, varname, line); break; case ',': case TK_IN: forlist(ls, varname); break; - default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected"); + default: luaX_syntaxerror(ls, "'=' or 'in' expected"); } check_match(ls, TK_END, TK_FOR, line); - leaveblock(fs); /* loop scope (`break' jumps to this point) */ + leaveblock(fs); /* loop scope ('break' jumps to this point) */ } -static int test_then_block (LexState *ls) { +static void test_then_block (LexState *ls, int *escapelist) { /* test_then_block -> [IF | ELSEIF] cond THEN block */ - int condexit; + BlockCnt bl; + FuncState *fs = ls->fs; + expdesc v; + int jf; /* instruction to skip 'then' code (if condition is false) */ luaX_next(ls); /* skip IF or ELSEIF */ - condexit = cond(ls); + expr(ls, &v); /* read condition */ checknext(ls, TK_THEN); - block(ls); /* `then' part */ - return condexit; + if (ls->t.token == TK_GOTO || ls->t.token == TK_BREAK) { + luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */ + enterblock(fs, &bl, 0); /* must enter block before 'goto' */ + gotostat(ls, v.t); /* handle goto/break */ + skipnoopstat(ls); /* skip other no-op statements */ + if (block_follow(ls, 0)) { /* 'goto' is the entire block? */ + leaveblock(fs); + return; /* and that is it */ + } + else /* must skip over 'then' part if condition is false */ + jf = luaK_jump(fs); + } + else { /* regular case (not goto/break) */ + luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */ + enterblock(fs, &bl, 0); + jf = v.f; + } + statlist(ls); /* 'then' part */ + leaveblock(fs); + if (ls->t.token == TK_ELSE || + ls->t.token == TK_ELSEIF) /* followed by 'else'/'elseif'? */ + luaK_concat(fs, escapelist, luaK_jump(fs)); /* must jump over it */ + luaK_patchtohere(fs, jf); } static void ifstat (LexState *ls, int line) { /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ FuncState *fs = ls->fs; - int flist; - int escapelist = NO_JUMP; - flist = test_then_block(ls); /* IF cond THEN block */ - while (ls->t.token == TK_ELSEIF) { - luaK_concat(fs, &escapelist, luaK_jump(fs)); - luaK_patchtohere(fs, flist); - flist = test_then_block(ls); /* ELSEIF cond THEN block */ - } - if (ls->t.token == TK_ELSE) { - luaK_concat(fs, &escapelist, luaK_jump(fs)); - luaK_patchtohere(fs, flist); - luaX_next(ls); /* skip ELSE (after patch, for correct line info) */ - block(ls); /* `else' part */ - } - else - luaK_concat(fs, &escapelist, flist); - luaK_patchtohere(fs, escapelist); + int escapelist = NO_JUMP; /* exit list for finished parts */ + test_then_block(ls, &escapelist); /* IF cond THEN block */ + while (ls->t.token == TK_ELSEIF) + test_then_block(ls, &escapelist); /* ELSEIF cond THEN block */ + if (testnext(ls, TK_ELSE)) + block(ls); /* 'else' part */ check_match(ls, TK_END, TK_IF, line); + luaK_patchtohere(fs, escapelist); /* patch escape list to 'if' end */ } static void localfunc (LexState *ls) { - expdesc v, b; + expdesc b; FuncState *fs = ls->fs; - new_localvar(ls, str_checkname(ls), 0); - init_exp(&v, VLOCAL, fs->freereg); - luaK_reserveregs(fs, 1); - adjustlocalvars(ls, 1); - body(ls, &b, 0, ls->linenumber); - luaK_storevar(fs, &v, &b); + new_localvar(ls, str_checkname(ls)); /* new local variable */ + adjustlocalvars(ls, 1); /* enter its scope */ + body(ls, &b, 0, ls->linenumber); /* function created in next register */ /* debug information will only see the variable after this point! */ - getlocvar(fs, fs->nactvar - 1).startpc = fs->pc; + getlocvar(fs, b.u.info)->startpc = fs->pc; } static void localstat (LexState *ls) { - /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ + /* stat -> LOCAL NAME {',' NAME} ['=' explist] */ int nvars = 0; int nexps; expdesc e; do { - new_localvar(ls, str_checkname(ls), nvars++); + new_localvar(ls, str_checkname(ls)); + nvars++; } while (testnext(ls, ',')); if (testnext(ls, '=')) - nexps = explist1(ls, &e); + nexps = explist(ls, &e); else { e.k = VVOID; nexps = 0; @@ -1196,28 +1462,28 @@ static void localstat (LexState *ls) { static int funcname (LexState *ls, expdesc *v) { - /* funcname -> NAME {field} [`:' NAME] */ - int needself = 0; + /* funcname -> NAME {fieldsel} [':' NAME] */ + int ismethod = 0; singlevar(ls, v); while (ls->t.token == '.') - field(ls, v); + fieldsel(ls, v); if (ls->t.token == ':') { - needself = 1; - field(ls, v); + ismethod = 1; + fieldsel(ls, v); } - return needself; + return ismethod; } static void funcstat (LexState *ls, int line) { /* funcstat -> FUNCTION funcname body */ - int needself; + int ismethod; expdesc v, b; luaX_next(ls); /* skip FUNCTION */ - needself = funcname(ls, &v); - body(ls, &b, needself, line); + ismethod = funcname(ls, &v); + body(ls, &b, ismethod, line); luaK_storevar(ls->fs, &v, &b); - luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ + luaK_fixline(ls->fs, line); /* definition "happens" in the first line */ } @@ -1225,31 +1491,32 @@ static void exprstat (LexState *ls) { /* stat -> func | assignment */ FuncState *fs = ls->fs; struct LHS_assign v; - primaryexp(ls, &v.v); - if (v.v.k == VCALL) /* stat -> func */ - SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ - else { /* stat -> assignment */ + suffixedexp(ls, &v.v); + if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */ v.prev = NULL; assignment(ls, &v, 1); } + else { /* stat -> func */ + check_condition(ls, v.v.k == VCALL, "syntax error"); + SETARG_C(getinstruction(fs, &v.v), 1); /* call statement uses no results */ + } } static void retstat (LexState *ls) { - /* stat -> RETURN explist */ + /* stat -> RETURN [explist] [';'] */ FuncState *fs = ls->fs; expdesc e; int first, nret; /* registers with returned values */ - luaX_next(ls); /* skip RETURN */ - if (block_follow(ls->t.token) || ls->t.token == ';') + if (block_follow(ls, 1) || ls->t.token == ';') first = nret = 0; /* return no values */ else { - nret = explist1(ls, &e); /* optional return values */ + nret = explist(ls, &e); /* optional return values */ if (hasmultret(e.k)) { luaK_setmultret(fs, &e); if (e.k == VCALL && nret == 1) { /* tail call? */ - SET_OPCODE(getcode(fs,&e), OP_TAILCALL); - lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); + SET_OPCODE(getinstruction(fs,&e), OP_TAILCALL); + lua_assert(GETARG_A(getinstruction(fs,&e)) == fs->nactvar); } first = fs->nactvar; nret = LUA_MULTRET; /* return all values */ @@ -1258,44 +1525,50 @@ static void retstat (LexState *ls) { if (nret == 1) /* only one single value? */ first = luaK_exp2anyreg(fs, &e); else { - luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ - first = fs->nactvar; /* return all `active' values */ + luaK_exp2nextreg(fs, &e); /* values must go to the stack */ + first = fs->nactvar; /* return all active values */ lua_assert(nret == fs->freereg - first); } } } luaK_ret(fs, first, nret); + testnext(ls, ';'); /* skip optional semicolon */ } -static int statement (LexState *ls) { +static void statement (LexState *ls) { int line = ls->linenumber; /* may be needed for error messages */ + enterlevel(ls); switch (ls->t.token) { + case ';': { /* stat -> ';' (empty statement) */ + luaX_next(ls); /* skip ';' */ + break; + } case TK_IF: { /* stat -> ifstat */ ifstat(ls, line); - return 0; + break; } case TK_WHILE: { /* stat -> whilestat */ whilestat(ls, line); - return 0; + break; } case TK_DO: { /* stat -> DO block END */ luaX_next(ls); /* skip DO */ block(ls); check_match(ls, TK_END, TK_DO, line); - return 0; + break; } case TK_FOR: { /* stat -> forstat */ forstat(ls, line); - return 0; + break; } case TK_REPEAT: { /* stat -> repeatstat */ repeatstat(ls, line); - return 0; + break; } - case TK_FUNCTION: { - funcstat(ls, line); /* stat -> funcstat */ - return 0; + case TK_FUNCTION: { /* stat -> funcstat */ + funcstat(ls, line); + break; } case TK_LOCAL: { /* stat -> localstat */ luaX_next(ls); /* skip LOCAL */ @@ -1303,37 +1576,77 @@ static int statement (LexState *ls) { localfunc(ls); else localstat(ls); - return 0; + break; + } + case TK_DBCOLON: { /* stat -> label */ + luaX_next(ls); /* skip double colon */ + labelstat(ls, str_checkname(ls), line); + break; } case TK_RETURN: { /* stat -> retstat */ + luaX_next(ls); /* skip RETURN */ retstat(ls); - return 1; /* must be last statement */ + break; } - case TK_BREAK: { /* stat -> breakstat */ - luaX_next(ls); /* skip BREAK */ - breakstat(ls); - return 1; /* must be last statement */ + case TK_BREAK: /* stat -> breakstat */ + case TK_GOTO: { /* stat -> 'goto' NAME */ + gotostat(ls, luaK_jump(ls->fs)); + break; } - default: { + default: { /* stat -> func | assignment */ exprstat(ls); - return 0; /* to avoid warnings */ + break; } } + lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && + ls->fs->freereg >= ls->fs->nactvar); + ls->fs->freereg = ls->fs->nactvar; /* free registers */ + leavelevel(ls); } +/* }====================================================================== */ -static void chunk (LexState *ls) { - /* chunk -> { stat [`;'] } */ - int islast = 0; - enterlevel(ls); - while (!islast && !block_follow(ls->t.token)) { - islast = statement(ls); - testnext(ls, ';'); - lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && - ls->fs->freereg >= ls->fs->nactvar); - ls->fs->freereg = ls->fs->nactvar; /* free registers */ - } - leavelevel(ls); + +/* +** compiles the main function, which is a regular vararg function with an +** upvalue named LUA_ENV +*/ +static void mainfunc (LexState *ls, FuncState *fs) { + BlockCnt bl; + expdesc v; + open_func(ls, fs, &bl); + fs->f->is_vararg = 2; /* main function is always declared vararg */ + init_exp(&v, VLOCAL, 0); /* create and... */ + newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ + luaX_next(ls); /* read first token */ + statlist(ls); /* parse main body */ + check(ls, TK_EOS); + close_func(ls); +} + + +LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, + Dyndata *dyd, const char *name, int firstchar) { + LexState lexstate; + FuncState funcstate; + LClosure *cl = luaF_newLclosure(L, 1); /* create main closure */ + setclLvalue(L, L->top, cl); /* anchor it (to avoid being collected) */ + luaD_inctop(L); + lexstate.h = luaH_new(L); /* create table for scanner */ + sethvalue(L, L->top, lexstate.h); /* anchor it */ + luaD_inctop(L); + funcstate.f = cl->p = luaF_newproto(L); + funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ + lua_assert(iswhite(funcstate.f)); /* do not need barrier here */ + lexstate.buff = buff; + lexstate.dyd = dyd; + dyd->actvar.n = dyd->gt.n = dyd->label.n = 0; + luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar); + mainfunc(&lexstate, &funcstate); + lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); + /* all scopes should be correctly finished */ + lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); + L->top--; /* remove scanner's table */ + return cl; /* closure is on the stack, too */ } -/* }====================================================================== */ diff --git a/app/src/main/jni/lua/lparser.h b/app/src/main/jni/lua/lparser.h index 18836af..02e9b03 100644 --- a/app/src/main/jni/lua/lparser.h +++ b/app/src/main/jni/lua/lparser.h @@ -1,5 +1,5 @@ /* -** $Id: lparser.h,v 1.57.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lparser.h,v 1.76 2015/12/30 18:16:13 roberto Exp $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -13,70 +13,121 @@ /* -** Expression descriptor +** Expression and variable descriptor. +** Code generation for variables and expressions can be delayed to allow +** optimizations; An 'expdesc' structure describes a potentially-delayed +** variable/expression. It has a description of its "main" value plus a +** list of conditional jumps that can also produce its value (generated +** by short-circuit operators 'and'/'or'). */ +/* kinds of variables/expressions */ typedef enum { - VVOID, /* no value */ - VNIL, - VTRUE, - VFALSE, - VK, /* info = index of constant in `k' */ - VKNUM, /* nval = numerical value */ - VLOCAL, /* info = local register */ - VUPVAL, /* info = index of upvalue in `upvalues' */ - VGLOBAL, /* info = index of table; aux = index of global name in `k' */ - VINDEXED, /* info = table register; aux = index register (or `k') */ - VJMP, /* info = instruction pc */ - VRELOCABLE, /* info = instruction pc */ - VNONRELOC, /* info = result register */ - VCALL, /* info = instruction pc */ - VVARARG /* info = instruction pc */ + VVOID, /* when 'expdesc' describes the last expression a list, + this kind means an empty list (so, no expression) */ + VNIL, /* constant nil */ + VTRUE, /* constant true */ + VFALSE, /* constant false */ + VK, /* constant in 'k'; info = index of constant in 'k' */ + VKFLT, /* floating constant; nval = numerical float value */ + VKINT, /* integer constant; nval = numerical integer value */ + VNONRELOC, /* expression has its value in a fixed register; + info = result register */ + VLOCAL, /* local variable; info = local register */ + VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */ + VINDEXED, /* indexed variable; + ind.vt = whether 't' is register or upvalue; + ind.t = table register or upvalue; + ind.idx = key's R/K index */ + VJMP, /* expression is a test/comparison; + info = pc of corresponding jump instruction */ + VRELOCABLE, /* expression can put result in any register; + info = instruction pc */ + VCALL, /* expression is a function call; info = instruction pc */ + VVARARG /* vararg expression; info = instruction pc */ } expkind; + +#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED) +#define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL) + typedef struct expdesc { expkind k; union { - struct { int info, aux; } s; - lua_Number nval; + lua_Integer ival; /* for VKINT */ + lua_Number nval; /* for VKFLT */ + int info; /* for generic use */ + struct { /* for indexed variables (VINDEXED) */ + short idx; /* index (R/K) */ + lu_byte t; /* table (register or upvalue) */ + lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */ + } ind; } u; - int t; /* patch list of `exit when true' */ - int f; /* patch list of `exit when false' */ + int t; /* patch list of 'exit when true' */ + int f; /* patch list of 'exit when false' */ } expdesc; -typedef struct upvaldesc { - lu_byte k; - lu_byte info; -} upvaldesc; +/* description of active local variable */ +typedef struct Vardesc { + short idx; /* variable index in stack */ +} Vardesc; + + +/* description of pending goto statements and label statements */ +typedef struct Labeldesc { + TString *name; /* label identifier */ + int pc; /* position in code */ + int line; /* line where it appeared */ + lu_byte nactvar; /* local level where it appears in current block */ +} Labeldesc; + + +/* list of labels or gotos */ +typedef struct Labellist { + Labeldesc *arr; /* array */ + int n; /* number of entries in use */ + int size; /* array size */ +} Labellist; + + +/* dynamic structures used by the parser */ +typedef struct Dyndata { + struct { /* list of active local variables */ + Vardesc *arr; + int n; + int size; + } actvar; + Labellist gt; /* list of pending gotos */ + Labellist label; /* list of active labels */ +} Dyndata; +/* control of blocks */ struct BlockCnt; /* defined in lparser.c */ /* state needed to generate code for a given function */ typedef struct FuncState { Proto *f; /* current function header */ - Table *h; /* table to find (and reuse) elements in `k' */ struct FuncState *prev; /* enclosing function */ struct LexState *ls; /* lexical state */ - struct lua_State *L; /* copy of the Lua state */ struct BlockCnt *bl; /* chain of current blocks */ - int pc; /* next position to code (equivalent to `ncode') */ - int lasttarget; /* `pc' of last `jump target' */ - int jpc; /* list of pending jumps to `pc' */ - int freereg; /* first free register */ - int nk; /* number of elements in `k' */ - int np; /* number of elements in `p' */ - short nlocvars; /* number of elements in `locvars' */ + int pc; /* next position to code (equivalent to 'ncode') */ + int lasttarget; /* 'label' of last 'jump label' */ + int jpc; /* list of pending jumps to 'pc' */ + int nk; /* number of elements in 'k' */ + int np; /* number of elements in 'p' */ + int firstlocal; /* index of first local var (in Dyndata array) */ + short nlocvars; /* number of elements in 'f->locvars' */ lu_byte nactvar; /* number of active local variables */ - upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */ - unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */ + lu_byte nups; /* number of upvalues */ + lu_byte freereg; /* first free register */ } FuncState; -LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, - const char *name); +LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, + Dyndata *dyd, const char *name, int firstchar); #endif diff --git a/app/src/main/jni/lua/lprefix.h b/app/src/main/jni/lua/lprefix.h new file mode 100644 index 0000000..02daa83 --- /dev/null +++ b/app/src/main/jni/lua/lprefix.h @@ -0,0 +1,45 @@ +/* +** $Id: lprefix.h,v 1.2 2014/12/29 16:54:13 roberto Exp $ +** Definitions for Lua code that must come before any other header file +** See Copyright Notice in lua.h +*/ + +#ifndef lprefix_h +#define lprefix_h + + +/* +** Allows POSIX/XSI stuff +*/ +#if !defined(LUA_USE_C89) /* { */ + +#if !defined(_XOPEN_SOURCE) +#define _XOPEN_SOURCE 600 +#elif _XOPEN_SOURCE == 0 +#undef _XOPEN_SOURCE /* use -D_XOPEN_SOURCE=0 to undefine it */ +#endif + +/* +** Allows manipulation of large files in gcc and some other compilers +*/ +#if !defined(LUA_32BITS) && !defined(_FILE_OFFSET_BITS) +#define _LARGEFILE_SOURCE 1 +#define _FILE_OFFSET_BITS 64 +#endif + +#endif /* } */ + + +/* +** Windows stuff +*/ +#if defined(_WIN32) /* { */ + +#if !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS /* avoid warnings about ISO C functions */ +#endif + +#endif /* } */ + +#endif + diff --git a/app/src/main/jni/lua/lstate.c b/app/src/main/jni/lua/lstate.c index 4313b83..9194ac3 100644 --- a/app/src/main/jni/lua/lstate.c +++ b/app/src/main/jni/lua/lstate.c @@ -1,17 +1,21 @@ /* -** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $ +** $Id: lstate.c,v 2.133 2015/11/13 12:16:51 roberto Exp $ ** Global State ** See Copyright Notice in lua.h */ - -#include - #define lstate_c #define LUA_CORE +#include "lprefix.h" + + +#include +#include + #include "lua.h" +#include "lapi.h" #include "ldebug.h" #include "ldo.h" #include "lfunc.h" @@ -24,119 +28,267 @@ #include "ltm.h" -#define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) -#define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE) -#define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE)) +#if !defined(LUAI_GCPAUSE) +#define LUAI_GCPAUSE 200 /* 200% */ +#endif + +#if !defined(LUAI_GCMUL) +#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ +#endif + + +/* +** a macro to help the creation of a unique random seed when a state is +** created; the seed is used to randomize hashes. +*/ +#if !defined(luai_makeseed) +#include +#define luai_makeseed() cast(unsigned int, time(NULL)) +#endif + + + +/* +** thread state + extra space +*/ +typedef struct LX { + lu_byte extra_[LUA_EXTRASPACE]; + lua_State l; +} LX; /* ** Main thread combines a thread state and the global state */ typedef struct LG { - lua_State l; + LX l; global_State g; } LG; - + + + +#define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l))) + + +/* +** Compute an initial seed as random as possible. Rely on Address Space +** Layout Randomization (if present) to increase randomness.. +*/ +#define addbuff(b,p,e) \ + { size_t t = cast(size_t, e); \ + memcpy(b + p, &t, sizeof(t)); p += sizeof(t); } + +static unsigned int makeseed (lua_State *L) { + char buff[4 * sizeof(size_t)]; + unsigned int h = luai_makeseed(); + int p = 0; + addbuff(buff, p, L); /* heap variable */ + addbuff(buff, p, &h); /* local variable */ + addbuff(buff, p, luaO_nilobject); /* global variable */ + addbuff(buff, p, &lua_newstate); /* public function */ + lua_assert(p == sizeof(buff)); + return luaS_hash(buff, p, h); +} + + +/* +** set GCdebt to a new value keeping the value (totalbytes + GCdebt) +** invariant (and avoiding underflows in 'totalbytes') +*/ +void luaE_setdebt (global_State *g, l_mem debt) { + l_mem tb = gettotalbytes(g); + lua_assert(tb > 0); + if (debt < tb - MAX_LMEM) + debt = tb - MAX_LMEM; /* will make 'totalbytes == MAX_LMEM' */ + g->totalbytes = tb - debt; + g->GCdebt = debt; +} + + +CallInfo *luaE_extendCI (lua_State *L) { + CallInfo *ci = luaM_new(L, CallInfo); + lua_assert(L->ci->next == NULL); + L->ci->next = ci; + ci->previous = L->ci; + ci->next = NULL; + L->nci++; + return ci; +} + + +/* +** free all CallInfo structures not in use by a thread +*/ +void luaE_freeCI (lua_State *L) { + CallInfo *ci = L->ci; + CallInfo *next = ci->next; + ci->next = NULL; + while ((ci = next) != NULL) { + next = ci->next; + luaM_free(L, ci); + L->nci--; + } +} + + +/* +** free half of the CallInfo structures not in use by a thread +*/ +void luaE_shrinkCI (lua_State *L) { + CallInfo *ci = L->ci; + CallInfo *next2; /* next's next */ + /* while there are two nexts */ + while (ci->next != NULL && (next2 = ci->next->next) != NULL) { + luaM_free(L, ci->next); /* free next */ + L->nci--; + ci->next = next2; /* remove 'next' from the list */ + next2->previous = ci; + ci = next2; /* keep next's next */ + } +} static void stack_init (lua_State *L1, lua_State *L) { - /* initialize CallInfo array */ - L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); - L1->ci = L1->base_ci; - L1->size_ci = BASIC_CI_SIZE; - L1->end_ci = L1->base_ci + L1->size_ci - 1; + int i; CallInfo *ci; /* initialize stack array */ - L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); - L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; + L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, TValue); + L1->stacksize = BASIC_STACK_SIZE; + for (i = 0; i < BASIC_STACK_SIZE; i++) + setnilvalue(L1->stack + i); /* erase new stack */ L1->top = L1->stack; - L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; + L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK; /* initialize first ci */ - L1->ci->func = L1->top; - setnilvalue(L1->top++); /* `function' entry for this `ci' */ - L1->base = L1->ci->base = L1->top; - L1->ci->top = L1->top + LUA_MINSTACK; + ci = &L1->base_ci; + ci->next = ci->previous = NULL; + ci->callstatus = 0; + ci->func = L1->top; + setnilvalue(L1->top++); /* 'function' entry for this 'ci' */ + ci->top = L1->top + LUA_MINSTACK; + L1->ci = ci; +} + + +static void freestack (lua_State *L) { + if (L->stack == NULL) + return; /* stack not completely built yet */ + L->ci = &L->base_ci; /* free the entire 'ci' list */ + luaE_freeCI(L); + lua_assert(L->nci == 0); + luaM_freearray(L, L->stack, L->stacksize); /* free stack array */ } -static void freestack (lua_State *L, lua_State *L1) { - luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo); - luaM_freearray(L, L1->stack, L1->stacksize, TValue); +/* +** Create registry table and its predefined values +*/ +static void init_registry (lua_State *L, global_State *g) { + TValue temp; + /* create registry */ + Table *registry = luaH_new(L); + sethvalue(L, &g->l_registry, registry); + luaH_resize(L, registry, LUA_RIDX_LAST, 0); + /* registry[LUA_RIDX_MAINTHREAD] = L */ + setthvalue(L, &temp, L); /* temp = L */ + luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp); + /* registry[LUA_RIDX_GLOBALS] = table of globals */ + sethvalue(L, &temp, luaH_new(L)); /* temp = new table (global table) */ + luaH_setint(L, registry, LUA_RIDX_GLOBALS, &temp); } /* -** open parts that may cause memory-allocation errors +** open parts of the state that may cause memory-allocation errors. +** ('g->version' != NULL flags that the state was completely build) */ static void f_luaopen (lua_State *L, void *ud) { global_State *g = G(L); UNUSED(ud); stack_init(L, L); /* init stack */ - sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */ - sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */ - luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ + init_registry(L, g); + luaS_init(L); luaT_init(L); luaX_init(L); - luaS_fix(luaS_newliteral(L, MEMERRMSG)); - g->GCthreshold = 4*g->totalbytes; + g->gcrunning = 1; /* allow gc */ + g->version = lua_version(NULL); + luai_userstateopen(L); } -static void preinit_state (lua_State *L, global_State *g) { +/* +** preinitialize a thread with consistent values without allocating +** any memory (to avoid errors) +*/ +static void preinit_thread (lua_State *L, global_State *g) { G(L) = g; L->stack = NULL; + L->ci = NULL; + L->nci = 0; L->stacksize = 0; + L->twups = L; /* thread has no upvalues */ L->errorJmp = NULL; + L->nCcalls = 0; L->hook = NULL; L->hookmask = 0; L->basehookcount = 0; L->allowhook = 1; resethookcount(L); L->openupval = NULL; - L->size_ci = 0; - L->nCcalls = L->baseCcalls = 0; - L->status = 0; - L->base_ci = L->ci = NULL; - L->savedpc = NULL; + L->nny = 1; + L->status = LUA_OK; L->errfunc = 0; - setnilvalue(gt(L)); } static void close_state (lua_State *L) { global_State *g = G(L); luaF_close(L, L->stack); /* close all upvalues for this thread */ - luaC_freeall(L); /* collect all objects */ - lua_assert(g->rootgc == obj2gco(L)); - lua_assert(g->strt.nuse == 0); - luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); - luaZ_freebuffer(L, &g->buff); - freestack(L, L); - lua_assert(g->totalbytes == sizeof(LG)); - (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0); + luaC_freeallobjects(L); /* collect all objects */ + if (g->version) /* closing a fully built state? */ + luai_userstateclose(L); + luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); + freestack(L); + lua_assert(gettotalbytes(g) == sizeof(LG)); + (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ } -lua_State *luaE_newthread (lua_State *L) { - lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); - luaC_link(L, obj2gco(L1), LUA_TTHREAD); - preinit_state(L1, G(L)); - stack_init(L1, L); /* init stack */ - setobj2n(L, gt(L1), gt(L)); /* share table of globals */ +LUA_API lua_State *lua_newthread (lua_State *L) { + global_State *g = G(L); + lua_State *L1; + lua_lock(L); + luaC_checkGC(L); + /* create new thread */ + L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l; + L1->marked = luaC_white(g); + L1->tt = LUA_TTHREAD; + /* link it on list 'allgc' */ + L1->next = g->allgc; + g->allgc = obj2gco(L1); + /* anchor it on L stack */ + setthvalue(L, L->top, L1); + api_incr_top(L); + preinit_thread(L1, g); L1->hookmask = L->hookmask; L1->basehookcount = L->basehookcount; L1->hook = L->hook; resethookcount(L1); - lua_assert(iswhite(obj2gco(L1))); + /* initialize L1 extra space */ + memcpy(lua_getextraspace(L1), lua_getextraspace(g->mainthread), + LUA_EXTRASPACE); + luai_userstatethread(L, L1); + stack_init(L1, L); /* init stack */ + lua_unlock(L); return L1; } void luaE_freethread (lua_State *L, lua_State *L1) { + LX *l = fromstate(L1); luaF_close(L1, L1->stack); /* close all upvalues for this thread */ lua_assert(L1->openupval == NULL); - luai_userstatefree(L1); - freestack(L, L1); - luaM_freemem(L, fromstate(L1), state_size(lua_State)); + luai_userstatefree(L, L1); + freestack(L1); + luaM_free(L, l); } @@ -144,71 +296,52 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { int i; lua_State *L; global_State *g; - void *l = (*f)(ud, NULL, 0, state_size(LG)); + LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG))); if (l == NULL) return NULL; - L = tostate(l); - g = &((LG *)L)->g; + L = &l->l.l; + g = &l->g; L->next = NULL; L->tt = LUA_TTHREAD; - g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); + g->currentwhite = bitmask(WHITE0BIT); L->marked = luaC_white(g); - set2bits(L->marked, FIXEDBIT, SFIXEDBIT); - preinit_state(L, g); + preinit_thread(L, g); g->frealloc = f; g->ud = ud; g->mainthread = L; - g->uvhead.u.l.prev = &g->uvhead; - g->uvhead.u.l.next = &g->uvhead; - g->GCthreshold = 0; /* mark it as unfinished state */ - g->strt.size = 0; - g->strt.nuse = 0; + g->seed = makeseed(L); + g->gcrunning = 0; /* no GC while building state */ + g->GCestimate = 0; + g->strt.size = g->strt.nuse = 0; g->strt.hash = NULL; - setnilvalue(registry(L)); - luaZ_initbuffer(L, &g->buff); + setnilvalue(&g->l_registry); g->panic = NULL; + g->version = NULL; g->gcstate = GCSpause; - g->rootgc = obj2gco(L); - g->sweepstrgc = 0; - g->sweepgc = &g->rootgc; - g->gray = NULL; - g->grayagain = NULL; - g->weak = NULL; - g->tmudata = NULL; + g->gckind = KGC_NORMAL; + g->allgc = g->finobj = g->tobefnz = g->fixedgc = NULL; + g->sweepgc = NULL; + g->gray = g->grayagain = NULL; + g->weak = g->ephemeron = g->allweak = NULL; + g->twups = NULL; g->totalbytes = sizeof(LG); + g->GCdebt = 0; + g->gcfinnum = 0; g->gcpause = LUAI_GCPAUSE; g->gcstepmul = LUAI_GCMUL; - g->gcdept = 0; - for (i=0; imt[i] = NULL; - if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { + for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; + if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { /* memory allocation error: free partial state */ close_state(L); L = NULL; } - else - luai_userstateopen(L); return L; } -static void callallgcTM (lua_State *L, void *ud) { - UNUSED(ud); - luaC_callGCTM(L); /* call GC metamethods for all udata */ -} - - LUA_API void lua_close (lua_State *L) { L = G(L)->mainthread; /* only the main thread can be closed */ lua_lock(L); - luaF_close(L, L->stack); /* close all upvalues for this thread */ - luaC_separateudata(L, 1); /* separate udata that have GC metamethods */ - L->errfunc = 0; /* no error function during GC metamethods */ - do { /* repeat until no more errors */ - L->ci = L->base_ci; - L->base = L->top = L->ci->base; - L->nCcalls = L->baseCcalls = 0; - } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0); - lua_assert(G(L)->tmudata == NULL); - luai_userstateclose(L); close_state(L); } + diff --git a/app/src/main/jni/lua/lstate.h b/app/src/main/jni/lua/lstate.h index 3bc575b..b3033be 100644 --- a/app/src/main/jni/lua/lstate.h +++ b/app/src/main/jni/lua/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $ +** $Id: lstate.h,v 2.130 2015/12/16 16:39:38 roberto Exp $ ** Global State ** See Copyright Notice in lua.h */ @@ -14,116 +14,172 @@ #include "lzio.h" +/* -struct lua_longjmp; /* defined in ldo.c */ +** Some notes about garbage-collected objects: All objects in Lua must +** be kept somehow accessible until being freed, so all objects always +** belong to one (and only one) of these lists, using field 'next' of +** the 'CommonHeader' for the link: +** +** 'allgc': all objects not marked for finalization; +** 'finobj': all objects marked for finalization; +** 'tobefnz': all objects ready to be finalized; +** 'fixedgc': all objects that are not to be collected (currently +** only small strings, such as reserved words). +*/ -/* table of globals */ -#define gt(L) (&L->l_gt) -/* registry */ -#define registry(L) (&G(L)->l_registry) +struct lua_longjmp; /* defined in ldo.c */ + + +/* +** Atomic type (relative to signals) to better ensure that 'lua_sethook' +** is thread safe +*/ +#if !defined(l_signalT) +#include +#define l_signalT sig_atomic_t +#endif /* extra stack space to handle TM calls and some other extras */ #define EXTRA_STACK 5 -#define BASIC_CI_SIZE 8 - #define BASIC_STACK_SIZE (2*LUA_MINSTACK) +/* kinds of Garbage Collection */ +#define KGC_NORMAL 0 +#define KGC_EMERGENCY 1 /* gc was forced by an allocation failure */ + typedef struct stringtable { - GCObject **hash; - lu_int32 nuse; /* number of elements */ + TString **hash; + int nuse; /* number of elements */ int size; } stringtable; /* -** informations about a call +** Information about a call. +** When a thread yields, 'func' is adjusted to pretend that the +** top function has only the yielded values in its stack; in that +** case, the actual 'func' value is saved in field 'extra'. +** When a function calls another with a continuation, 'extra' keeps +** the function index so that, in case of errors, the continuation +** function can be called with the correct top. */ typedef struct CallInfo { - StkId base; /* base for this function */ StkId func; /* function index in the stack */ StkId top; /* top for this function */ - const Instruction *savedpc; - int nresults; /* expected number of results from this function */ - int tailcalls; /* number of tail calls lost under this entry */ + struct CallInfo *previous, *next; /* dynamic call link */ + union { + struct { /* only for Lua functions */ + StkId base; /* base for this function */ + const Instruction *savedpc; + } l; + struct { /* only for C functions */ + lua_KFunction k; /* continuation in case of yields */ + ptrdiff_t old_errfunc; + lua_KContext ctx; /* context info. in case of yields */ + } c; + } u; + ptrdiff_t extra; + short nresults; /* expected number of results from this function */ + lu_byte callstatus; } CallInfo; +/* +** Bits in CallInfo status +*/ +#define CIST_OAH (1<<0) /* original value of 'allowhook' */ +#define CIST_LUA (1<<1) /* call is running a Lua function */ +#define CIST_HOOKED (1<<2) /* call is running a debug hook */ +#define CIST_FRESH (1<<3) /* call is running on a fresh invocation + of luaV_execute */ +#define CIST_YPCALL (1<<4) /* call is a yieldable protected call */ +#define CIST_TAIL (1<<5) /* call was tail called */ +#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */ +#define CIST_LEQ (1<<7) /* using __lt for __le */ + +#define isLua(ci) ((ci)->callstatus & CIST_LUA) -#define curr_func(L) (clvalue(L->ci->func)) -#define ci_func(ci) (clvalue((ci)->func)) -#define f_isLua(ci) (!ci_func(ci)->c.isC) -#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci)) +/* assume that CIST_OAH has offset 0 and that 'v' is strictly 0/1 */ +#define setoah(st,v) ((st) = ((st) & ~CIST_OAH) | (v)) +#define getoah(st) ((st) & CIST_OAH) /* -** `global state', shared by all threads of this state +** 'global state', shared by all threads of this state */ typedef struct global_State { - stringtable strt; /* hash table for strings */ lua_Alloc frealloc; /* function to reallocate memory */ - void *ud; /* auxiliary data to `frealloc' */ + void *ud; /* auxiliary data to 'frealloc' */ + l_mem totalbytes; /* number of bytes currently allocated - GCdebt */ + l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ + lu_mem GCmemtrav; /* memory traversed by the GC */ + lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ + stringtable strt; /* hash table for strings */ + TValue l_registry; + unsigned int seed; /* randomized seed for hashes */ lu_byte currentwhite; lu_byte gcstate; /* state of garbage collector */ - int sweepstrgc; /* position of sweep in `strt' */ - GCObject *rootgc; /* list of all collectable objects */ - GCObject **sweepgc; /* position of sweep in `rootgc' */ + lu_byte gckind; /* kind of GC running */ + lu_byte gcrunning; /* true if GC is running */ + GCObject *allgc; /* list of all collectable objects */ + GCObject **sweepgc; /* current position of sweep in list */ + GCObject *finobj; /* list of collectable objects with finalizers */ GCObject *gray; /* list of gray objects */ GCObject *grayagain; /* list of objects to be traversed atomically */ - GCObject *weak; /* list of weak tables (to be cleared) */ - GCObject *tmudata; /* last element of list of userdata to be GC */ - Mbuffer buff; /* temporary buffer for string concatentation */ - lu_mem GCthreshold; - lu_mem totalbytes; /* number of bytes currently allocated */ - lu_mem estimate; /* an estimate of number of bytes actually in use */ - lu_mem gcdept; /* how much GC is `behind schedule' */ + GCObject *weak; /* list of tables with weak values */ + GCObject *ephemeron; /* list of ephemeron tables (weak keys) */ + GCObject *allweak; /* list of all-weak tables */ + GCObject *tobefnz; /* list of userdata to be GC */ + GCObject *fixedgc; /* list of objects not to be collected */ + struct lua_State *twups; /* list of threads with open upvalues */ + unsigned int gcfinnum; /* number of finalizers to call in each GC step */ int gcpause; /* size of pause between successive GCs */ - int gcstepmul; /* GC `granularity' */ + int gcstepmul; /* GC 'granularity' */ lua_CFunction panic; /* to be called in unprotected errors */ - TValue l_registry; struct lua_State *mainthread; - UpVal uvhead; /* head of double-linked list of all open upvalues */ - struct Table *mt[NUM_TAGS]; /* metatables for basic types */ + const lua_Number *version; /* pointer to version number */ + TString *memerrmsg; /* memory-error message */ TString *tmname[TM_N]; /* array with tag-method names */ + struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */ + TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */ } global_State; /* -** `per thread' state +** 'per thread' state */ struct lua_State { CommonHeader; + unsigned short nci; /* number of items in 'ci' list */ lu_byte status; StkId top; /* first free slot in the stack */ - StkId base; /* base of current function */ global_State *l_G; CallInfo *ci; /* call info for current function */ - const Instruction *savedpc; /* `savedpc' of current function */ + const Instruction *oldpc; /* last pc traced */ StkId stack_last; /* last free slot in the stack */ StkId stack; /* stack base */ - CallInfo *end_ci; /* points after end of ci array*/ - CallInfo *base_ci; /* array of CallInfo's */ - int stacksize; - int size_ci; /* size of array `base_ci' */ - unsigned short nCcalls; /* number of nested C calls */ - unsigned short baseCcalls; /* nested C calls when resuming coroutine */ - lu_byte hookmask; - lu_byte allowhook; - int basehookcount; - int hookcount; - lua_Hook hook; - TValue l_gt; /* table of globals */ - TValue env; /* temporary place for environments */ - GCObject *openupval; /* list of open upvalues in this stack */ + UpVal *openupval; /* list of open upvalues in this stack */ GCObject *gclist; + struct lua_State *twups; /* list of threads with open upvalues */ struct lua_longjmp *errorJmp; /* current error recover point */ + CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ + volatile lua_Hook hook; ptrdiff_t errfunc; /* current error handling function (stack index) */ + int stacksize; + int basehookcount; + int hookcount; + unsigned short nny; /* number of non-yieldable calls in stack */ + unsigned short nCcalls; /* number of nested C calls */ + l_signalT hookmask; + lu_byte allowhook; }; @@ -131,39 +187,48 @@ struct lua_State { /* -** Union of all collectable objects +** Union of all collectable objects (only for conversions) */ -union GCObject { - GCheader gch; - union TString ts; - union Udata u; +union GCUnion { + GCObject gc; /* common header */ + struct TString ts; + struct Udata u; union Closure cl; struct Table h; struct Proto p; - struct UpVal uv; struct lua_State th; /* thread */ }; +#define cast_u(o) cast(union GCUnion *, (o)) + /* macros to convert a GCObject into a specific value */ -#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) -#define gco2ts(o) (&rawgco2ts(o)->tsv) -#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) -#define gco2u(o) (&rawgco2u(o)->uv) -#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl)) -#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) -#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) -#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) -#define ngcotouv(o) \ - check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv)) -#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) - -/* macro to convert any Lua object into a GCObject */ -#define obj2gco(v) (cast(GCObject *, (v))) - - -LUAI_FUNC lua_State *luaE_newthread (lua_State *L); +#define gco2ts(o) \ + check_exp(novariant((o)->tt) == LUA_TSTRING, &((cast_u(o))->ts)) +#define gco2u(o) check_exp((o)->tt == LUA_TUSERDATA, &((cast_u(o))->u)) +#define gco2lcl(o) check_exp((o)->tt == LUA_TLCL, &((cast_u(o))->cl.l)) +#define gco2ccl(o) check_exp((o)->tt == LUA_TCCL, &((cast_u(o))->cl.c)) +#define gco2cl(o) \ + check_exp(novariant((o)->tt) == LUA_TFUNCTION, &((cast_u(o))->cl)) +#define gco2t(o) check_exp((o)->tt == LUA_TTABLE, &((cast_u(o))->h)) +#define gco2p(o) check_exp((o)->tt == LUA_TPROTO, &((cast_u(o))->p)) +#define gco2th(o) check_exp((o)->tt == LUA_TTHREAD, &((cast_u(o))->th)) + + +/* macro to convert a Lua object into a GCObject */ +#define obj2gco(v) \ + check_exp(novariant((v)->tt) < LUA_TDEADKEY, (&(cast_u(v)->gc))) + + +/* actual number of total bytes allocated */ +#define gettotalbytes(g) cast(lu_mem, (g)->totalbytes + (g)->GCdebt) + +LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt); LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); +LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L); +LUAI_FUNC void luaE_freeCI (lua_State *L); +LUAI_FUNC void luaE_shrinkCI (lua_State *L); + #endif diff --git a/app/src/main/jni/lua/lstring.c b/app/src/main/jni/lua/lstring.c index 4911315..9351766 100644 --- a/app/src/main/jni/lua/lstring.c +++ b/app/src/main/jni/lua/lstring.c @@ -1,111 +1,248 @@ /* -** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lstring.c,v 2.56 2015/11/23 11:32:51 roberto Exp $ ** String table (keeps all strings handled by Lua) ** See Copyright Notice in lua.h */ - -#include - #define lstring_c #define LUA_CORE +#include "lprefix.h" + + +#include + #include "lua.h" +#include "ldebug.h" +#include "ldo.h" #include "lmem.h" #include "lobject.h" #include "lstate.h" #include "lstring.h" +#define MEMERRMSG "not enough memory" + + +/* +** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to +** compute its hash +*/ +#if !defined(LUAI_HASHLIMIT) +#define LUAI_HASHLIMIT 5 +#endif + + +/* +** equality for long strings +*/ +int luaS_eqlngstr (TString *a, TString *b) { + size_t len = a->u.lnglen; + lua_assert(a->tt == LUA_TLNGSTR && b->tt == LUA_TLNGSTR); + return (a == b) || /* same instance or... */ + ((len == b->u.lnglen) && /* equal length and ... */ + (memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */ +} + + +unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) { + unsigned int h = seed ^ cast(unsigned int, l); + size_t step = (l >> LUAI_HASHLIMIT) + 1; + for (; l >= step; l -= step) + h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1])); + return h; +} + + +unsigned int luaS_hashlongstr (TString *ts) { + lua_assert(ts->tt == LUA_TLNGSTR); + if (ts->extra == 0) { /* no hash? */ + ts->hash = luaS_hash(getstr(ts), ts->u.lnglen, ts->hash); + ts->extra = 1; /* now it has its hash */ + } + return ts->hash; +} + +/* +** resizes the string table +*/ void luaS_resize (lua_State *L, int newsize) { - GCObject **newhash; - stringtable *tb; int i; - if (G(L)->gcstate == GCSsweepstring) - return; /* cannot resize during GC traverse */ - newhash = luaM_newvector(L, newsize, GCObject *); - tb = &G(L)->strt; - for (i=0; isize; i++) { - GCObject *p = tb->hash[i]; + stringtable *tb = &G(L)->strt; + if (newsize > tb->size) { /* grow table if needed */ + luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *); + for (i = tb->size; i < newsize; i++) + tb->hash[i] = NULL; + } + for (i = 0; i < tb->size; i++) { /* rehash */ + TString *p = tb->hash[i]; + tb->hash[i] = NULL; while (p) { /* for each node in the list */ - GCObject *next = p->gch.next; /* save next */ - unsigned int h = gco2ts(p)->hash; - int h1 = lmod(h, newsize); /* new position */ - lua_assert(cast_int(h%newsize) == lmod(h, newsize)); - p->gch.next = newhash[h1]; /* chain it */ - newhash[h1] = p; - p = next; + TString *hnext = p->u.hnext; /* save next */ + unsigned int h = lmod(p->hash, newsize); /* new position */ + p->u.hnext = tb->hash[h]; /* chain it */ + tb->hash[h] = p; + p = hnext; } } - luaM_freearray(L, tb->hash, tb->size, TString *); + if (newsize < tb->size) { /* shrink table if needed */ + /* vanishing slice should be empty */ + lua_assert(tb->hash[newsize] == NULL && tb->hash[tb->size - 1] == NULL); + luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *); + } tb->size = newsize; - tb->hash = newhash; } -static TString *newlstr (lua_State *L, const char *str, size_t l, - unsigned int h) { +/* +** Clear API string cache. (Entries cannot be empty, so fill them with +** a non-collectable string.) +*/ +void luaS_clearcache (global_State *g) { + int i, j; + for (i = 0; i < STRCACHE_N; i++) + for (j = 0; j < STRCACHE_M; j++) { + if (iswhite(g->strcache[i][j])) /* will entry be collected? */ + g->strcache[i][j] = g->memerrmsg; /* replace it with something fixed */ + } +} + + +/* +** Initialize the string table and the string cache +*/ +void luaS_init (lua_State *L) { + global_State *g = G(L); + int i, j; + luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ + /* pre-create memory-error message */ + g->memerrmsg = luaS_newliteral(L, MEMERRMSG); + luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */ + for (i = 0; i < STRCACHE_N; i++) /* fill cache with valid strings */ + for (j = 0; j < STRCACHE_M; j++) + g->strcache[i][j] = g->memerrmsg; +} + + + +/* +** creates a new string object +*/ +static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) { TString *ts; - stringtable *tb; - if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) - luaM_toobig(L); - ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString))); - ts->tsv.len = l; - ts->tsv.hash = h; - ts->tsv.marked = luaC_white(G(L)); - ts->tsv.tt = LUA_TSTRING; - ts->tsv.reserved = 0; - memcpy(ts+1, str, l*sizeof(char)); - ((char *)(ts+1))[l] = '\0'; /* ending 0 */ - tb = &G(L)->strt; - h = lmod(h, tb->size); - ts->tsv.next = tb->hash[h]; /* chain new entry */ - tb->hash[h] = obj2gco(ts); - tb->nuse++; - if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) - luaS_resize(L, tb->size*2); /* too crowded */ + GCObject *o; + size_t totalsize; /* total size of TString object */ + totalsize = sizelstring(l); + o = luaC_newobj(L, tag, totalsize); + ts = gco2ts(o); + ts->hash = h; + ts->extra = 0; + getstr(ts)[l] = '\0'; /* ending 0 */ return ts; } -TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { - GCObject *o; - unsigned int h = cast(unsigned int, l); /* seed */ - size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ - size_t l1; - for (l1=l; l1>=step; l1-=step) /* compute hash */ - h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1])); - for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; - o != NULL; - o = o->gch.next) { - TString *ts = rawgco2ts(o); - if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) { - /* string may be dead */ - if (isdead(G(L), o)) changewhite(o); +TString *luaS_createlngstrobj (lua_State *L, size_t l) { + TString *ts = createstrobj(L, l, LUA_TLNGSTR, G(L)->seed); + ts->u.lnglen = l; + return ts; +} + + +void luaS_remove (lua_State *L, TString *ts) { + stringtable *tb = &G(L)->strt; + TString **p = &tb->hash[lmod(ts->hash, tb->size)]; + while (*p != ts) /* find previous element */ + p = &(*p)->u.hnext; + *p = (*p)->u.hnext; /* remove element from its list */ + tb->nuse--; +} + + +/* +** checks whether short string exists and reuses it or creates a new one +*/ +static TString *internshrstr (lua_State *L, const char *str, size_t l) { + TString *ts; + global_State *g = G(L); + unsigned int h = luaS_hash(str, l, g->seed); + TString **list = &g->strt.hash[lmod(h, g->strt.size)]; + lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */ + for (ts = *list; ts != NULL; ts = ts->u.hnext) { + if (l == ts->shrlen && + (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { + /* found! */ + if (isdead(g, ts)) /* dead (but not collected yet)? */ + changewhite(ts); /* resurrect it */ return ts; } } - return newlstr(L, str, l, h); /* not found */ + if (g->strt.nuse >= g->strt.size && g->strt.size <= MAX_INT/2) { + luaS_resize(L, g->strt.size * 2); + list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */ + } + ts = createstrobj(L, l, LUA_TSHRSTR, h); + memcpy(getstr(ts), str, l * sizeof(char)); + ts->shrlen = cast_byte(l); + ts->u.hnext = *list; + *list = ts; + g->strt.nuse++; + return ts; +} + + +/* +** new string (with explicit length) +*/ +TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { + if (l <= LUAI_MAXSHORTLEN) /* short string? */ + return internshrstr(L, str, l); + else { + TString *ts; + if (l >= (MAX_SIZE - sizeof(TString))/sizeof(char)) + luaM_toobig(L); + ts = luaS_createlngstrobj(L, l); + memcpy(getstr(ts), str, l * sizeof(char)); + return ts; + } } -Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { +/* +** Create or reuse a zero-terminated string, first checking in the +** cache (using the string address as a key). The cache can contain +** only zero-terminated strings, so it is safe to use 'strcmp' to +** check hits. +*/ +TString *luaS_new (lua_State *L, const char *str) { + unsigned int i = point2uint(str) % STRCACHE_N; /* hash */ + int j; + TString **p = G(L)->strcache[i]; + for (j = 0; j < STRCACHE_M; j++) { + if (strcmp(str, getstr(p[j])) == 0) /* hit? */ + return p[j]; /* that is it */ + } + /* normal route */ + for (j = STRCACHE_M - 1; j > 0; j--) + p[j] = p[j - 1]; /* move out last element */ + /* new element is first in the list */ + p[0] = luaS_newlstr(L, str, strlen(str)); + return p[0]; +} + + +Udata *luaS_newudata (lua_State *L, size_t s) { Udata *u; - if (s > MAX_SIZET - sizeof(Udata)) + GCObject *o; + if (s > MAX_SIZE - sizeof(Udata)) luaM_toobig(L); - u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata))); - u->uv.marked = luaC_white(G(L)); /* is not finalized */ - u->uv.tt = LUA_TUSERDATA; - u->uv.len = s; - u->uv.metatable = NULL; - u->uv.env = e; - /* chain it on udata list (after main thread) */ - u->uv.next = G(L)->mainthread->next; - G(L)->mainthread->next = obj2gco(u); + o = luaC_newobj(L, LUA_TUSERDATA, sizeludata(s)); + u = gco2u(o); + u->len = s; + u->metatable = NULL; + setuservalue(L, u, luaO_nilobject); return u; } diff --git a/app/src/main/jni/lua/lstring.h b/app/src/main/jni/lua/lstring.h index 73a2ff8..27efd20 100644 --- a/app/src/main/jni/lua/lstring.h +++ b/app/src/main/jni/lua/lstring.h @@ -1,5 +1,5 @@ /* -** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lstring.h,v 1.61 2015/11/03 15:36:01 roberto Exp $ ** String table (keep all strings handled by Lua) ** See Copyright Notice in lua.h */ @@ -7,25 +7,43 @@ #ifndef lstring_h #define lstring_h - #include "lgc.h" #include "lobject.h" #include "lstate.h" -#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) +#define sizelstring(l) (sizeof(union UTString) + ((l) + 1) * sizeof(char)) -#define sizeudata(u) (sizeof(union Udata)+(u)->len) +#define sizeludata(l) (sizeof(union UUdata) + (l)) +#define sizeudata(u) sizeludata((u)->len) -#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ (sizeof(s)/sizeof(char))-1)) -#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) +/* +** test whether a string is a reserved word +*/ +#define isreserved(s) ((s)->tt == LUA_TSHRSTR && (s)->extra > 0) + + +/* +** equality for short strings, which are always internalized +*/ +#define eqshrstr(a,b) check_exp((a)->tt == LUA_TSHRSTR, (a) == (b)) + + +LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed); +LUAI_FUNC unsigned int luaS_hashlongstr (TString *ts); +LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); LUAI_FUNC void luaS_resize (lua_State *L, int newsize); -LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); +LUAI_FUNC void luaS_clearcache (global_State *g); +LUAI_FUNC void luaS_init (lua_State *L); +LUAI_FUNC void luaS_remove (lua_State *L, TString *ts); +LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s); LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); +LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); +LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l); #endif diff --git a/app/src/main/jni/lua/lstrlib.c b/app/src/main/jni/lua/lstrlib.c index 7a03489..12264f8 100644 --- a/app/src/main/jni/lua/lstrlib.c +++ b/app/src/main/jni/lua/lstrlib.c @@ -1,66 +1,94 @@ /* -** $Id: lstrlib.c,v 1.132.1.5 2010/05/14 15:34:19 roberto Exp $ +** $Id: lstrlib.c,v 1.251 2016/05/20 14:13:21 roberto Exp $ ** Standard library for string operations and pattern-matching ** See Copyright Notice in lua.h */ +#define lstrlib_c +#define LUA_LIB + +#include "lprefix.h" + #include +#include +#include +#include #include #include #include #include -#define lstrlib_c -#define LUA_LIB - #include "lua.h" #include "lauxlib.h" #include "lualib.h" -/* macro to `unsign' a character */ -#define uchar(c) ((unsigned char)(c)) +/* +** maximum number of captures that a pattern can do during +** pattern-matching. This limit is arbitrary, but must fit in +** an unsigned char. +*/ +#if !defined(LUA_MAXCAPTURES) +#define LUA_MAXCAPTURES 32 +#endif + + +/* macro to 'unsign' a character */ +#define uchar(c) ((unsigned char)(c)) + + +/* +** Some sizes are better limited to fit in 'int', but must also fit in +** 'size_t'. (We assume that 'lua_Integer' cannot be smaller than 'int'.) +*/ +#define MAX_SIZET ((size_t)(~(size_t)0)) + +#define MAXSIZE \ + (sizeof(size_t) < sizeof(int) ? MAX_SIZET : (size_t)(INT_MAX)) + static int str_len (lua_State *L) { size_t l; luaL_checklstring(L, 1, &l); - lua_pushinteger(L, l); + lua_pushinteger(L, (lua_Integer)l); return 1; } -static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) { - /* relative string position: negative means back from end */ - if (pos < 0) pos += (ptrdiff_t)len + 1; - return (pos >= 0) ? pos : 0; +/* translate a relative string position: negative means back from end */ +static lua_Integer posrelat (lua_Integer pos, size_t len) { + if (pos >= 0) return pos; + else if (0u - (size_t)pos > len) return 0; + else return (lua_Integer)len + pos + 1; } static int str_sub (lua_State *L) { size_t l; const char *s = luaL_checklstring(L, 1, &l); - ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l); - ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l); + lua_Integer start = posrelat(luaL_checkinteger(L, 2), l); + lua_Integer end = posrelat(luaL_optinteger(L, 3, -1), l); if (start < 1) start = 1; - if (end > (ptrdiff_t)l) end = (ptrdiff_t)l; + if (end > (lua_Integer)l) end = l; if (start <= end) - lua_pushlstring(L, s+start-1, end-start+1); + lua_pushlstring(L, s + start - 1, (size_t)(end - start) + 1); else lua_pushliteral(L, ""); return 1; } static int str_reverse (lua_State *L) { - size_t l; + size_t l, i; luaL_Buffer b; const char *s = luaL_checklstring(L, 1, &l); - luaL_buffinit(L, &b); - while (l--) luaL_addchar(&b, s[l]); - luaL_pushresult(&b); + char *p = luaL_buffinitsize(L, &b, l); + for (i = 0; i < l; i++) + p[i] = s[l - i - 1]; + luaL_pushresultsize(&b, l); return 1; } @@ -70,10 +98,10 @@ static int str_lower (lua_State *L) { size_t i; luaL_Buffer b; const char *s = luaL_checklstring(L, 1, &l); - luaL_buffinit(L, &b); + char *p = luaL_buffinitsize(L, &b, l); for (i=0; i 0) - luaL_addlstring(&b, s, l); - luaL_pushresult(&b); + lua_Integer n = luaL_checkinteger(L, 2); + const char *sep = luaL_optlstring(L, 3, "", &lsep); + if (n <= 0) lua_pushliteral(L, ""); + else if (l + lsep < l || l + lsep > MAXSIZE / n) /* may overflow? */ + return luaL_error(L, "resulting string too large"); + else { + size_t totallen = (size_t)n * l + (size_t)(n - 1) * lsep; + luaL_Buffer b; + char *p = luaL_buffinitsize(L, &b, totallen); + while (n-- > 1) { /* first n-1 copies (followed by separator) */ + memcpy(p, s, l * sizeof(char)); p += l; + if (lsep > 0) { /* empty 'memcpy' is not that cheap */ + memcpy(p, sep, lsep * sizeof(char)); + p += lsep; + } + } + memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */ + luaL_pushresultsize(&b, totallen); + } return 1; } @@ -106,15 +148,15 @@ static int str_rep (lua_State *L) { static int str_byte (lua_State *L) { size_t l; const char *s = luaL_checklstring(L, 1, &l); - ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l); - ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l); + lua_Integer posi = posrelat(luaL_optinteger(L, 2, 1), l); + lua_Integer pose = posrelat(luaL_optinteger(L, 3, posi), l); int n, i; - if (posi <= 0) posi = 1; - if ((size_t)pose > l) pose = l; + if (posi < 1) posi = 1; + if (pose > (lua_Integer)l) pose = l; if (posi > pose) return 0; /* empty interval; return no values */ - n = (int)(pose - posi + 1); - if (posi + n <= pose) /* overflow? */ - luaL_error(L, "string slice too long"); + if (pose - posi >= INT_MAX) /* arithmetic overflow? */ + return luaL_error(L, "string slice too long"); + n = (int)(pose - posi) + 1; luaL_checkstack(L, n, "string slice too long"); for (i=0; i= ms->level || ms->capture[l].len == CAP_UNFINISHED) - return luaL_error(ms->L, "invalid capture index"); + return luaL_error(ms->L, "invalid capture index %%%d", l + 1); return l; } @@ -202,17 +258,17 @@ static int capture_to_close (MatchState *ms) { static const char *classend (MatchState *ms, const char *p) { switch (*p++) { case L_ESC: { - if (*p == '\0') - luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); + if (p == ms->p_end) + luaL_error(ms->L, "malformed pattern (ends with '%%')"); return p+1; } case '[': { if (*p == '^') p++; - do { /* look for a `]' */ - if (*p == '\0') - luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); - if (*(p++) == L_ESC && *p != '\0') - p++; /* skip escapes (e.g. `%]') */ + do { /* look for a ']' */ + if (p == ms->p_end) + luaL_error(ms->L, "malformed pattern (missing ']')"); + if (*(p++) == L_ESC && p < ms->p_end) + p++; /* skip escapes (e.g. '%]') */ } while (*p != ']'); return p+1; } @@ -229,13 +285,14 @@ static int match_class (int c, int cl) { case 'a' : res = isalpha(c); break; case 'c' : res = iscntrl(c); break; case 'd' : res = isdigit(c); break; + case 'g' : res = isgraph(c); break; case 'l' : res = islower(c); break; case 'p' : res = ispunct(c); break; case 's' : res = isspace(c); break; case 'u' : res = isupper(c); break; case 'w' : res = isalnum(c); break; case 'x' : res = isxdigit(c); break; - case 'z' : res = (c == 0); break; + case 'z' : res = (c == 0); break; /* deprecated option */ default: return (cl == c); } return (islower(cl) ? res : !res); @@ -246,7 +303,7 @@ static int matchbracketclass (int c, const char *p, const char *ec) { int sig = 1; if (*(p+1) == '^') { sig = 0; - p++; /* skip the `^' */ + p++; /* skip the '^' */ } while (++p < ec) { if (*p == L_ESC) { @@ -265,23 +322,26 @@ static int matchbracketclass (int c, const char *p, const char *ec) { } -static int singlematch (int c, const char *p, const char *ep) { - switch (*p) { - case '.': return 1; /* matches any char */ - case L_ESC: return match_class(c, uchar(*(p+1))); - case '[': return matchbracketclass(c, p, ep-1); - default: return (uchar(*p) == c); +static int singlematch (MatchState *ms, const char *s, const char *p, + const char *ep) { + if (s >= ms->src_end) + return 0; + else { + int c = uchar(*s); + switch (*p) { + case '.': return 1; /* matches any char */ + case L_ESC: return match_class(c, uchar(*(p+1))); + case '[': return matchbracketclass(c, p, ep-1); + default: return (uchar(*p) == c); + } } } -static const char *match (MatchState *ms, const char *s, const char *p); - - static const char *matchbalance (MatchState *ms, const char *s, const char *p) { - if (*p == 0 || *(p+1) == 0) - luaL_error(ms->L, "unbalanced pattern"); + if (p >= ms->p_end - 1) + luaL_error(ms->L, "malformed pattern (missing arguments to '%%b')"); if (*s != *p) return NULL; else { int b = *p; @@ -301,7 +361,7 @@ static const char *matchbalance (MatchState *ms, const char *s, static const char *max_expand (MatchState *ms, const char *s, const char *p, const char *ep) { ptrdiff_t i = 0; /* counts maximum expand for item */ - while ((s+i)src_end && singlematch(uchar(*(s+i)), p, ep)) + while (singlematch(ms, s + i, p, ep)) i++; /* keeps trying to match with the maximum repetitions */ while (i>=0) { @@ -319,7 +379,7 @@ static const char *min_expand (MatchState *ms, const char *s, const char *res = match(ms, s, ep+1); if (res != NULL) return res; - else if (ssrc_end && singlematch(uchar(*s), p, ep)) + else if (singlematch(ms, s, p, ep)) s++; /* try with one more repetition */ else return NULL; } @@ -363,80 +423,104 @@ static const char *match_capture (MatchState *ms, const char *s, int l) { static const char *match (MatchState *ms, const char *s, const char *p) { + if (ms->matchdepth-- == 0) + luaL_error(ms->L, "pattern too complex"); init: /* using goto's to optimize tail recursion */ - switch (*p) { - case '(': { /* start capture */ - if (*(p+1) == ')') /* position capture? */ - return start_capture(ms, s, p+2, CAP_POSITION); - else - return start_capture(ms, s, p+1, CAP_UNFINISHED); - } - case ')': { /* end capture */ - return end_capture(ms, s, p+1); - } - case L_ESC: { - switch (*(p+1)) { - case 'b': { /* balanced string? */ - s = matchbalance(ms, s, p+2); - if (s == NULL) return NULL; - p+=4; goto init; /* else return match(ms, s, p+4); */ - } - case 'f': { /* frontier? */ - const char *ep; char previous; - p += 2; - if (*p != '[') - luaL_error(ms->L, "missing " LUA_QL("[") " after " - LUA_QL("%%f") " in pattern"); - ep = classend(ms, p); /* points to what is next */ - previous = (s == ms->src_init) ? '\0' : *(s-1); - if (matchbracketclass(uchar(previous), p, ep-1) || - !matchbracketclass(uchar(*s), p, ep-1)) return NULL; - p=ep; goto init; /* else return match(ms, s, ep); */ - } - default: { - if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ - s = match_capture(ms, s, uchar(*(p+1))); - if (s == NULL) return NULL; - p+=2; goto init; /* else return match(ms, s, p+2) */ + if (p != ms->p_end) { /* end of pattern? */ + switch (*p) { + case '(': { /* start capture */ + if (*(p + 1) == ')') /* position capture? */ + s = start_capture(ms, s, p + 2, CAP_POSITION); + else + s = start_capture(ms, s, p + 1, CAP_UNFINISHED); + break; + } + case ')': { /* end capture */ + s = end_capture(ms, s, p + 1); + break; + } + case '$': { + if ((p + 1) != ms->p_end) /* is the '$' the last char in pattern? */ + goto dflt; /* no; go to default */ + s = (s == ms->src_end) ? s : NULL; /* check end of string */ + break; + } + case L_ESC: { /* escaped sequences not in the format class[*+?-]? */ + switch (*(p + 1)) { + case 'b': { /* balanced string? */ + s = matchbalance(ms, s, p + 2); + if (s != NULL) { + p += 4; goto init; /* return match(ms, s, p + 4); */ + } /* else fail (s == NULL) */ + break; + } + case 'f': { /* frontier? */ + const char *ep; char previous; + p += 2; + if (*p != '[') + luaL_error(ms->L, "missing '[' after '%%f' in pattern"); + ep = classend(ms, p); /* points to what is next */ + previous = (s == ms->src_init) ? '\0' : *(s - 1); + if (!matchbracketclass(uchar(previous), p, ep - 1) && + matchbracketclass(uchar(*s), p, ep - 1)) { + p = ep; goto init; /* return match(ms, s, ep); */ + } + s = NULL; /* match failed */ + break; + } + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case '8': case '9': { /* capture results (%0-%9)? */ + s = match_capture(ms, s, uchar(*(p + 1))); + if (s != NULL) { + p += 2; goto init; /* return match(ms, s, p + 2) */ + } + break; } - goto dflt; /* case default */ + default: goto dflt; } + break; } - } - case '\0': { /* end of pattern */ - return s; /* match succeeded */ - } - case '$': { - if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ - return (s == ms->src_end) ? s : NULL; /* check end of string */ - else goto dflt; - } - default: dflt: { /* it is a pattern item */ - const char *ep = classend(ms, p); /* points to what is next */ - int m = ssrc_end && singlematch(uchar(*s), p, ep); - switch (*ep) { - case '?': { /* optional */ - const char *res; - if (m && ((res=match(ms, s+1, ep+1)) != NULL)) - return res; - p=ep+1; goto init; /* else return match(ms, s, ep+1); */ - } - case '*': { /* 0 or more repetitions */ - return max_expand(ms, s, p, ep); - } - case '+': { /* 1 or more repetitions */ - return (m ? max_expand(ms, s+1, p, ep) : NULL); - } - case '-': { /* 0 or more repetitions (minimum) */ - return min_expand(ms, s, p, ep); + default: dflt: { /* pattern class plus optional suffix */ + const char *ep = classend(ms, p); /* points to optional suffix */ + /* does not match at least once? */ + if (!singlematch(ms, s, p, ep)) { + if (*ep == '*' || *ep == '?' || *ep == '-') { /* accept empty? */ + p = ep + 1; goto init; /* return match(ms, s, ep + 1); */ + } + else /* '+' or no suffix */ + s = NULL; /* fail */ } - default: { - if (!m) return NULL; - s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ + else { /* matched once */ + switch (*ep) { /* handle optional suffix */ + case '?': { /* optional */ + const char *res; + if ((res = match(ms, s + 1, ep + 1)) != NULL) + s = res; + else { + p = ep + 1; goto init; /* else return match(ms, s, ep + 1); */ + } + break; + } + case '+': /* 1 or more repetitions */ + s++; /* 1 match already done */ + /* FALLTHROUGH */ + case '*': /* 0 or more repetitions */ + s = max_expand(ms, s, p, ep); + break; + case '-': /* 0 or more repetitions (minimum) */ + s = min_expand(ms, s, p, ep); + break; + default: /* no suffix */ + s++; p = ep; goto init; /* return match(ms, s + 1, ep); */ + } } + break; } } } + ms->matchdepth++; + return s; } @@ -444,16 +528,16 @@ static const char *match (MatchState *ms, const char *s, const char *p) { static const char *lmemfind (const char *s1, size_t l1, const char *s2, size_t l2) { if (l2 == 0) return s1; /* empty strings are everywhere */ - else if (l2 > l1) return NULL; /* avoids a negative `l1' */ + else if (l2 > l1) return NULL; /* avoids a negative 'l1' */ else { - const char *init; /* to search for a `*s2' inside `s1' */ - l2--; /* 1st char will be checked by `memchr' */ - l1 = l1-l2; /* `s2' cannot be found after that */ + const char *init; /* to search for a '*s2' inside 's1' */ + l2--; /* 1st char will be checked by 'memchr' */ + l1 = l1-l2; /* 's2' cannot be found after that */ while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { init++; /* 1st char is already checked */ if (memcmp(init, s2+1, l2) == 0) return init-1; - else { /* correct `l1' and `s1' to try again */ + else { /* correct 'l1' and 's1' to try again */ l1 -= init-s1; s1 = init; } @@ -469,13 +553,13 @@ static void push_onecapture (MatchState *ms, int i, const char *s, if (i == 0) /* ms->level == 0, too */ lua_pushlstring(ms->L, s, e - s); /* add whole match */ else - luaL_error(ms->L, "invalid capture index"); + luaL_error(ms->L, "invalid capture index %%%d", i + 1); } else { ptrdiff_t l = ms->capture[i].len; if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); if (l == CAP_POSITION) - lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1); + lua_pushinteger(ms->L, (ms->capture[i].init - ms->src_init) + 1); else lua_pushlstring(ms->L, ms->capture[i].init, l); } @@ -492,37 +576,69 @@ static int push_captures (MatchState *ms, const char *s, const char *e) { } +/* check whether pattern has no special characters */ +static int nospecials (const char *p, size_t l) { + size_t upto = 0; + do { + if (strpbrk(p + upto, SPECIALS)) + return 0; /* pattern has a special character */ + upto += strlen(p + upto) + 1; /* may have more after \0 */ + } while (upto <= l); + return 1; /* no special chars found */ +} + + +static void prepstate (MatchState *ms, lua_State *L, + const char *s, size_t ls, const char *p, size_t lp) { + ms->L = L; + ms->matchdepth = MAXCCALLS; + ms->src_init = s; + ms->src_end = s + ls; + ms->p_end = p + lp; +} + + +static void reprepstate (MatchState *ms) { + ms->level = 0; + lua_assert(ms->matchdepth == MAXCCALLS); +} + + static int str_find_aux (lua_State *L, int find) { - size_t l1, l2; - const char *s = luaL_checklstring(L, 1, &l1); - const char *p = luaL_checklstring(L, 2, &l2); - ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1; - if (init < 0) init = 0; - else if ((size_t)(init) > l1) init = (ptrdiff_t)l1; - if (find && (lua_toboolean(L, 4) || /* explicit request? */ - strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */ + size_t ls, lp; + const char *s = luaL_checklstring(L, 1, &ls); + const char *p = luaL_checklstring(L, 2, &lp); + lua_Integer init = posrelat(luaL_optinteger(L, 3, 1), ls); + if (init < 1) init = 1; + else if (init > (lua_Integer)ls + 1) { /* start after string's end? */ + lua_pushnil(L); /* cannot find anything */ + return 1; + } + /* explicit request or no special characters? */ + if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) { /* do a plain search */ - const char *s2 = lmemfind(s+init, l1-init, p, l2); + const char *s2 = lmemfind(s + init - 1, ls - (size_t)init + 1, p, lp); if (s2) { - lua_pushinteger(L, s2-s+1); - lua_pushinteger(L, s2-s+l2); + lua_pushinteger(L, (s2 - s) + 1); + lua_pushinteger(L, (s2 - s) + lp); return 2; } } else { MatchState ms; - int anchor = (*p == '^') ? (p++, 1) : 0; - const char *s1=s+init; - ms.L = L; - ms.src_init = s; - ms.src_end = s+l1; + const char *s1 = s + init - 1; + int anchor = (*p == '^'); + if (anchor) { + p++; lp--; /* skip anchor character */ + } + prepstate(&ms, L, s, ls, p, lp); do { const char *res; - ms.level = 0; + reprepstate(&ms); if ((res=match(&ms, s1, p)) != NULL) { if (find) { - lua_pushinteger(L, s1-s+1); /* start */ - lua_pushinteger(L, res-s); /* end */ + lua_pushinteger(L, (s1 - s) + 1); /* start */ + lua_pushinteger(L, res - s); /* end */ return push_captures(&ms, NULL, 0) + 2; } else @@ -545,26 +661,25 @@ static int str_match (lua_State *L) { } +/* state for 'gmatch' */ +typedef struct GMatchState { + const char *src; /* current position */ + const char *p; /* pattern */ + const char *lastmatch; /* end of last match */ + MatchState ms; /* match state */ +} GMatchState; + + static int gmatch_aux (lua_State *L) { - MatchState ms; - size_t ls; - const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); - const char *p = lua_tostring(L, lua_upvalueindex(2)); + GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3)); const char *src; - ms.L = L; - ms.src_init = s; - ms.src_end = s+ls; - for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); - src <= ms.src_end; - src++) { + gm->ms.L = L; + for (src = gm->src; src <= gm->ms.src_end; src++) { const char *e; - ms.level = 0; - 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); + reprepstate(&gm->ms); + if ((e = match(&gm->ms, src, gm->p)) != NULL && e != gm->lastmatch) { + gm->src = gm->lastmatch = e; + return push_captures(&gm->ms, src, e); } } return 0; /* not found */ @@ -572,36 +687,40 @@ static int gmatch_aux (lua_State *L) { static int gmatch (lua_State *L) { - luaL_checkstring(L, 1); - luaL_checkstring(L, 2); - lua_settop(L, 2); - lua_pushinteger(L, 0); + size_t ls, lp; + const char *s = luaL_checklstring(L, 1, &ls); + const char *p = luaL_checklstring(L, 2, &lp); + GMatchState *gm; + lua_settop(L, 2); /* keep them on closure to avoid being collected */ + gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState)); + prepstate(&gm->ms, L, s, ls, p, lp); + gm->src = s; gm->p = p; gm->lastmatch = NULL; lua_pushcclosure(L, gmatch_aux, 3); return 1; } -static int gfind_nodef (lua_State *L) { - return luaL_error(L, LUA_QL("string.gfind") " was renamed to " - LUA_QL("string.gmatch")); -} - - static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, const char *e) { size_t l, i; - const char *news = lua_tolstring(ms->L, 3, &l); + lua_State *L = ms->L; + const char *news = lua_tolstring(L, 3, &l); for (i = 0; i < l; i++) { if (news[i] != L_ESC) luaL_addchar(b, news[i]); else { i++; /* skip ESC */ - if (!isdigit(uchar(news[i]))) + if (!isdigit(uchar(news[i]))) { + if (news[i] != L_ESC) + luaL_error(L, "invalid use of '%c' in replacement string", L_ESC); luaL_addchar(b, news[i]); + } else if (news[i] == '0') luaL_addlstring(b, s, e - s); else { push_onecapture(ms, news[i] - '1', s, e); + luaL_tolstring(L, -1, NULL); /* if number, convert it to string */ + lua_remove(L, -2); /* remove original value */ luaL_addvalue(b); /* add capture to accumulated result */ } } @@ -610,14 +729,9 @@ static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, - const char *e) { + const char *e, int tr) { lua_State *L = ms->L; - switch (lua_type(L, 3)) { - case LUA_TNUMBER: - case LUA_TSTRING: { - add_s(ms, b, s, e); - return; - } + switch (tr) { case LUA_TFUNCTION: { int n; lua_pushvalue(L, 3); @@ -630,47 +744,51 @@ static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, lua_gettable(L, 3); break; } + default: { /* LUA_TNUMBER or LUA_TSTRING */ + add_s(ms, b, s, e); + return; + } } if (!lua_toboolean(L, -1)) { /* nil or false? */ lua_pop(L, 1); lua_pushlstring(L, s, e - s); /* keep original text */ } else if (!lua_isstring(L, -1)) - luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); + luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); luaL_addvalue(b); /* add result to accumulator */ } static int str_gsub (lua_State *L) { - size_t srcl; - const char *src = luaL_checklstring(L, 1, &srcl); - const char *p = luaL_checkstring(L, 2); - int tr = lua_type(L, 3); - int max_s = luaL_optint(L, 4, srcl+1); - int anchor = (*p == '^') ? (p++, 1) : 0; - int n = 0; + size_t srcl, lp; + const char *src = luaL_checklstring(L, 1, &srcl); /* subject */ + const char *p = luaL_checklstring(L, 2, &lp); /* pattern */ + const char *lastmatch = NULL; /* end of last match */ + int tr = lua_type(L, 3); /* replacement type */ + lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); /* max replacements */ + int anchor = (*p == '^'); + lua_Integer n = 0; /* replacement count */ MatchState ms; luaL_Buffer b; luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, "string/function/table expected"); luaL_buffinit(L, &b); - ms.L = L; - ms.src_init = src; - ms.src_end = src+srcl; + if (anchor) { + p++; lp--; /* skip anchor character */ + } + prepstate(&ms, L, src, srcl, p, lp); while (n < max_s) { const char *e; - ms.level = 0; - e = match(&ms, src, p); - if (e) { + reprepstate(&ms); /* (re)prepare state for new match */ + if ((e = match(&ms, src, p)) != NULL && e != lastmatch) { /* match? */ n++; - add_value(&ms, &b, src, e); + add_value(&ms, &b, src, e, tr); /* add replacement to buffer */ + src = lastmatch = e; } - if (e && e>src) /* non empty match? */ - src = e; /* skip it */ - else if (src < ms.src_end) + else if (src < ms.src_end) /* otherwise, skip one character */ luaL_addchar(&b, *src++); - else break; + else break; /* end of subject */ if (anchor) break; } luaL_addlstring(&b, src, ms.src_end-src); @@ -682,50 +800,187 @@ static int str_gsub (lua_State *L) { /* }====================================================== */ -/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ -#define MAX_ITEM 512 + +/* +** {====================================================== +** STRING FORMAT +** ======================================================= +*/ + +#if !defined(lua_number2strx) /* { */ + +/* +** Hexadecimal floating-point formatter +*/ + +#include + +#define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char)) + + +/* +** Number of bits that goes into the first digit. It can be any value +** between 1 and 4; the following definition tries to align the number +** to nibble boundaries by making what is left after that first digit a +** multiple of 4. +*/ +#define L_NBFD ((l_mathlim(MANT_DIG) - 1)%4 + 1) + + +/* +** Add integer part of 'x' to buffer and return new 'x' +*/ +static lua_Number adddigit (char *buff, int n, lua_Number x) { + lua_Number dd = l_mathop(floor)(x); /* get integer part from 'x' */ + int d = (int)dd; + buff[n] = (d < 10 ? d + '0' : d - 10 + 'a'); /* add to buffer */ + return x - dd; /* return what is left */ +} + + +static int num2straux (char *buff, int sz, lua_Number x) { + if (x != x || x == HUGE_VAL || x == -HUGE_VAL) /* inf or NaN? */ + return l_sprintf(buff, sz, LUA_NUMBER_FMT, x); /* equal to '%g' */ + else if (x == 0) { /* can be -0... */ + /* create "0" or "-0" followed by exponent */ + return l_sprintf(buff, sz, LUA_NUMBER_FMT "x0p+0", x); + } + else { + int e; + lua_Number m = l_mathop(frexp)(x, &e); /* 'x' fraction and exponent */ + int n = 0; /* character count */ + if (m < 0) { /* is number negative? */ + buff[n++] = '-'; /* add signal */ + m = -m; /* make it positive */ + } + buff[n++] = '0'; buff[n++] = 'x'; /* add "0x" */ + m = adddigit(buff, n++, m * (1 << L_NBFD)); /* add first digit */ + e -= L_NBFD; /* this digit goes before the radix point */ + if (m > 0) { /* more digits? */ + buff[n++] = lua_getlocaledecpoint(); /* add radix point */ + do { /* add as many digits as needed */ + m = adddigit(buff, n++, m * 16); + } while (m > 0); + } + n += l_sprintf(buff + n, sz - n, "p%+d", e); /* add exponent */ + lua_assert(n < sz); + return n; + } +} + + +static int lua_number2strx (lua_State *L, char *buff, int sz, + const char *fmt, lua_Number x) { + int n = num2straux(buff, sz, x); + if (fmt[SIZELENMOD] == 'A') { + int i; + for (i = 0; i < n; i++) + buff[i] = toupper(uchar(buff[i])); + } + else if (fmt[SIZELENMOD] != 'a') + luaL_error(L, "modifiers for format '%%a'/'%%A' not implemented"); + return n; +} + +#endif /* } */ + + +/* +** Maximum size of each formatted item. This maximum size is produced +** by format('%.99f', -maxfloat), and is equal to 99 + 3 ('-', '.', +** and '\0') + number of decimal digits to represent maxfloat (which +** is maximum exponent + 1). (99+3+1 then rounded to 120 for "extra +** expenses", such as locale-dependent stuff) +*/ +#define MAX_ITEM (120 + l_mathlim(MAX_10_EXP)) + + /* valid flags in a format specification */ #define FLAGS "-+ #0" + /* -** maximum size of each format specification (such as '%-099.99d') -** (+10 accounts for %99.99x plus margin of error) +** maximum size of each format specification (such as "%-099.99d") */ -#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) +#define MAX_FORMAT 32 -static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { - size_t l; - const char *s = luaL_checklstring(L, arg, &l); +static void addquoted (luaL_Buffer *b, const char *s, size_t len) { luaL_addchar(b, '"'); - while (l--) { - switch (*s) { - case '"': case '\\': case '\n': { - luaL_addchar(b, '\\'); - luaL_addchar(b, *s); - break; - } - case '\r': { - luaL_addlstring(b, "\\r", 2); - break; - } - case '\0': { - luaL_addlstring(b, "\\000", 4); - break; - } - default: { - luaL_addchar(b, *s); - break; - } + while (len--) { + if (*s == '"' || *s == '\\' || *s == '\n') { + luaL_addchar(b, '\\'); + luaL_addchar(b, *s); + } + else if (iscntrl(uchar(*s))) { + char buff[10]; + if (!isdigit(uchar(*(s+1)))) + l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s)); + else + l_sprintf(buff, sizeof(buff), "\\%03d", (int)uchar(*s)); + luaL_addstring(b, buff); } + else + luaL_addchar(b, *s); s++; } luaL_addchar(b, '"'); } + +/* +** Ensures the 'buff' string uses a dot as the radix character. +*/ +static void checkdp (char *buff, int nb) { + if (memchr(buff, '.', nb) == NULL) { /* no dot? */ + char point = lua_getlocaledecpoint(); /* try locale point */ + char *ppoint = memchr(buff, point, nb); + if (ppoint) *ppoint = '.'; /* change it to a dot */ + } +} + + +static void addliteral (lua_State *L, luaL_Buffer *b, int arg) { + switch (lua_type(L, arg)) { + case LUA_TSTRING: { + size_t len; + const char *s = lua_tolstring(L, arg, &len); + addquoted(b, s, len); + break; + } + case LUA_TNUMBER: { + char *buff = luaL_prepbuffsize(b, MAX_ITEM); + int nb; + if (!lua_isinteger(L, arg)) { /* float? */ + lua_Number n = lua_tonumber(L, arg); /* write as hexa ('%a') */ + nb = lua_number2strx(L, buff, MAX_ITEM, "%" LUA_NUMBER_FRMLEN "a", n); + checkdp(buff, nb); /* ensure it uses a dot */ + } + else { /* integers */ + lua_Integer n = lua_tointeger(L, arg); + const char *format = (n == LUA_MININTEGER) /* corner case? */ + ? "0x%" LUA_INTEGER_FRMLEN "x" /* use hexa */ + : LUA_INTEGER_FMT; /* else use default format */ + nb = l_sprintf(buff, MAX_ITEM, format, n); + } + luaL_addsize(b, nb); + break; + } + case LUA_TNIL: case LUA_TBOOLEAN: { + luaL_tolstring(L, arg, NULL); + luaL_addvalue(b); + break; + } + default: { + luaL_argerror(L, arg, "value has no literal form"); + } + } +} + + static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { const char *p = strfrmt; while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ - if ((size_t)(p - strfrmt) >= sizeof(FLAGS)) + if ((size_t)(p - strfrmt) >= sizeof(FLAGS)/sizeof(char)) luaL_error(L, "invalid format (repeated flags)"); if (isdigit(uchar(*p))) p++; /* skip width */ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ @@ -737,19 +992,23 @@ static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { if (isdigit(uchar(*p))) luaL_error(L, "invalid format (width or precision too long)"); *(form++) = '%'; - strncpy(form, strfrmt, p - strfrmt + 1); - form += p - strfrmt + 1; + memcpy(form, strfrmt, ((p - strfrmt) + 1) * sizeof(char)); + form += (p - strfrmt) + 1; *form = '\0'; return p; } -static void addintlen (char *form) { +/* +** add length modifier into formats +*/ +static void addlenmod (char *form, const char *lenmod) { size_t l = strlen(form); + size_t lm = strlen(lenmod); char spec = form[l - 1]; - strcpy(form + l - 1, LUA_INTFRMLEN); - form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; - form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; + strcpy(form + l - 1, lenmod); + form[l + lm - 1] = spec; + form[l + lm] = '\0'; } @@ -767,62 +1026,516 @@ static int str_format (lua_State *L) { else if (*++strfrmt == L_ESC) luaL_addchar(&b, *strfrmt++); /* %% */ else { /* format item */ - char form[MAX_FORMAT]; /* to store the format (`%...') */ - char buff[MAX_ITEM]; /* to store the formatted item */ + char form[MAX_FORMAT]; /* to store the format ('%...') */ + char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */ + int nb = 0; /* number of bytes in added item */ if (++arg > top) luaL_argerror(L, arg, "no value"); strfrmt = scanformat(L, strfrmt, form); switch (*strfrmt++) { case 'c': { - sprintf(buff, form, (int)luaL_checknumber(L, arg)); + nb = l_sprintf(buff, MAX_ITEM, form, (int)luaL_checkinteger(L, arg)); break; } - case 'd': case 'i': { - addintlen(form); - sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); + case 'd': case 'i': + case 'o': case 'u': case 'x': case 'X': { + lua_Integer n = luaL_checkinteger(L, arg); + addlenmod(form, LUA_INTEGER_FRMLEN); + nb = l_sprintf(buff, MAX_ITEM, form, n); break; } - case 'o': case 'u': case 'x': case 'X': { - addintlen(form); - sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); + case 'a': case 'A': + addlenmod(form, LUA_NUMBER_FRMLEN); + nb = lua_number2strx(L, buff, MAX_ITEM, form, + luaL_checknumber(L, arg)); break; - } - case 'e': case 'E': case 'f': + case 'e': case 'E': case 'f': case 'g': case 'G': { - sprintf(buff, form, (double)luaL_checknumber(L, arg)); + addlenmod(form, LUA_NUMBER_FRMLEN); + nb = l_sprintf(buff, MAX_ITEM, form, luaL_checknumber(L, arg)); break; } case 'q': { - addquoted(L, &b, arg); - continue; /* skip the 'addsize' at the end */ + addliteral(L, &b, arg); + break; } case 's': { size_t l; - const char *s = luaL_checklstring(L, arg, &l); - if (!strchr(form, '.') && l >= 100) { - /* no precision and string is too long to be formatted; - keep original string */ - lua_pushvalue(L, arg); - luaL_addvalue(&b); - continue; /* skip the `addsize' at the end */ - } + const char *s = luaL_tolstring(L, arg, &l); + if (form[2] == '\0') /* no modifiers? */ + luaL_addvalue(&b); /* keep entire string */ else { - sprintf(buff, form, s); - break; + luaL_argcheck(L, l == strlen(s), arg, "string contains zeros"); + if (!strchr(form, '.') && l >= 100) { + /* no precision and string is too long to be formatted */ + luaL_addvalue(&b); /* keep entire string */ + } + else { /* format the string into 'buff' */ + nb = l_sprintf(buff, MAX_ITEM, form, s); + lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ + } } + break; } - default: { /* also treat cases `pnLlh' */ - return luaL_error(L, "invalid option " LUA_QL("%%%c") " to " - LUA_QL("format"), *(strfrmt - 1)); + default: { /* also treat cases 'pnLlh' */ + return luaL_error(L, "invalid option '%%%c' to 'format'", + *(strfrmt - 1)); } } - luaL_addlstring(&b, buff, strlen(buff)); + lua_assert(nb < MAX_ITEM); + luaL_addsize(&b, nb); } } luaL_pushresult(&b); return 1; } +/* }====================================================== */ + + +/* +** {====================================================== +** PACK/UNPACK +** ======================================================= +*/ + + +/* value used for padding */ +#if !defined(LUAL_PACKPADBYTE) +#define LUAL_PACKPADBYTE 0x00 +#endif + +/* maximum size for the binary representation of an integer */ +#define MAXINTSIZE 16 + +/* number of bits in a character */ +#define NB CHAR_BIT + +/* mask for one character (NB 1's) */ +#define MC ((1 << NB) - 1) + +/* size of a lua_Integer */ +#define SZINT ((int)sizeof(lua_Integer)) + + +/* dummy union to get native endianness */ +static const union { + int dummy; + char little; /* true iff machine is little endian */ +} nativeendian = {1}; + + +/* dummy structure to get native alignment requirements */ +struct cD { + char c; + union { double d; void *p; lua_Integer i; lua_Number n; } u; +}; + +#define MAXALIGN (offsetof(struct cD, u)) + + +/* +** Union for serializing floats +*/ +typedef union Ftypes { + float f; + double d; + lua_Number n; + char buff[5 * sizeof(lua_Number)]; /* enough for any float type */ +} Ftypes; + + +/* +** information to pack/unpack stuff +*/ +typedef struct Header { + lua_State *L; + int islittle; + int maxalign; +} Header; + + +/* +** options for pack/unpack +*/ +typedef enum KOption { + Kint, /* signed integers */ + Kuint, /* unsigned integers */ + Kfloat, /* floating-point numbers */ + Kchar, /* fixed-length strings */ + Kstring, /* strings with prefixed length */ + Kzstr, /* zero-terminated strings */ + Kpadding, /* padding */ + Kpaddalign, /* padding for alignment */ + Knop /* no-op (configuration or spaces) */ +} KOption; + + +/* +** Read an integer numeral from string 'fmt' or return 'df' if +** there is no numeral +*/ +static int digit (int c) { return '0' <= c && c <= '9'; } + +static int getnum (const char **fmt, int df) { + if (!digit(**fmt)) /* no number? */ + return df; /* return default value */ + else { + int a = 0; + do { + a = a*10 + (*((*fmt)++) - '0'); + } while (digit(**fmt) && a <= ((int)MAXSIZE - 9)/10); + return a; + } +} + + +/* +** Read an integer numeral and raises an error if it is larger +** than the maximum size for integers. +*/ +static int getnumlimit (Header *h, const char **fmt, int df) { + int sz = getnum(fmt, df); + if (sz > MAXINTSIZE || sz <= 0) + luaL_error(h->L, "integral size (%d) out of limits [1,%d]", + sz, MAXINTSIZE); + return sz; +} + + +/* +** Initialize Header +*/ +static void initheader (lua_State *L, Header *h) { + h->L = L; + h->islittle = nativeendian.little; + h->maxalign = 1; +} + + +/* +** Read and classify next option. 'size' is filled with option's size. +*/ +static KOption getoption (Header *h, const char **fmt, int *size) { + int opt = *((*fmt)++); + *size = 0; /* default */ + switch (opt) { + case 'b': *size = sizeof(char); return Kint; + case 'B': *size = sizeof(char); return Kuint; + case 'h': *size = sizeof(short); return Kint; + case 'H': *size = sizeof(short); return Kuint; + case 'l': *size = sizeof(long); return Kint; + case 'L': *size = sizeof(long); return Kuint; + case 'j': *size = sizeof(lua_Integer); return Kint; + case 'J': *size = sizeof(lua_Integer); return Kuint; + case 'T': *size = sizeof(size_t); return Kuint; + case 'f': *size = sizeof(float); return Kfloat; + case 'd': *size = sizeof(double); return Kfloat; + case 'n': *size = sizeof(lua_Number); return Kfloat; + case 'i': *size = getnumlimit(h, fmt, sizeof(int)); return Kint; + case 'I': *size = getnumlimit(h, fmt, sizeof(int)); return Kuint; + case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring; + case 'c': + *size = getnum(fmt, -1); + if (*size == -1) + luaL_error(h->L, "missing size for format option 'c'"); + return Kchar; + case 'z': return Kzstr; + case 'x': *size = 1; return Kpadding; + case 'X': return Kpaddalign; + case ' ': break; + case '<': h->islittle = 1; break; + case '>': h->islittle = 0; break; + case '=': h->islittle = nativeendian.little; break; + case '!': h->maxalign = getnumlimit(h, fmt, MAXALIGN); break; + default: luaL_error(h->L, "invalid format option '%c'", opt); + } + return Knop; +} + + +/* +** Read, classify, and fill other details about the next option. +** 'psize' is filled with option's size, 'notoalign' with its +** alignment requirements. +** Local variable 'size' gets the size to be aligned. (Kpadal option +** always gets its full alignment, other options are limited by +** the maximum alignment ('maxalign'). Kchar option needs no alignment +** despite its size. +*/ +static KOption getdetails (Header *h, size_t totalsize, + const char **fmt, int *psize, int *ntoalign) { + KOption opt = getoption(h, fmt, psize); + int align = *psize; /* usually, alignment follows size */ + if (opt == Kpaddalign) { /* 'X' gets alignment from following option */ + if (**fmt == '\0' || getoption(h, fmt, &align) == Kchar || align == 0) + luaL_argerror(h->L, 1, "invalid next option for option 'X'"); + } + if (align <= 1 || opt == Kchar) /* need no alignment? */ + *ntoalign = 0; + else { + if (align > h->maxalign) /* enforce maximum alignment */ + align = h->maxalign; + if ((align & (align - 1)) != 0) /* is 'align' not a power of 2? */ + luaL_argerror(h->L, 1, "format asks for alignment not power of 2"); + *ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1); + } + return opt; +} + + +/* +** Pack integer 'n' with 'size' bytes and 'islittle' endianness. +** The final 'if' handles the case when 'size' is larger than +** the size of a Lua integer, correcting the extra sign-extension +** bytes if necessary (by default they would be zeros). +*/ +static void packint (luaL_Buffer *b, lua_Unsigned n, + int islittle, int size, int neg) { + char *buff = luaL_prepbuffsize(b, size); + int i; + buff[islittle ? 0 : size - 1] = (char)(n & MC); /* first byte */ + for (i = 1; i < size; i++) { + n >>= NB; + buff[islittle ? i : size - 1 - i] = (char)(n & MC); + } + if (neg && size > SZINT) { /* negative number need sign extension? */ + for (i = SZINT; i < size; i++) /* correct extra bytes */ + buff[islittle ? i : size - 1 - i] = (char)MC; + } + luaL_addsize(b, size); /* add result to buffer */ +} + + +/* +** Copy 'size' bytes from 'src' to 'dest', correcting endianness if +** given 'islittle' is different from native endianness. +*/ +static void copywithendian (volatile char *dest, volatile const char *src, + int size, int islittle) { + if (islittle == nativeendian.little) { + while (size-- != 0) + *(dest++) = *(src++); + } + else { + dest += size - 1; + while (size-- != 0) + *(dest--) = *(src++); + } +} + + +static int str_pack (lua_State *L) { + luaL_Buffer b; + Header h; + const char *fmt = luaL_checkstring(L, 1); /* format string */ + int arg = 1; /* current argument to pack */ + size_t totalsize = 0; /* accumulate total size of result */ + initheader(L, &h); + lua_pushnil(L); /* mark to separate arguments from string buffer */ + luaL_buffinit(L, &b); + while (*fmt != '\0') { + int size, ntoalign; + KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); + totalsize += ntoalign + size; + while (ntoalign-- > 0) + luaL_addchar(&b, LUAL_PACKPADBYTE); /* fill alignment */ + arg++; + switch (opt) { + case Kint: { /* signed integers */ + lua_Integer n = luaL_checkinteger(L, arg); + if (size < SZINT) { /* need overflow check? */ + lua_Integer lim = (lua_Integer)1 << ((size * NB) - 1); + luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow"); + } + packint(&b, (lua_Unsigned)n, h.islittle, size, (n < 0)); + break; + } + case Kuint: { /* unsigned integers */ + lua_Integer n = luaL_checkinteger(L, arg); + if (size < SZINT) /* need overflow check? */ + luaL_argcheck(L, (lua_Unsigned)n < ((lua_Unsigned)1 << (size * NB)), + arg, "unsigned overflow"); + packint(&b, (lua_Unsigned)n, h.islittle, size, 0); + break; + } + case Kfloat: { /* floating-point options */ + volatile Ftypes u; + char *buff = luaL_prepbuffsize(&b, size); + lua_Number n = luaL_checknumber(L, arg); /* get argument */ + if (size == sizeof(u.f)) u.f = (float)n; /* copy it into 'u' */ + else if (size == sizeof(u.d)) u.d = (double)n; + else u.n = n; + /* move 'u' to final result, correcting endianness if needed */ + copywithendian(buff, u.buff, size, h.islittle); + luaL_addsize(&b, size); + break; + } + case Kchar: { /* fixed-size string */ + size_t len; + const char *s = luaL_checklstring(L, arg, &len); + luaL_argcheck(L, len <= (size_t)size, arg, + "string longer than given size"); + luaL_addlstring(&b, s, len); /* add string */ + while (len++ < (size_t)size) /* pad extra space */ + luaL_addchar(&b, LUAL_PACKPADBYTE); + break; + } + case Kstring: { /* strings with length count */ + size_t len; + const char *s = luaL_checklstring(L, arg, &len); + luaL_argcheck(L, size >= (int)sizeof(size_t) || + len < ((size_t)1 << (size * NB)), + arg, "string length does not fit in given size"); + packint(&b, (lua_Unsigned)len, h.islittle, size, 0); /* pack length */ + luaL_addlstring(&b, s, len); + totalsize += len; + break; + } + case Kzstr: { /* zero-terminated string */ + size_t len; + const char *s = luaL_checklstring(L, arg, &len); + luaL_argcheck(L, strlen(s) == len, arg, "string contains zeros"); + luaL_addlstring(&b, s, len); + luaL_addchar(&b, '\0'); /* add zero at the end */ + totalsize += len + 1; + break; + } + case Kpadding: luaL_addchar(&b, LUAL_PACKPADBYTE); /* FALLTHROUGH */ + case Kpaddalign: case Knop: + arg--; /* undo increment */ + break; + } + } + luaL_pushresult(&b); + return 1; +} + + +static int str_packsize (lua_State *L) { + Header h; + const char *fmt = luaL_checkstring(L, 1); /* format string */ + size_t totalsize = 0; /* accumulate total size of result */ + initheader(L, &h); + while (*fmt != '\0') { + int size, ntoalign; + KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); + size += ntoalign; /* total space used by option */ + luaL_argcheck(L, totalsize <= MAXSIZE - size, 1, + "format result too large"); + totalsize += size; + switch (opt) { + case Kstring: /* strings with length count */ + case Kzstr: /* zero-terminated string */ + luaL_argerror(L, 1, "variable-length format"); + /* call never return, but to avoid warnings: *//* FALLTHROUGH */ + default: break; + } + } + lua_pushinteger(L, (lua_Integer)totalsize); + return 1; +} + + +/* +** Unpack an integer with 'size' bytes and 'islittle' endianness. +** If size is smaller than the size of a Lua integer and integer +** is signed, must do sign extension (propagating the sign to the +** higher bits); if size is larger than the size of a Lua integer, +** it must check the unread bytes to see whether they do not cause an +** overflow. +*/ +static lua_Integer unpackint (lua_State *L, const char *str, + int islittle, int size, int issigned) { + lua_Unsigned res = 0; + int i; + int limit = (size <= SZINT) ? size : SZINT; + for (i = limit - 1; i >= 0; i--) { + res <<= NB; + res |= (lua_Unsigned)(unsigned char)str[islittle ? i : size - 1 - i]; + } + if (size < SZINT) { /* real size smaller than lua_Integer? */ + if (issigned) { /* needs sign extension? */ + lua_Unsigned mask = (lua_Unsigned)1 << (size*NB - 1); + res = ((res ^ mask) - mask); /* do sign extension */ + } + } + else if (size > SZINT) { /* must check unread bytes */ + int mask = (!issigned || (lua_Integer)res >= 0) ? 0 : MC; + for (i = limit; i < size; i++) { + if ((unsigned char)str[islittle ? i : size - 1 - i] != mask) + luaL_error(L, "%d-byte integer does not fit into Lua Integer", size); + } + } + return (lua_Integer)res; +} + + +static int str_unpack (lua_State *L) { + Header h; + const char *fmt = luaL_checkstring(L, 1); + size_t ld; + const char *data = luaL_checklstring(L, 2, &ld); + size_t pos = (size_t)posrelat(luaL_optinteger(L, 3, 1), ld) - 1; + int n = 0; /* number of results */ + luaL_argcheck(L, pos <= ld, 3, "initial position out of string"); + initheader(L, &h); + while (*fmt != '\0') { + int size, ntoalign; + KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign); + if ((size_t)ntoalign + size > ~pos || pos + ntoalign + size > ld) + luaL_argerror(L, 2, "data string too short"); + pos += ntoalign; /* skip alignment */ + /* stack space for item + next position */ + luaL_checkstack(L, 2, "too many results"); + n++; + switch (opt) { + case Kint: + case Kuint: { + lua_Integer res = unpackint(L, data + pos, h.islittle, size, + (opt == Kint)); + lua_pushinteger(L, res); + break; + } + case Kfloat: { + volatile Ftypes u; + lua_Number num; + copywithendian(u.buff, data + pos, size, h.islittle); + if (size == sizeof(u.f)) num = (lua_Number)u.f; + else if (size == sizeof(u.d)) num = (lua_Number)u.d; + else num = u.n; + lua_pushnumber(L, num); + break; + } + case Kchar: { + lua_pushlstring(L, data + pos, size); + break; + } + case Kstring: { + size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0); + luaL_argcheck(L, pos + len + size <= ld, 2, "data string too short"); + lua_pushlstring(L, data + pos + size, len); + pos += len; /* skip string */ + break; + } + case Kzstr: { + size_t len = (int)strlen(data + pos); + lua_pushlstring(L, data + pos, len); + pos += len + 1; /* skip string plus final '\0' */ + break; + } + case Kpaddalign: case Kpadding: case Knop: + n--; /* undo increment */ + break; + } + pos += size; + } + lua_pushinteger(L, pos + 1); /* next position */ + return n + 1; +} + +/* }====================================================== */ + static const luaL_Reg strlib[] = { {"byte", str_byte}, @@ -830,7 +1543,6 @@ static const luaL_Reg strlib[] = { {"dump", str_dump}, {"find", str_find}, {"format", str_format}, - {"gfind", gfind_nodef}, {"gmatch", gmatch}, {"gsub", str_gsub}, {"len", str_len}, @@ -840,18 +1552,21 @@ static const luaL_Reg strlib[] = { {"reverse", str_reverse}, {"sub", str_sub}, {"upper", str_upper}, + {"pack", str_pack}, + {"packsize", str_packsize}, + {"unpack", str_unpack}, {NULL, NULL} }; static void createmetatable (lua_State *L) { - lua_createtable(L, 0, 1); /* create metatable for strings */ + lua_createtable(L, 0, 1); /* table to be metatable for strings */ lua_pushliteral(L, ""); /* dummy string */ - lua_pushvalue(L, -2); - lua_setmetatable(L, -2); /* set string metatable */ + lua_pushvalue(L, -2); /* copy table */ + lua_setmetatable(L, -2); /* set table as metatable for strings */ lua_pop(L, 1); /* pop dummy string */ - lua_pushvalue(L, -2); /* string library... */ - lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */ + lua_pushvalue(L, -2); /* get string library */ + lua_setfield(L, -2, "__index"); /* metatable.__index = string */ lua_pop(L, 1); /* pop metatable */ } @@ -859,12 +1574,8 @@ static void createmetatable (lua_State *L) { /* ** Open string library */ -LUALIB_API int luaopen_string (lua_State *L) { - luaL_register(L, LUA_STRLIBNAME, strlib); -#if defined(LUA_COMPAT_GFIND) - lua_getfield(L, -1, "gmatch"); - lua_setfield(L, -2, "gfind"); -#endif +LUAMOD_API int luaopen_string (lua_State *L) { + luaL_newlib(L, strlib); createmetatable(L); return 1; } diff --git a/app/src/main/jni/lua/ltable.c b/app/src/main/jni/lua/ltable.c index ec84f4f..7e15b71 100644 --- a/app/src/main/jni/lua/ltable.c +++ b/app/src/main/jni/lua/ltable.c @@ -1,28 +1,30 @@ /* -** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $ +** $Id: ltable.c,v 2.117 2015/11/19 19:16:22 roberto Exp $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ +#define ltable_c +#define LUA_CORE + +#include "lprefix.h" + /* ** Implementation of tables (aka arrays, objects, or hash tables). ** Tables keep its elements in two parts: an array part and a hash part. ** Non-negative integer keys are all candidates to be kept in the array -** part. The actual size of the array is the largest `n' such that at -** least half the slots between 0 and n are in use. +** part. The actual size of the array is the largest 'n' such that +** more than half the slots between 1 and n are in use. ** Hash uses a mix of chained scatter table with Brent's variation. ** A main invariant of these tables is that, if an element is not -** in its main position (i.e. the `original' position that its hash gives +** in its main position (i.e. the 'original' position that its hash gives ** to it), then the colliding element is in its own main position. ** Hence even when the load factor reaches 100%, performance remains good. */ #include -#include - -#define ltable_c -#define LUA_CORE +#include #include "lua.h" @@ -32,25 +34,32 @@ #include "lmem.h" #include "lobject.h" #include "lstate.h" +#include "lstring.h" #include "ltable.h" +#include "lvm.h" /* -** max size of array part is 2^MAXBITS +** Maximum size of array part (MAXASIZE) is 2^MAXABITS. MAXABITS is +** the largest integer such that MAXASIZE fits in an unsigned int. */ -#if LUAI_BITSINT > 26 -#define MAXBITS 26 -#else -#define MAXBITS (LUAI_BITSINT-2) -#endif +#define MAXABITS cast_int(sizeof(int) * CHAR_BIT - 1) +#define MAXASIZE (1u << MAXABITS) -#define MAXASIZE (1 << MAXBITS) +/* +** Maximum size of hash part is 2^MAXHBITS. MAXHBITS is the largest +** integer such that 2^MAXHBITS fits in a signed int. (Note that the +** maximum number of elements in a table, 2^MAXABITS + 2^MAXHBITS, still +** fits comfortably in an unsigned int.) +*/ +#define MAXHBITS (MAXABITS - 1) -#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) - -#define hashstr(t,str) hashpow2(t, (str)->tsv.hash) -#define hashboolean(t,p) hashpow2(t, p) +#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) + +#define hashstr(t,str) hashpow2(t, (str)->hash) +#define hashboolean(t,p) hashpow2(t, p) +#define hashint(t,i) hashpow2(t, i) /* @@ -60,117 +69,134 @@ #define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) -#define hashpointer(t,p) hashmod(t, IntPoint(p)) - - -/* -** number of ints inside a lua_Number -*/ -#define numints cast_int(sizeof(lua_Number)/sizeof(int)) - +#define hashpointer(t,p) hashmod(t, point2uint(p)) #define dummynode (&dummynode_) +#define isdummy(n) ((n) == dummynode) + static const Node dummynode_ = { - {{NULL}, LUA_TNIL}, /* value */ - {{{NULL}, LUA_TNIL, NULL}} /* key */ + {NILCONSTANT}, /* value */ + {{NILCONSTANT, 0}} /* key */ }; /* -** hash for lua_Numbers +** Hash for floating-point numbers. +** The main computation should be just +** n = frexp(n, &i); return (n * INT_MAX) + i +** but there are some numerical subtleties. +** In a two-complement representation, INT_MAX does not has an exact +** representation as a float, but INT_MIN does; because the absolute +** value of 'frexp' is smaller than 1 (unless 'n' is inf/NaN), the +** absolute value of the product 'frexp * -INT_MIN' is smaller or equal +** to INT_MAX. Next, the use of 'unsigned int' avoids overflows when +** adding 'i'; the use of '~u' (instead of '-u') avoids problems with +** INT_MIN. */ -static Node *hashnum (const Table *t, lua_Number n) { - unsigned int a[numints]; +#if !defined(l_hashfloat) +static int l_hashfloat (lua_Number n) { int i; - if (luai_numeq(n, 0)) /* avoid problems with -0 */ - return gnode(t, 0); - memcpy(a, &n, sizeof(a)); - for (i = 1; i < numints; i++) a[0] += a[i]; - return hashmod(t, a[0]); + lua_Integer ni; + n = l_mathop(frexp)(n, &i) * -cast_num(INT_MIN); + if (!lua_numbertointeger(n, &ni)) { /* is 'n' inf/-inf/NaN? */ + lua_assert(luai_numisnan(n) || l_mathop(fabs)(n) == cast_num(HUGE_VAL)); + return 0; + } + else { /* normal case */ + unsigned int u = cast(unsigned int, i) + cast(unsigned int, ni); + return cast_int(u <= cast(unsigned int, INT_MAX) ? u : ~u); + } } - +#endif /* -** returns the `main' position of an element in a table (that is, the index +** returns the 'main' position of an element in a table (that is, the index ** of its hash value) */ static Node *mainposition (const Table *t, const TValue *key) { switch (ttype(key)) { - case LUA_TNUMBER: - return hashnum(t, nvalue(key)); - case LUA_TSTRING: - return hashstr(t, rawtsvalue(key)); + case LUA_TNUMINT: + return hashint(t, ivalue(key)); + case LUA_TNUMFLT: + return hashmod(t, l_hashfloat(fltvalue(key))); + case LUA_TSHRSTR: + return hashstr(t, tsvalue(key)); + case LUA_TLNGSTR: + return hashpow2(t, luaS_hashlongstr(tsvalue(key))); case LUA_TBOOLEAN: return hashboolean(t, bvalue(key)); case LUA_TLIGHTUSERDATA: return hashpointer(t, pvalue(key)); + case LUA_TLCF: + return hashpointer(t, fvalue(key)); default: + lua_assert(!ttisdeadkey(key)); return hashpointer(t, gcvalue(key)); } } /* -** returns the index for `key' if `key' is an appropriate key to live in -** the array part of the table, -1 otherwise. +** returns the index for 'key' if 'key' is an appropriate key to live in +** the array part of the table, 0 otherwise. */ -static int arrayindex (const TValue *key) { - if (ttisnumber(key)) { - lua_Number n = nvalue(key); - int k; - lua_number2int(k, n); - if (luai_numeq(cast_num(k), n)) - return k; +static unsigned int arrayindex (const TValue *key) { + if (ttisinteger(key)) { + lua_Integer k = ivalue(key); + if (0 < k && (lua_Unsigned)k <= MAXASIZE) + return cast(unsigned int, k); /* 'key' is an appropriate array index */ } - return -1; /* `key' did not match some condition */ + return 0; /* 'key' did not match some condition */ } /* -** returns the index of a `key' for table traversals. First goes all +** returns the index of a 'key' for table traversals. First goes all ** elements in the array part, then elements in the hash part. The -** beginning of a traversal is signalled by -1. +** beginning of a traversal is signaled by 0. */ -static int findindex (lua_State *L, Table *t, StkId key) { - int i; - if (ttisnil(key)) return -1; /* first iteration */ +static unsigned int findindex (lua_State *L, Table *t, StkId key) { + unsigned int i; + if (ttisnil(key)) return 0; /* first iteration */ i = arrayindex(key); - if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ - return i-1; /* yes; that's the index (corrected to C) */ + if (i != 0 && i <= t->sizearray) /* is 'key' inside array part? */ + return i; /* yes; that's the index */ else { + int nx; Node *n = mainposition(t, key); - do { /* check whether `key' is somewhere in the chain */ - /* key may be dead already, but it is ok to use it in `next' */ - if (luaO_rawequalObj(key2tval(n), key) || - (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) && - gcvalue(gkey(n)) == gcvalue(key))) { + for (;;) { /* check whether 'key' is somewhere in the chain */ + /* key may be dead already, but it is ok to use it in 'next' */ + if (luaV_rawequalobj(gkey(n), key) || + (ttisdeadkey(gkey(n)) && iscollectable(key) && + deadvalue(gkey(n)) == gcvalue(key))) { i = cast_int(n - gnode(t, 0)); /* key index in hash table */ /* hash elements are numbered after array ones */ - return i + t->sizearray; + return (i + 1) + t->sizearray; } - else n = gnext(n); - } while (n); - luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ - return 0; /* to avoid warnings */ + nx = gnext(n); + if (nx == 0) + luaG_runerror(L, "invalid key to 'next'"); /* key not found */ + else n += nx; + } } } int luaH_next (lua_State *L, Table *t, StkId key) { - int i = findindex(L, t, key); /* find original element */ - for (i++; i < t->sizearray; i++) { /* try first array part */ + unsigned int i = findindex(L, t, key); /* find original element */ + for (; i < t->sizearray; i++) { /* try first array part */ if (!ttisnil(&t->array[i])) { /* a non-nil value? */ - setnvalue(key, cast_num(i+1)); + setivalue(key, i + 1); setobj2s(L, key+1, &t->array[i]); return 1; } } - for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ + for (i -= t->sizearray; cast_int(i) < sizenode(t); i++) { /* hash part */ if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ - setobj2s(L, key, key2tval(gnode(t, i))); + setobj2s(L, key, gkey(gnode(t, i))); setobj2s(L, key+1, gval(gnode(t, i))); return 1; } @@ -185,33 +211,39 @@ int luaH_next (lua_State *L, Table *t, StkId key) { ** ============================================================== */ - -static int computesizes (int nums[], int *narray) { +/* +** Compute the optimal size for the array part of table 't'. 'nums' is a +** "count array" where 'nums[i]' is the number of integers in the table +** between 2^(i - 1) + 1 and 2^i. 'pna' enters with the total number of +** integer keys in the table and leaves with the number of keys that +** will go to the array part; return the optimal size. +*/ +static unsigned int computesizes (unsigned int nums[], unsigned int *pna) { int i; - int twotoi; /* 2^i */ - int a = 0; /* number of elements smaller than 2^i */ - int na = 0; /* number of elements to go to array part */ - int n = 0; /* optimal size for array part */ - for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) { + unsigned int twotoi; /* 2^i (candidate for optimal size) */ + unsigned int a = 0; /* number of elements smaller than 2^i */ + unsigned int na = 0; /* number of elements to go to array part */ + unsigned int optimal = 0; /* optimal size for array part */ + /* loop while keys can fill more than half of total size */ + for (i = 0, twotoi = 1; *pna > twotoi / 2; i++, twotoi *= 2) { if (nums[i] > 0) { a += nums[i]; if (a > twotoi/2) { /* more than half elements present? */ - n = twotoi; /* optimal size (till now) */ - na = a; /* all elements smaller than n will go to array part */ + optimal = twotoi; /* optimal size (till now) */ + na = a; /* all elements up to 'optimal' will go to array part */ } } - if (a == *narray) break; /* all elements already counted */ } - *narray = n; - lua_assert(*narray/2 <= na && na <= *narray); - return na; + lua_assert((optimal == 0 || optimal / 2 < na) && na <= optimal); + *pna = na; + return optimal; } -static int countint (const TValue *key, int *nums) { - int k = arrayindex(key); - if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ - nums[ceillog2(k)]++; /* count as such */ +static int countint (const TValue *key, unsigned int *nums) { + unsigned int k = arrayindex(key); + if (k != 0) { /* is 'key' an appropriate array index? */ + nums[luaO_ceillog2(k)]++; /* count as such */ return 1; } else @@ -219,20 +251,26 @@ static int countint (const TValue *key, int *nums) { } -static int numusearray (const Table *t, int *nums) { +/* +** Count keys in array part of table 't': Fill 'nums[i]' with +** number of keys that will go into corresponding slice and return +** total number of non-nil keys. +*/ +static unsigned int numusearray (const Table *t, unsigned int *nums) { int lg; - int ttlg; /* 2^lg */ - int ause = 0; /* summation of `nums' */ - int i = 1; /* count to traverse all array keys */ - for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */ - int lc = 0; /* counter */ - int lim = ttlg; + unsigned int ttlg; /* 2^lg */ + unsigned int ause = 0; /* summation of 'nums' */ + unsigned int i = 1; /* count to traverse all array keys */ + /* traverse each slice */ + for (lg = 0, ttlg = 1; lg <= MAXABITS; lg++, ttlg *= 2) { + unsigned int lc = 0; /* counter */ + unsigned int lim = ttlg; if (lim > t->sizearray) { lim = t->sizearray; /* adjust upper limit */ if (i > lim) break; /* no more elements to count */ } - /* count elements in range (2^(lg-1), 2^lg] */ + /* count elements in range (2^(lg - 1), 2^lg] */ for (; i <= lim; i++) { if (!ttisnil(&t->array[i-1])) lc++; @@ -244,24 +282,24 @@ static int numusearray (const Table *t, int *nums) { } -static int numusehash (const Table *t, int *nums, int *pnasize) { +static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) { int totaluse = 0; /* total number of elements */ - int ause = 0; /* summation of `nums' */ + int ause = 0; /* elements added to 'nums' (can go to array part) */ int i = sizenode(t); while (i--) { Node *n = &t->node[i]; if (!ttisnil(gval(n))) { - ause += countint(key2tval(n), nums); + ause += countint(gkey(n), nums); totaluse++; } } - *pnasize += ause; + *pna += ause; return totaluse; } -static void setarrayvector (lua_State *L, Table *t, int size) { - int i; +static void setarrayvector (lua_State *L, Table *t, unsigned int size) { + unsigned int i; luaM_reallocvector(L, t->array, t->sizearray, size, TValue); for (i=t->sizearray; iarray[i]); @@ -269,23 +307,23 @@ static void setarrayvector (lua_State *L, Table *t, int size) { } -static void setnodevector (lua_State *L, Table *t, int size) { +static void setnodevector (lua_State *L, Table *t, unsigned int size) { int lsize; if (size == 0) { /* no elements to hash part? */ - t->node = cast(Node *, dummynode); /* use common `dummynode' */ + t->node = cast(Node *, dummynode); /* use common 'dummynode' */ lsize = 0; } else { int i; - lsize = ceillog2(size); - if (lsize > MAXBITS) + lsize = luaO_ceillog2(size); + if (lsize > MAXHBITS) luaG_runerror(L, "table overflow"); size = twoto(lsize); t->node = luaM_newvector(L, size, Node); - for (i=0; isizearray; +void luaH_resize (lua_State *L, Table *t, unsigned int nasize, + unsigned int nhsize) { + unsigned int i; + int j; + unsigned int oldasize = t->sizearray; int oldhsize = t->lsizenode; Node *nold = t->node; /* save old hash ... */ if (nasize > oldasize) /* array part must grow? */ setarrayvector(L, t, nasize); /* create new hash part with appropriate size */ - setnodevector(L, t, nhsize); + setnodevector(L, t, nhsize); if (nasize < oldasize) { /* array part must shrink? */ t->sizearray = nasize; /* re-insert elements from vanishing slice */ for (i=nasize; iarray[i])) - setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]); + luaH_setint(L, t, i + 1, &t->array[i]); } /* shrink array */ luaM_reallocvector(L, t->array, oldasize, nasize, TValue); } /* re-insert elements from hash part */ - for (i = twoto(oldhsize) - 1; i >= 0; i--) { - Node *old = nold+i; - if (!ttisnil(gval(old))) - setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old)); + for (j = twoto(oldhsize) - 1; j >= 0; j--) { + Node *old = nold + j; + if (!ttisnil(gval(old))) { + /* doesn't need barrier/invalidate cache, as entry was + already present in the table */ + setobjt2t(L, luaH_set(L, t, gkey(old)), gval(old)); + } } - if (nold != dummynode) - luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ + if (!isdummy(nold)) + luaM_freearray(L, nold, cast(size_t, twoto(oldhsize))); /* free old hash */ } -void luaH_resizearray (lua_State *L, Table *t, int nasize) { - int nsize = (t->node == dummynode) ? 0 : sizenode(t); - resize(L, t, nasize, nsize); +void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize) { + int nsize = isdummy(t->node) ? 0 : sizenode(t); + luaH_resize(L, t, nasize, nsize); } - +/* +** nums[i] = number of keys 'k' where 2^(i - 1) < k <= 2^i +*/ static void rehash (lua_State *L, Table *t, const TValue *ek) { - int nasize, na; - int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */ + unsigned int asize; /* optimal size for array part */ + unsigned int na; /* number of keys in the array part */ + unsigned int nums[MAXABITS + 1]; int i; int totaluse; - for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */ - nasize = numusearray(t, nums); /* count keys in array part */ - totaluse = nasize; /* all those keys are integer keys */ - totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */ + for (i = 0; i <= MAXABITS; i++) nums[i] = 0; /* reset counts */ + na = numusearray(t, nums); /* count keys in array part */ + totaluse = na; /* all those keys are integer keys */ + totaluse += numusehash(t, nums, &na); /* count keys in hash part */ /* count extra key */ - nasize += countint(ek, nums); + na += countint(ek, nums); totaluse++; /* compute new size for array part */ - na = computesizes(nums, &nasize); + asize = computesizes(nums, &na); /* resize the table to new computed sizes */ - resize(L, t, nasize, totaluse - na); + luaH_resize(L, t, asize, totaluse - na); } @@ -355,32 +401,29 @@ static void rehash (lua_State *L, Table *t, const TValue *ek) { */ -Table *luaH_new (lua_State *L, int narray, int nhash) { - Table *t = luaM_new(L, Table); - luaC_link(L, obj2gco(t), LUA_TTABLE); +Table *luaH_new (lua_State *L) { + GCObject *o = luaC_newobj(L, LUA_TTABLE, sizeof(Table)); + Table *t = gco2t(o); t->metatable = NULL; t->flags = cast_byte(~0); - /* temporary values (kept only if some malloc fails) */ t->array = NULL; t->sizearray = 0; - t->lsizenode = 0; - t->node = cast(Node *, dummynode); - setarrayvector(L, t, narray); - setnodevector(L, t, nhash); + setnodevector(L, t, 0); return t; } void luaH_free (lua_State *L, Table *t) { - if (t->node != dummynode) - luaM_freearray(L, t->node, sizenode(t), Node); - luaM_freearray(L, t->array, t->sizearray, TValue); + if (!isdummy(t->node)) + luaM_freearray(L, t->node, cast(size_t, sizenode(t))); + luaM_freearray(L, t->array, t->sizearray); luaM_free(L, t); } static Node *getfreepos (Table *t) { - while (t->lastfree-- > t->node) { + while (t->lastfree > t->node) { + t->lastfree--; if (ttisnil(gkey(t->lastfree))) return t->lastfree; } @@ -390,40 +433,59 @@ static Node *getfreepos (Table *t) { /* -** inserts a new key into a hash table; first, check whether key's main -** position is free. If not, check whether colliding node is in its main -** position or not: if it is not, move colliding node to an empty place and -** put new key in its main position; otherwise (colliding node is in its main -** position), new key goes to an empty position. +** inserts a new key into a hash table; first, check whether key's main +** position is free. If not, check whether colliding node is in its main +** position or not: if it is not, move colliding node to an empty place and +** put new key in its main position; otherwise (colliding node is in its main +** position), new key goes to an empty position. */ -static TValue *newkey (lua_State *L, Table *t, const TValue *key) { - Node *mp = mainposition(t, key); - if (!ttisnil(gval(mp)) || mp == dummynode) { +TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { + Node *mp; + TValue aux; + if (ttisnil(key)) luaG_runerror(L, "table index is nil"); + else if (ttisfloat(key)) { + lua_Integer k; + if (luaV_tointeger(key, &k, 0)) { /* index is int? */ + setivalue(&aux, k); + key = &aux; /* insert it as an integer */ + } + else if (luai_numisnan(fltvalue(key))) + luaG_runerror(L, "table index is NaN"); + } + mp = mainposition(t, key); + if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ Node *othern; - Node *n = getfreepos(t); /* get a free place */ - if (n == NULL) { /* cannot find a free place? */ + Node *f = getfreepos(t); /* get a free place */ + if (f == NULL) { /* cannot find a free place? */ rehash(L, t, key); /* grow table */ - return luaH_set(L, t, key); /* re-insert key into grown table */ + /* whatever called 'newkey' takes care of TM cache */ + return luaH_set(L, t, key); /* insert key into grown table */ } - lua_assert(n != dummynode); - othern = mainposition(t, key2tval(mp)); + lua_assert(!isdummy(f)); + othern = mainposition(t, gkey(mp)); if (othern != mp) { /* is colliding node out of its main position? */ /* yes; move colliding node into free position */ - while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ - gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ - *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ - gnext(mp) = NULL; /* now `mp' is free */ + while (othern + gnext(othern) != mp) /* find previous */ + othern += gnext(othern); + gnext(othern) = cast_int(f - othern); /* rechain to point to 'f' */ + *f = *mp; /* copy colliding node into free pos. (mp->next also goes) */ + if (gnext(mp) != 0) { + gnext(f) += cast_int(mp - f); /* correct 'next' */ + gnext(mp) = 0; /* now 'mp' is free */ + } setnilvalue(gval(mp)); } else { /* colliding node is in its own main position */ /* new node will go into free position */ - gnext(n) = gnext(mp); /* chain new position */ - gnext(mp) = n; - mp = n; + if (gnext(mp) != 0) + gnext(f) = cast_int((mp + gnext(mp)) - f); /* chain new position */ + else lua_assert(gnext(f) == 0); + gnext(mp) = cast_int(f - mp); + mp = f; } } - gkey(mp)->value = key->value; gkey(mp)->tt = key->tt; - luaC_barriert(L, t, key); + setnodekey(L, &mp->i_key, key); + luaC_barrierback(L, t, key); lua_assert(ttisnil(gval(mp))); return gval(mp); } @@ -432,34 +494,73 @@ static TValue *newkey (lua_State *L, Table *t, const TValue *key) { /* ** search function for integers */ -const TValue *luaH_getnum (Table *t, int key) { +const TValue *luaH_getint (Table *t, lua_Integer key) { /* (1 <= key && key <= t->sizearray) */ - if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) - return &t->array[key-1]; + if (l_castS2U(key) - 1 < t->sizearray) + return &t->array[key - 1]; else { - lua_Number nk = cast_num(key); - Node *n = hashnum(t, nk); - do { /* check whether `key' is somewhere in the chain */ - if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) + Node *n = hashint(t, key); + for (;;) { /* check whether 'key' is somewhere in the chain */ + if (ttisinteger(gkey(n)) && ivalue(gkey(n)) == key) return gval(n); /* that's it */ - else n = gnext(n); - } while (n); + else { + int nx = gnext(n); + if (nx == 0) break; + n += nx; + } + } return luaO_nilobject; } } /* -** search function for strings +** search function for short strings */ -const TValue *luaH_getstr (Table *t, TString *key) { +const TValue *luaH_getshortstr (Table *t, TString *key) { Node *n = hashstr(t, key); - do { /* check whether `key' is somewhere in the chain */ - if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key) + lua_assert(key->tt == LUA_TSHRSTR); + for (;;) { /* check whether 'key' is somewhere in the chain */ + const TValue *k = gkey(n); + if (ttisshrstring(k) && eqshrstr(tsvalue(k), key)) return gval(n); /* that's it */ - else n = gnext(n); - } while (n); - return luaO_nilobject; + else { + int nx = gnext(n); + if (nx == 0) + return luaO_nilobject; /* not found */ + n += nx; + } + } +} + + +/* +** "Generic" get version. (Not that generic: not valid for integers, +** which may be in array part, nor for floats with integral values.) +*/ +static const TValue *getgeneric (Table *t, const TValue *key) { + Node *n = mainposition(t, key); + for (;;) { /* check whether 'key' is somewhere in the chain */ + if (luaV_rawequalobj(gkey(n), key)) + return gval(n); /* that's it */ + else { + int nx = gnext(n); + if (nx == 0) + return luaO_nilobject; /* not found */ + n += nx; + } + } +} + + +const TValue *luaH_getstr (Table *t, TString *key) { + if (key->tt == LUA_TSHRSTR) + return luaH_getshortstr(t, key); + else { /* for long strings, use generic case */ + TValue ko; + setsvalue(cast(lua_State *, NULL), &ko, key); + return getgeneric(t, &ko); + } } @@ -468,85 +569,65 @@ const TValue *luaH_getstr (Table *t, TString *key) { */ const TValue *luaH_get (Table *t, const TValue *key) { switch (ttype(key)) { + case LUA_TSHRSTR: return luaH_getshortstr(t, tsvalue(key)); + case LUA_TNUMINT: return luaH_getint(t, ivalue(key)); case LUA_TNIL: return luaO_nilobject; - case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); - case LUA_TNUMBER: { - int k; - lua_Number n = nvalue(key); - lua_number2int(k, n); - if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */ - return luaH_getnum(t, k); /* use specialized version */ - /* else go through */ - } - default: { - Node *n = mainposition(t, key); - do { /* check whether `key' is somewhere in the chain */ - if (luaO_rawequalObj(key2tval(n), key)) - return gval(n); /* that's it */ - else n = gnext(n); - } while (n); - return luaO_nilobject; - } + case LUA_TNUMFLT: { + lua_Integer k; + if (luaV_tointeger(key, &k, 0)) /* index is int? */ + return luaH_getint(t, k); /* use specialized version */ + /* else... */ + } /* FALLTHROUGH */ + default: + return getgeneric(t, key); } } +/* +** beware: when using this function you probably need to check a GC +** barrier and invalidate the TM cache. +*/ TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { const TValue *p = luaH_get(t, key); - t->flags = 0; if (p != luaO_nilobject) return cast(TValue *, p); - else { - if (ttisnil(key)) luaG_runerror(L, "table index is nil"); - else if (ttisnumber(key) && luai_numisnan(nvalue(key))) - luaG_runerror(L, "table index is NaN"); - return newkey(L, t, key); - } + else return luaH_newkey(L, t, key); } -TValue *luaH_setnum (lua_State *L, Table *t, int key) { - const TValue *p = luaH_getnum(t, key); +void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) { + const TValue *p = luaH_getint(t, key); + TValue *cell; if (p != luaO_nilobject) - return cast(TValue *, p); + cell = cast(TValue *, p); else { TValue k; - setnvalue(&k, cast_num(key)); - return newkey(L, t, &k); - } -} - - -TValue *luaH_setstr (lua_State *L, Table *t, TString *key) { - const TValue *p = luaH_getstr(t, key); - if (p != luaO_nilobject) - return cast(TValue *, p); - else { - TValue k; - setsvalue(L, &k, key); - return newkey(L, t, &k); + setivalue(&k, key); + cell = luaH_newkey(L, t, &k); } + setobj2t(L, cell, value); } static int unbound_search (Table *t, unsigned int j) { unsigned int i = j; /* i is zero or a present index */ j++; - /* find `i' and `j' such that i is present and j is not */ - while (!ttisnil(luaH_getnum(t, j))) { + /* find 'i' and 'j' such that i is present and j is not */ + while (!ttisnil(luaH_getint(t, j))) { i = j; - j *= 2; - if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ + if (j > cast(unsigned int, MAX_INT)/2) { /* overflow? */ /* table was built with bad purposes: resort to linear search */ i = 1; - while (!ttisnil(luaH_getnum(t, i))) i++; + while (!ttisnil(luaH_getint(t, i))) i++; return i - 1; } + j *= 2; } /* now do a binary search between them */ while (j - i > 1) { unsigned int m = (i+j)/2; - if (ttisnil(luaH_getnum(t, m))) j = m; + if (ttisnil(luaH_getint(t, m))) j = m; else i = m; } return i; @@ -554,7 +635,7 @@ static int unbound_search (Table *t, unsigned int j) { /* -** Try to find a boundary in table `t'. A `boundary' is an integer index +** Try to find a boundary in table 't'. A 'boundary' is an integer index ** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). */ int luaH_getn (Table *t) { @@ -570,7 +651,7 @@ int luaH_getn (Table *t) { return i; } /* else must find a boundary in hash part */ - else if (t->node == dummynode) /* hash part is empty? */ + else if (isdummy(t->node)) /* hash part is empty? */ return j; /* that is easy... */ else return unbound_search(t, j); } @@ -583,6 +664,6 @@ Node *luaH_mainposition (const Table *t, const TValue *key) { return mainposition(t, key); } -int luaH_isdummy (Node *n) { return n == dummynode; } +int luaH_isdummy (Node *n) { return isdummy(n); } #endif diff --git a/app/src/main/jni/lua/ltable.h b/app/src/main/jni/lua/ltable.h index f5b9d5e..213cc13 100644 --- a/app/src/main/jni/lua/ltable.h +++ b/app/src/main/jni/lua/ltable.h @@ -1,5 +1,5 @@ /* -** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: ltable.h,v 2.21 2015/11/03 15:47:30 roberto Exp $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -11,21 +11,39 @@ #define gnode(t,i) (&(t)->node[i]) -#define gkey(n) (&(n)->i_key.nk) #define gval(n) (&(n)->i_val) #define gnext(n) ((n)->i_key.nk.next) -#define key2tval(n) (&(n)->i_key.tvk) +/* 'const' to avoid wrong writings that can mess up field 'next' */ +#define gkey(n) cast(const TValue*, (&(n)->i_key.tvk)) -LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); -LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key); +/* +** writable version of 'gkey'; allows updates to individual fields, +** but not to the whole (which has incompatible type) +*/ +#define wgkey(n) (&(n)->i_key.nk) + +#define invalidateTMcache(t) ((t)->flags = 0) + + +/* returns the key, given the value of a table entry */ +#define keyfromval(v) \ + (gkey(cast(Node *, cast(char *, (v)) - offsetof(Node, i_val)))) + + +LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key); +LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key, + TValue *value); +LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key); LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); -LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key); LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); +LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key); LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); -LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash); -LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize); +LUAI_FUNC Table *luaH_new (lua_State *L); +LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned int nasize, + unsigned int nhsize); +LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize); LUAI_FUNC void luaH_free (lua_State *L, Table *t); LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); LUAI_FUNC int luaH_getn (Table *t); diff --git a/app/src/main/jni/lua/ltablib.c b/app/src/main/jni/lua/ltablib.c index b6d9cb4..98b2f87 100644 --- a/app/src/main/jni/lua/ltablib.c +++ b/app/src/main/jni/lua/ltablib.c @@ -1,58 +1,64 @@ /* -** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $ +** $Id: ltablib.c,v 1.93 2016/02/25 19:41:54 roberto Exp $ ** Library for Table Manipulation ** See Copyright Notice in lua.h */ - -#include - #define ltablib_c #define LUA_LIB +#include "lprefix.h" + + +#include +#include +#include + #include "lua.h" #include "lauxlib.h" #include "lualib.h" -#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) +/* +** Operations that an object must define to mimic a table +** (some functions only need some of them) +*/ +#define TAB_R 1 /* read */ +#define TAB_W 2 /* write */ +#define TAB_L 4 /* length */ +#define TAB_RW (TAB_R | TAB_W) /* read/write */ -static int foreachi (lua_State *L) { - int i; - int n = aux_getn(L, 1); - luaL_checktype(L, 2, LUA_TFUNCTION); - for (i=1; i <= n; i++) { - lua_pushvalue(L, 2); /* function */ - lua_pushinteger(L, i); /* 1st argument */ - lua_rawgeti(L, 1, i); /* 2nd argument */ - lua_call(L, 2, 1); - if (!lua_isnil(L, -1)) - return 1; - lua_pop(L, 1); /* remove nil result */ - } - return 0; +#define aux_getn(L,n,w) (checktab(L, n, (w) | TAB_L), luaL_len(L, n)) + + +static int checkfield (lua_State *L, const char *key, int n) { + lua_pushstring(L, key); + return (lua_rawget(L, -n) != LUA_TNIL); } -static int foreach (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checktype(L, 2, LUA_TFUNCTION); - lua_pushnil(L); /* first key */ - while (lua_next(L, 1)) { - lua_pushvalue(L, 2); /* function */ - lua_pushvalue(L, -3); /* key */ - lua_pushvalue(L, -3); /* value */ - lua_call(L, 2, 1); - if (!lua_isnil(L, -1)) - return 1; - lua_pop(L, 2); /* remove value and result */ +/* +** Check that 'arg' either is a table or can behave like one (that is, +** has a metatable with the required metamethods) +*/ +static void checktab (lua_State *L, int arg, int what) { + if (lua_type(L, arg) != LUA_TTABLE) { /* is it not a table? */ + int n = 1; /* number of elements to pop */ + if (lua_getmetatable(L, arg) && /* must have metatable */ + (!(what & TAB_R) || checkfield(L, "__index", ++n)) && + (!(what & TAB_W) || checkfield(L, "__newindex", ++n)) && + (!(what & TAB_L) || checkfield(L, "__len", ++n))) { + lua_pop(L, n); /* pop metatable and tested metamethods */ + } + else + luaL_checktype(L, arg, LUA_TTABLE); /* force an error */ } - return 0; } +#if defined(LUA_COMPAT_MAXN) static int maxn (lua_State *L) { lua_Number max = 0; luaL_checktype(L, 1, LUA_TTABLE); @@ -67,88 +73,106 @@ static int maxn (lua_State *L) { lua_pushnumber(L, max); return 1; } - - -static int getn (lua_State *L) { - lua_pushinteger(L, aux_getn(L, 1)); - return 1; -} - - -static int setn (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); -#ifndef luaL_setn - luaL_setn(L, 1, luaL_checkint(L, 2)); -#else - luaL_error(L, LUA_QL("setn") " is obsolete"); #endif - lua_pushvalue(L, 1); - return 1; -} static int tinsert (lua_State *L) { - int e = aux_getn(L, 1) + 1; /* first empty element */ - int pos; /* where to insert new element */ + lua_Integer e = aux_getn(L, 1, TAB_RW) + 1; /* first empty element */ + lua_Integer pos; /* where to insert new element */ switch (lua_gettop(L)) { case 2: { /* called with only 2 arguments */ pos = e; /* insert new element at the end */ break; } case 3: { - int i; - pos = luaL_checkint(L, 2); /* 2nd argument is the position */ - if (pos > e) e = pos; /* `grow' array if necessary */ + lua_Integer i; + pos = luaL_checkinteger(L, 2); /* 2nd argument is the position */ + luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds"); for (i = e; i > pos; i--) { /* move up elements */ - lua_rawgeti(L, 1, i-1); - lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ + lua_geti(L, 1, i - 1); + lua_seti(L, 1, i); /* t[i] = t[i - 1] */ } break; } default: { - return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); + return luaL_error(L, "wrong number of arguments to 'insert'"); } } - luaL_setn(L, 1, e); /* new size */ - lua_rawseti(L, 1, pos); /* t[pos] = v */ + lua_seti(L, 1, pos); /* t[pos] = v */ return 0; } static int tremove (lua_State *L) { - int e = aux_getn(L, 1); - int pos = luaL_optint(L, 2, e); - if (!(1 <= pos && pos <= e)) /* position is outside bounds? */ - return 0; /* nothing to remove */ - luaL_setn(L, 1, e - 1); /* t.n = n-1 */ - lua_rawgeti(L, 1, pos); /* result = t[pos] */ - for ( ;pos= f) { /* otherwise, nothing to move */ + lua_Integer n, i; + luaL_argcheck(L, f > 0 || e < LUA_MAXINTEGER + f, 3, + "too many elements to move"); + n = e - f + 1; /* number of elements to move */ + luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4, + "destination wrap around"); + if (t > e || t <= f || (tt != 1 && !lua_compare(L, 1, tt, LUA_OPEQ))) { + for (i = 0; i < n; i++) { + lua_geti(L, 1, f + i); + lua_seti(L, tt, t + i); + } + } + else { + for (i = n - 1; i >= 0; i--) { + lua_geti(L, 1, f + i); + lua_seti(L, tt, t + i); + } + } + } + lua_pushvalue(L, tt); /* return destination table */ + return 1; +} + + +static void addfield (lua_State *L, luaL_Buffer *b, lua_Integer i) { + lua_geti(L, 1, i); if (!lua_isstring(L, -1)) - luaL_error(L, "invalid value (%s) at index %d in table for " - LUA_QL("concat"), luaL_typename(L, -1), i); - luaL_addvalue(b); + luaL_error(L, "invalid value (%s) at index %d in table for 'concat'", + luaL_typename(L, -1), i); + luaL_addvalue(b); } static int tconcat (lua_State *L) { luaL_Buffer b; + lua_Integer last = aux_getn(L, 1, TAB_R); size_t lsep; - int i, last; const char *sep = luaL_optlstring(L, 2, "", &lsep); - luaL_checktype(L, 1, LUA_TTABLE); - i = luaL_optint(L, 3, 1); - last = luaL_opt(L, luaL_checkint, 4, luaL_getn(L, 1)); + lua_Integer i = luaL_optinteger(L, 3, 1); + last = luaL_optinteger(L, 4, last); luaL_buffinit(L, &b); for (; i < last; i++) { addfield(L, &b, i); @@ -161,105 +185,238 @@ static int tconcat (lua_State *L) { } +/* +** {====================================================== +** Pack/unpack +** ======================================================= +*/ + +static int pack (lua_State *L) { + int i; + int n = lua_gettop(L); /* number of elements to pack */ + lua_createtable(L, n, 1); /* create result table */ + lua_insert(L, 1); /* put it at index 1 */ + for (i = n; i >= 1; i--) /* assign elements */ + lua_seti(L, 1, i); + lua_pushinteger(L, n); + lua_setfield(L, 1, "n"); /* t.n = number of elements */ + return 1; /* return table */ +} + + +static int unpack (lua_State *L) { + lua_Unsigned n; + lua_Integer i = luaL_optinteger(L, 2, 1); + lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1)); + if (i > e) return 0; /* empty range */ + n = (lua_Unsigned)e - i; /* number of elements minus 1 (avoid overflows) */ + if (n >= (unsigned int)INT_MAX || !lua_checkstack(L, (int)(++n))) + return luaL_error(L, "too many results to unpack"); + for (; i < e; i++) { /* push arg[i..e - 1] (to avoid overflows) */ + lua_geti(L, 1, i); + } + lua_geti(L, 1, e); /* push last element */ + return (int)n; +} + +/* }====================================================== */ + + /* ** {====================================================== ** Quicksort -** (based on `Algorithms in MODULA-3', Robert Sedgewick; +** (based on 'Algorithms in MODULA-3', Robert Sedgewick; ** Addison-Wesley, 1993.) +** ======================================================= +*/ + + +/* type for array indices */ +typedef unsigned int IdxT; + + +/* +** Produce a "random" 'unsigned int' to randomize pivot choice. This +** macro is used only when 'sort' detects a big imbalance in the result +** of a partition. (If you don't want/need this "randomness", ~0 is a +** good choice.) */ +#if !defined(l_randomizePivot) /* { */ +#include -static void set2 (lua_State *L, int i, int j) { - lua_rawseti(L, 1, i); - lua_rawseti(L, 1, j); +/* size of 'e' measured in number of 'unsigned int's */ +#define sof(e) (sizeof(e) / sizeof(unsigned int)) + +/* +** Use 'time' and 'clock' as sources of "randomness". Because we don't +** know the types 'clock_t' and 'time_t', we cannot cast them to +** anything without risking overflows. A safe way to use their values +** is to copy them to an array of a known type and use the array values. +*/ +static unsigned int l_randomizePivot (void) { + clock_t c = clock(); + time_t t = time(NULL); + unsigned int buff[sof(c) + sof(t)]; + unsigned int i, rnd = 0; + memcpy(buff, &c, sof(c) * sizeof(unsigned int)); + memcpy(buff + sof(c), &t, sof(t) * sizeof(unsigned int)); + for (i = 0; i < sof(buff); i++) + rnd += buff[i]; + return rnd; +} + +#endif /* } */ + + +/* arrays larger than 'RANLIMIT' may use randomized pivots */ +#define RANLIMIT 100u + + +static void set2 (lua_State *L, IdxT i, IdxT j) { + lua_seti(L, 1, i); + lua_seti(L, 1, j); } + +/* +** Return true iff value at stack index 'a' is less than the value at +** index 'b' (according to the order of the sort). +*/ static int sort_comp (lua_State *L, int a, int b) { - if (!lua_isnil(L, 2)) { /* function? */ + if (lua_isnil(L, 2)) /* no function? */ + return lua_compare(L, a, b, LUA_OPLT); /* a < b */ + else { /* function */ int res; - lua_pushvalue(L, 2); + lua_pushvalue(L, 2); /* push function */ lua_pushvalue(L, a-1); /* -1 to compensate function */ - lua_pushvalue(L, b-2); /* -2 to compensate function and `a' */ - lua_call(L, 2, 1); - res = lua_toboolean(L, -1); - lua_pop(L, 1); + lua_pushvalue(L, b-2); /* -2 to compensate function and 'a' */ + lua_call(L, 2, 1); /* call function */ + res = lua_toboolean(L, -1); /* get result */ + lua_pop(L, 1); /* pop result */ return res; } - else /* a < b? */ - return lua_lessthan(L, a, b); } -static void auxsort (lua_State *L, int l, int u) { - while (l < u) { /* for tail recursion */ - int i, j; - /* sort elements a[l], a[(l+u)/2] and a[u] */ - lua_rawgeti(L, 1, l); - lua_rawgeti(L, 1, u); - if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */ - set2(L, l, u); /* swap a[l] - a[u] */ + +/* +** Does the partition: Pivot P is at the top of the stack. +** precondition: a[lo] <= P == a[up-1] <= a[up], +** so it only needs to do the partition from lo + 1 to up - 2. +** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up] +** returns 'i'. +*/ +static IdxT partition (lua_State *L, IdxT lo, IdxT up) { + IdxT i = lo; /* will be incremented before first use */ + IdxT j = up - 1; /* will be decremented before first use */ + /* loop invariant: a[lo .. i] <= P <= a[j .. up] */ + for (;;) { + /* next loop: repeat ++i while a[i] < P */ + while (lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) { + if (i == up - 1) /* a[i] < P but a[up - 1] == P ?? */ + luaL_error(L, "invalid order function for sorting"); + lua_pop(L, 1); /* remove a[i] */ + } + /* after the loop, a[i] >= P and a[lo .. i - 1] < P */ + /* next loop: repeat --j while P < a[j] */ + while (lua_geti(L, 1, --j), sort_comp(L, -3, -1)) { + if (j < i) /* j < i but a[j] > P ?? */ + luaL_error(L, "invalid order function for sorting"); + lua_pop(L, 1); /* remove a[j] */ + } + /* after the loop, a[j] <= P and a[j + 1 .. up] >= P */ + if (j < i) { /* no elements out of place? */ + /* a[lo .. i - 1] <= P <= a[j + 1 .. i .. up] */ + lua_pop(L, 1); /* pop a[j] */ + /* swap pivot (a[up - 1]) with a[i] to satisfy pos-condition */ + set2(L, up - 1, i); + return i; + } + /* otherwise, swap a[i] - a[j] to restore invariant and repeat */ + set2(L, i, j); + } +} + + +/* +** Choose an element in the middle (2nd-3th quarters) of [lo,up] +** "randomized" by 'rnd' +*/ +static IdxT choosePivot (IdxT lo, IdxT up, unsigned int rnd) { + IdxT r4 = (up - lo) / 4; /* range/4 */ + IdxT p = rnd % (r4 * 2) + (lo + r4); + lua_assert(lo + r4 <= p && p <= up - r4); + return p; +} + + +/* +** QuickSort algorithm (recursive function) +*/ +static void auxsort (lua_State *L, IdxT lo, IdxT up, + unsigned int rnd) { + while (lo < up) { /* loop for tail recursion */ + IdxT p; /* Pivot index */ + IdxT n; /* to be used later */ + /* sort elements 'lo', 'p', and 'up' */ + lua_geti(L, 1, lo); + lua_geti(L, 1, up); + if (sort_comp(L, -1, -2)) /* a[up] < a[lo]? */ + set2(L, lo, up); /* swap a[lo] - a[up] */ else - lua_pop(L, 2); - if (u-l == 1) break; /* only 2 elements */ - i = (l+u)/2; - lua_rawgeti(L, 1, i); - lua_rawgeti(L, 1, l); - if (sort_comp(L, -2, -1)) /* a[i]= P */ - while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { - if (i>u) luaL_error(L, "invalid order function for sorting"); - lua_pop(L, 1); /* remove a[i] */ - } - /* repeat --j until a[j] <= P */ - while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { - if (j n) /* partition too imbalanced? */ + rnd = l_randomizePivot(); /* try a new randomization */ + } /* tail call auxsort(L, lo, up, rnd) */ } + static int sort (lua_State *L) { - int n = aux_getn(L, 1); - luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */ - if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ - luaL_checktype(L, 2, LUA_TFUNCTION); - lua_settop(L, 2); /* make sure there is two arguments */ - auxsort(L, 1, n); + lua_Integer n = aux_getn(L, 1, TAB_RW); + if (n > 1) { /* non-trivial interval? */ + luaL_argcheck(L, n < INT_MAX, 1, "array too big"); + if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ + luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */ + lua_settop(L, 2); /* make sure there are two arguments */ + auxsort(L, 1, (IdxT)n, 0); + } return 0; } @@ -268,20 +425,26 @@ static int sort (lua_State *L) { static const luaL_Reg tab_funcs[] = { {"concat", tconcat}, - {"foreach", foreach}, - {"foreachi", foreachi}, - {"getn", getn}, +#if defined(LUA_COMPAT_MAXN) {"maxn", maxn}, +#endif {"insert", tinsert}, + {"pack", pack}, + {"unpack", unpack}, {"remove", tremove}, - {"setn", setn}, + {"move", tmove}, {"sort", sort}, {NULL, NULL} }; -LUALIB_API int luaopen_table (lua_State *L) { - luaL_register(L, LUA_TABLIBNAME, tab_funcs); +LUAMOD_API int luaopen_table (lua_State *L) { + luaL_newlib(L, tab_funcs); +#if defined(LUA_COMPAT_UNPACK) + /* _G.unpack = table.unpack */ + lua_getfield(L, -1, "unpack"); + lua_setglobal(L, "unpack"); +#endif return 1; } diff --git a/app/src/main/jni/lua/ltm.c b/app/src/main/jni/lua/ltm.c index c27f0f6..4650cc2 100644 --- a/app/src/main/jni/lua/ltm.c +++ b/app/src/main/jni/lua/ltm.c @@ -1,44 +1,53 @@ /* -** $Id: ltm.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: ltm.c,v 2.37 2016/02/26 19:20:15 roberto Exp $ ** Tag methods ** See Copyright Notice in lua.h */ - -#include - #define ltm_c #define LUA_CORE +#include "lprefix.h" + + +#include + #include "lua.h" +#include "ldebug.h" +#include "ldo.h" #include "lobject.h" #include "lstate.h" #include "lstring.h" #include "ltable.h" #include "ltm.h" +#include "lvm.h" +static const char udatatypename[] = "userdata"; -const char *const luaT_typenames[] = { - "nil", "boolean", "userdata", "number", - "string", "table", "function", "userdata", "thread", - "proto", "upval" +LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = { + "no value", + "nil", "boolean", udatatypename, "number", + "string", "table", "function", udatatypename, "thread", + "proto" /* this last case is used for tests only */ }; void luaT_init (lua_State *L) { static const char *const luaT_eventname[] = { /* ORDER TM */ "__index", "__newindex", - "__gc", "__mode", "__eq", - "__add", "__sub", "__mul", "__div", "__mod", - "__pow", "__unm", "__len", "__lt", "__le", + "__gc", "__mode", "__len", "__eq", + "__add", "__sub", "__mul", "__mod", "__pow", + "__div", "__idiv", + "__band", "__bor", "__bxor", "__shl", "__shr", + "__unm", "__bnot", "__lt", "__le", "__concat", "__call" }; int i; for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); - luaS_fix(G(L)->tmname[i]); /* never collect these names */ + luaC_fix(L, obj2gco(G(L)->tmname[i])); /* never collect these names */ } } @@ -48,7 +57,7 @@ void luaT_init (lua_State *L) { ** tag methods */ const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { - const TValue *tm = luaH_getstr(events, ename); + const TValue *tm = luaH_getshortstr(events, ename); lua_assert(event <= TM_EQ); if (ttisnil(tm)) { /* no tag method? */ events->flags |= cast_byte(1u<metatable; break; @@ -68,8 +77,89 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) { mt = uvalue(o)->metatable; break; default: - mt = G(L)->mt[ttype(o)]; + mt = G(L)->mt[ttnov(o)]; + } + return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : luaO_nilobject); +} + + +/* +** Return the name of the type of an object. For tables and userdata +** with metatable, use their '__name' metafield, if present. +*/ +const char *luaT_objtypename (lua_State *L, const TValue *o) { + Table *mt; + if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) || + (ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL)) { + const TValue *name = luaH_getshortstr(mt, luaS_new(L, "__name")); + if (ttisstring(name)) /* is '__name' a string? */ + return getstr(tsvalue(name)); /* use it as type name */ } - return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); + return ttypename(ttnov(o)); /* else use standard type name */ +} + + +void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, + const TValue *p2, TValue *p3, int hasres) { + ptrdiff_t result = savestack(L, p3); + StkId func = L->top; + setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ + setobj2s(L, func + 1, p1); /* 1st argument */ + setobj2s(L, func + 2, p2); /* 2nd argument */ + L->top += 3; + if (!hasres) /* no result? 'p3' is third argument */ + setobj2s(L, L->top++, p3); /* 3rd argument */ + /* metamethod may yield only when called from Lua code */ + if (isLua(L->ci)) + luaD_call(L, func, hasres); + else + luaD_callnoyield(L, func, hasres); + if (hasres) { /* if has result, move it to its place */ + p3 = restorestack(L, result); + setobjs2s(L, p3, --L->top); + } +} + + +int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2, + StkId res, TMS event) { + const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ + if (ttisnil(tm)) + tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ + if (ttisnil(tm)) return 0; + luaT_callTM(L, tm, p1, p2, res, 1); + return 1; +} + + +void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, + StkId res, TMS event) { + if (!luaT_callbinTM(L, p1, p2, res, event)) { + switch (event) { + case TM_CONCAT: + luaG_concaterror(L, p1, p2); + /* call never returns, but to avoid warnings: *//* FALLTHROUGH */ + case TM_BAND: case TM_BOR: case TM_BXOR: + case TM_SHL: case TM_SHR: case TM_BNOT: { + lua_Number dummy; + if (tonumber(p1, &dummy) && tonumber(p2, &dummy)) + luaG_tointerror(L, p1, p2); + else + luaG_opinterror(L, p1, p2, "perform bitwise operation on"); + } + /* calls never return, but to avoid warnings: *//* FALLTHROUGH */ + default: + luaG_opinterror(L, p1, p2, "perform arithmetic on"); + } + } +} + + +int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2, + TMS event) { + if (!luaT_callbinTM(L, p1, p2, L->top, event)) + return -1; /* no metamethod */ + else + return !l_isfalse(L->top); } diff --git a/app/src/main/jni/lua/ltm.h b/app/src/main/jni/lua/ltm.h index 64343b7..63db726 100644 --- a/app/src/main/jni/lua/ltm.h +++ b/app/src/main/jni/lua/ltm.h @@ -1,5 +1,5 @@ /* -** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: ltm.h,v 2.22 2016/02/26 19:20:15 roberto Exp $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -13,22 +13,29 @@ /* * WARNING: if you change the order of this enumeration, -* grep "ORDER TM" +* grep "ORDER TM" and "ORDER OP" */ typedef enum { TM_INDEX, TM_NEWINDEX, TM_GC, TM_MODE, - TM_EQ, /* last tag method with `fast' access */ + TM_LEN, + TM_EQ, /* last tag method with fast access */ TM_ADD, TM_SUB, TM_MUL, - TM_DIV, TM_MOD, TM_POW, + TM_DIV, + TM_IDIV, + TM_BAND, + TM_BOR, + TM_BXOR, + TM_SHL, + TM_SHR, TM_UNM, - TM_LEN, + TM_BNOT, TM_LT, TM_LE, TM_CONCAT, @@ -43,12 +50,27 @@ typedef enum { #define fasttm(l,et,e) gfasttm(G(l), et, e) -LUAI_DATA const char *const luaT_typenames[]; +#define ttypename(x) luaT_typenames_[(x) + 1] + +LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS]; +LUAI_FUNC const char *luaT_objtypename (lua_State *L, const TValue *o); + LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event); LUAI_FUNC void luaT_init (lua_State *L); +LUAI_FUNC void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, + const TValue *p2, TValue *p3, int hasres); +LUAI_FUNC int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2, + StkId res, TMS event); +LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, + StkId res, TMS event); +LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1, + const TValue *p2, TMS event); + + + #endif diff --git a/app/src/main/jni/lua/lua.c b/app/src/main/jni/lua/lua.c new file mode 100644 index 0000000..545d23d --- /dev/null +++ b/app/src/main/jni/lua/lua.c @@ -0,0 +1,609 @@ +/* +** $Id: lua.c,v 1.226 2015/08/14 19:11:20 roberto Exp $ +** Lua stand-alone interpreter +** See Copyright Notice in lua.h +*/ + +#define lua_c + +#include "lprefix.h" + + +#include +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#if !defined(LUA_PROMPT) +#define LUA_PROMPT "> " +#define LUA_PROMPT2 ">> " +#endif + +#if !defined(LUA_PROGNAME) +#define LUA_PROGNAME "lua" +#endif + +#if !defined(LUA_MAXINPUT) +#define LUA_MAXINPUT 512 +#endif + +#if !defined(LUA_INIT_VAR) +#define LUA_INIT_VAR "LUA_INIT" +#endif + +#define LUA_INITVARVERSION \ + LUA_INIT_VAR "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR + + +/* +** lua_stdin_is_tty detects whether the standard input is a 'tty' (that +** is, whether we're running lua interactively). +*/ +#if !defined(lua_stdin_is_tty) /* { */ + +#if defined(LUA_USE_POSIX) /* { */ + +#include +#define lua_stdin_is_tty() isatty(0) + +#elif defined(LUA_USE_WINDOWS) /* }{ */ + +#include +#define lua_stdin_is_tty() _isatty(_fileno(stdin)) + +#else /* }{ */ + +/* ISO C definition */ +#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ + +#endif /* } */ + +#endif /* } */ + + +/* +** lua_readline defines how to show a prompt and then read a line from +** the standard input. +** lua_saveline defines how to "save" a read line in a "history". +** lua_freeline defines how to free a line read by lua_readline. +*/ +#if !defined(lua_readline) /* { */ + +#if defined(LUA_USE_READLINE) /* { */ + +#include +#include +#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) +#define lua_saveline(L,line) ((void)L, add_history(line)) +#define lua_freeline(L,b) ((void)L, free(b)) + +#else /* }{ */ + +#define lua_readline(L,b,p) \ + ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ + fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ +#define lua_saveline(L,line) { (void)L; (void)line; } +#define lua_freeline(L,b) { (void)L; (void)b; } + +#endif /* } */ + +#endif /* } */ + + + + +static lua_State *globalL = NULL; + +static const char *progname = LUA_PROGNAME; + + +/* +** Hook set by signal function to stop the interpreter. +*/ +static void lstop (lua_State *L, lua_Debug *ar) { + (void)ar; /* unused arg. */ + lua_sethook(L, NULL, 0, 0); /* reset hook */ + luaL_error(L, "interrupted!"); +} + + +/* +** Function to be called at a C signal. Because a C signal cannot +** just change a Lua state (as there is no proper synchronization), +** this function only sets a hook that, when called, will stop the +** interpreter. +*/ +static void laction (int i) { + signal(i, SIG_DFL); /* if another SIGINT happens, terminate process */ + lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); +} + + +static void print_usage (const char *badoption) { + lua_writestringerror("%s: ", progname); + if (badoption[1] == 'e' || badoption[1] == 'l') + lua_writestringerror("'%s' needs argument\n", badoption); + else + lua_writestringerror("unrecognized option '%s'\n", badoption); + lua_writestringerror( + "usage: %s [options] [script [args]]\n" + "Available options are:\n" + " -e stat execute string 'stat'\n" + " -i enter interactive mode after executing 'script'\n" + " -l name require library 'name'\n" + " -v show version information\n" + " -E ignore environment variables\n" + " -- stop handling options\n" + " - stop handling options and execute stdin\n" + , + progname); +} + + +/* +** Prints an error message, adding the program name in front of it +** (if present) +*/ +static void l_message (const char *pname, const char *msg) { + if (pname) lua_writestringerror("%s: ", pname); + lua_writestringerror("%s\n", msg); +} + + +/* +** Check whether 'status' is not OK and, if so, prints the error +** message on the top of the stack. It assumes that the error object +** is a string, as it was either generated by Lua or by 'msghandler'. +*/ +static int report (lua_State *L, int status) { + if (status != LUA_OK) { + const char *msg = lua_tostring(L, -1); + l_message(progname, msg); + lua_pop(L, 1); /* remove message */ + } + return status; +} + + +/* +** Message handler used to run all chunks +*/ +static int msghandler (lua_State *L) { + const char *msg = lua_tostring(L, 1); + if (msg == NULL) { /* is error object not a string? */ + if (luaL_callmeta(L, 1, "__tostring") && /* does it have a metamethod */ + lua_type(L, -1) == LUA_TSTRING) /* that produces a string? */ + return 1; /* that is the message */ + else + msg = lua_pushfstring(L, "(error object is a %s value)", + luaL_typename(L, 1)); + } + luaL_traceback(L, L, msg, 1); /* append a standard traceback */ + return 1; /* return the traceback */ +} + + +/* +** Interface to 'lua_pcall', which sets appropriate message function +** and C-signal handler. Used to run all chunks. +*/ +static int docall (lua_State *L, int narg, int nres) { + int status; + int base = lua_gettop(L) - narg; /* function index */ + lua_pushcfunction(L, msghandler); /* push message handler */ + lua_insert(L, base); /* put it under function and args */ + globalL = L; /* to be available to 'laction' */ + signal(SIGINT, laction); /* set C-signal handler */ + status = lua_pcall(L, narg, nres, base); + signal(SIGINT, SIG_DFL); /* reset C-signal handler */ + lua_remove(L, base); /* remove message handler from the stack */ + return status; +} + + +static void print_version (void) { + lua_writestring(LUA_COPYRIGHT, strlen(LUA_COPYRIGHT)); + lua_writeline(); +} + + +/* +** Create the 'arg' table, which stores all arguments from the +** command line ('argv'). It should be aligned so that, at index 0, +** it has 'argv[script]', which is the script name. The arguments +** to the script (everything after 'script') go to positive indices; +** other arguments (before the script name) go to negative indices. +** If there is no script name, assume interpreter's name as base. +*/ +static void createargtable (lua_State *L, char **argv, int argc, int script) { + int i, narg; + if (script == argc) script = 0; /* no script name? */ + narg = argc - (script + 1); /* number of positive indices */ + lua_createtable(L, narg, script + 1); + for (i = 0; i < argc; i++) { + lua_pushstring(L, argv[i]); + lua_rawseti(L, -2, i - script); + } + lua_setglobal(L, "arg"); +} + + +static int dochunk (lua_State *L, int status) { + if (status == LUA_OK) status = docall(L, 0, 0); + return report(L, status); +} + + +static int dofile (lua_State *L, const char *name) { + return dochunk(L, luaL_loadfile(L, name)); +} + + +static int dostring (lua_State *L, const char *s, const char *name) { + return dochunk(L, luaL_loadbuffer(L, s, strlen(s), name)); +} + + +/* +** Calls 'require(name)' and stores the result in a global variable +** with the given name. +*/ +static int dolibrary (lua_State *L, const char *name) { + int status; + lua_getglobal(L, "require"); + lua_pushstring(L, name); + status = docall(L, 1, 1); /* call 'require(name)' */ + if (status == LUA_OK) + lua_setglobal(L, name); /* global[name] = require return */ + return report(L, status); +} + + +/* +** Returns the string to be used as a prompt by the interpreter. +*/ +static const char *get_prompt (lua_State *L, int firstline) { + const char *p; + lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2"); + p = lua_tostring(L, -1); + if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2); + return p; +} + +/* mark in error messages for incomplete statements */ +#define EOFMARK "" +#define marklen (sizeof(EOFMARK)/sizeof(char) - 1) + + +/* +** Check whether 'status' signals a syntax error and the error +** message at the top of the stack ends with the above mark for +** incomplete statements. +*/ +static int incomplete (lua_State *L, int status) { + if (status == LUA_ERRSYNTAX) { + size_t lmsg; + const char *msg = lua_tolstring(L, -1, &lmsg); + if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0) { + lua_pop(L, 1); + return 1; + } + } + return 0; /* else... */ +} + + +/* +** Prompt the user, read a line, and push it into the Lua stack. +*/ +static int pushline (lua_State *L, int firstline) { + char buffer[LUA_MAXINPUT]; + char *b = buffer; + size_t l; + const char *prmt = get_prompt(L, firstline); + int readstatus = lua_readline(L, b, prmt); + if (readstatus == 0) + return 0; /* no input (prompt will be popped by caller) */ + lua_pop(L, 1); /* remove prompt */ + l = strlen(b); + if (l > 0 && b[l-1] == '\n') /* line ends with newline? */ + b[--l] = '\0'; /* remove it */ + if (firstline && b[0] == '=') /* for compatibility with 5.2, ... */ + lua_pushfstring(L, "return %s", b + 1); /* change '=' to 'return' */ + else + lua_pushlstring(L, b, l); + lua_freeline(L, b); + return 1; +} + + +/* +** Try to compile line on the stack as 'return ;'; on return, stack +** has either compiled chunk or original line (if compilation failed). +*/ +static int addreturn (lua_State *L) { + const char *line = lua_tostring(L, -1); /* original line */ + const char *retline = lua_pushfstring(L, "return %s;", line); + int status = luaL_loadbuffer(L, retline, strlen(retline), "=stdin"); + if (status == LUA_OK) { + lua_remove(L, -2); /* remove modified line */ + if (line[0] != '\0') /* non empty? */ + lua_saveline(L, line); /* keep history */ + } + else + lua_pop(L, 2); /* pop result from 'luaL_loadbuffer' and modified line */ + return status; +} + + +/* +** Read multiple lines until a complete Lua statement +*/ +static int multiline (lua_State *L) { + for (;;) { /* repeat until gets a complete statement */ + size_t len; + const char *line = lua_tolstring(L, 1, &len); /* get what it has */ + int status = luaL_loadbuffer(L, line, len, "=stdin"); /* try it */ + if (!incomplete(L, status) || !pushline(L, 0)) { + lua_saveline(L, line); /* keep history */ + return status; /* cannot or should not try to add continuation line */ + } + lua_pushliteral(L, "\n"); /* add newline... */ + lua_insert(L, -2); /* ...between the two lines */ + lua_concat(L, 3); /* join them */ + } +} + + +/* +** Read a line and try to load (compile) it first as an expression (by +** adding "return " in front of it) and second as a statement. Return +** the final status of load/call with the resulting function (if any) +** in the top of the stack. +*/ +static int loadline (lua_State *L) { + int status; + lua_settop(L, 0); + if (!pushline(L, 1)) + return -1; /* no input */ + if ((status = addreturn(L)) != LUA_OK) /* 'return ...' did not work? */ + status = multiline(L); /* try as command, maybe with continuation lines */ + lua_remove(L, 1); /* remove line from the stack */ + lua_assert(lua_gettop(L) == 1); + return status; +} + + +/* +** Prints (calling the Lua 'print' function) any values on the stack +*/ +static void l_print (lua_State *L) { + int n = lua_gettop(L); + if (n > 0) { /* any result to be printed? */ + luaL_checkstack(L, LUA_MINSTACK, "too many results to print"); + lua_getglobal(L, "print"); + lua_insert(L, 1); + if (lua_pcall(L, n, 0, 0) != LUA_OK) + l_message(progname, lua_pushfstring(L, "error calling 'print' (%s)", + lua_tostring(L, -1))); + } +} + + +/* +** Do the REPL: repeatedly read (load) a line, evaluate (call) it, and +** print any results. +*/ +static void doREPL (lua_State *L) { + int status; + const char *oldprogname = progname; + progname = NULL; /* no 'progname' on errors in interactive mode */ + while ((status = loadline(L)) != -1) { + if (status == LUA_OK) + status = docall(L, 0, LUA_MULTRET); + if (status == LUA_OK) l_print(L); + else report(L, status); + } + lua_settop(L, 0); /* clear stack */ + lua_writeline(); + progname = oldprogname; +} + + +/* +** Push on the stack the contents of table 'arg' from 1 to #arg +*/ +static int pushargs (lua_State *L) { + int i, n; + if (lua_getglobal(L, "arg") != LUA_TTABLE) + luaL_error(L, "'arg' is not a table"); + n = (int)luaL_len(L, -1); + luaL_checkstack(L, n + 3, "too many arguments to script"); + for (i = 1; i <= n; i++) + lua_rawgeti(L, -i, i); + lua_remove(L, -i); /* remove table from the stack */ + return n; +} + + +static int handle_script (lua_State *L, char **argv) { + int status; + const char *fname = argv[0]; + if (strcmp(fname, "-") == 0 && strcmp(argv[-1], "--") != 0) + fname = NULL; /* stdin */ + status = luaL_loadfile(L, fname); + if (status == LUA_OK) { + int n = pushargs(L); /* push arguments to script */ + status = docall(L, n, LUA_MULTRET); + } + return report(L, status); +} + + + +/* bits of various argument indicators in 'args' */ +#define has_error 1 /* bad option */ +#define has_i 2 /* -i */ +#define has_v 4 /* -v */ +#define has_e 8 /* -e */ +#define has_E 16 /* -E */ + +/* +** Traverses all arguments from 'argv', returning a mask with those +** needed before running any Lua code (or an error code if it finds +** any invalid argument). 'first' returns the first not-handled argument +** (either the script name or a bad argument in case of error). +*/ +static int collectargs (char **argv, int *first) { + int args = 0; + int i; + for (i = 1; argv[i] != NULL; i++) { + *first = i; + if (argv[i][0] != '-') /* not an option? */ + return args; /* stop handling options */ + switch (argv[i][1]) { /* else check option */ + case '-': /* '--' */ + if (argv[i][2] != '\0') /* extra characters after '--'? */ + return has_error; /* invalid option */ + *first = i + 1; + return args; + case '\0': /* '-' */ + return args; /* script "name" is '-' */ + case 'E': + if (argv[i][2] != '\0') /* extra characters after 1st? */ + return has_error; /* invalid option */ + args |= has_E; + break; + case 'i': + args |= has_i; /* (-i implies -v) *//* FALLTHROUGH */ + case 'v': + if (argv[i][2] != '\0') /* extra characters after 1st? */ + return has_error; /* invalid option */ + args |= has_v; + break; + case 'e': + args |= has_e; /* FALLTHROUGH */ + case 'l': /* both options need an argument */ + if (argv[i][2] == '\0') { /* no concatenated argument? */ + i++; /* try next 'argv' */ + if (argv[i] == NULL || argv[i][0] == '-') + return has_error; /* no next argument or it is another option */ + } + break; + default: /* invalid option */ + return has_error; + } + } + *first = i; /* no script name */ + return args; +} + + +/* +** Processes options 'e' and 'l', which involve running Lua code. +** Returns 0 if some code raises an error. +*/ +static int runargs (lua_State *L, char **argv, int n) { + int i; + for (i = 1; i < n; i++) { + int option = argv[i][1]; + lua_assert(argv[i][0] == '-'); /* already checked */ + if (option == 'e' || option == 'l') { + int status; + const char *extra = argv[i] + 2; /* both options need an argument */ + if (*extra == '\0') extra = argv[++i]; + lua_assert(extra != NULL); + status = (option == 'e') + ? dostring(L, extra, "=(command line)") + : dolibrary(L, extra); + if (status != LUA_OK) return 0; + } + } + return 1; +} + + +static int handle_luainit (lua_State *L) { + const char *name = "=" LUA_INITVARVERSION; + const char *init = getenv(name + 1); + if (init == NULL) { + name = "=" LUA_INIT_VAR; + init = getenv(name + 1); /* try alternative name */ + } + if (init == NULL) return LUA_OK; + else if (init[0] == '@') + return dofile(L, init+1); + else + return dostring(L, init, name); +} + + +/* +** Main body of stand-alone interpreter (to be called in protected mode). +** Reads the options and handles them all. +*/ +static int pmain (lua_State *L) { + int argc = (int)lua_tointeger(L, 1); + char **argv = (char **)lua_touserdata(L, 2); + int script; + int args = collectargs(argv, &script); + luaL_checkversion(L); /* check that interpreter has correct version */ + if (argv[0] && argv[0][0]) progname = argv[0]; + if (args == has_error) { /* bad arg? */ + print_usage(argv[script]); /* 'script' has index of bad arg. */ + return 0; + } + if (args & has_v) /* option '-v'? */ + print_version(); + if (args & has_E) { /* option '-E'? */ + lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */ + lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); + } + luaL_openlibs(L); /* open standard libraries */ + createargtable(L, argv, argc, script); /* create table 'arg' */ + if (!(args & has_E)) { /* no option '-E'? */ + if (handle_luainit(L) != LUA_OK) /* run LUA_INIT */ + return 0; /* error running LUA_INIT */ + } + if (!runargs(L, argv, script)) /* execute arguments -e and -l */ + return 0; /* something failed */ + if (script < argc && /* execute main script (if there is one) */ + handle_script(L, argv + script) != LUA_OK) + return 0; + if (args & has_i) /* -i option? */ + doREPL(L); /* do read-eval-print loop */ + else if (script == argc && !(args & (has_e | has_v))) { /* no arguments? */ + if (lua_stdin_is_tty()) { /* running in interactive mode? */ + print_version(); + doREPL(L); /* do read-eval-print loop */ + } + else dofile(L, NULL); /* executes stdin as a file */ + } + lua_pushboolean(L, 1); /* signal no errors */ + return 1; +} + + +int main (int argc, char **argv) { + int status, result; + lua_State *L = luaL_newstate(); /* create state */ + if (L == NULL) { + l_message(argv[0], "cannot create state: not enough memory"); + return EXIT_FAILURE; + } + lua_pushcfunction(L, &pmain); /* to call 'pmain' in protected mode */ + lua_pushinteger(L, argc); /* 1st argument */ + lua_pushlightuserdata(L, argv); /* 2nd argument */ + status = lua_pcall(L, 2, 1, 0); /* do the call */ + result = lua_toboolean(L, -1); /* get result */ + report(L, status); + lua_close(L); + return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE; +} + diff --git a/app/src/main/jni/lua/lua.h b/app/src/main/jni/lua/lua.h index a4b73e7..f78899f 100644 --- a/app/src/main/jni/lua/lua.h +++ b/app/src/main/jni/lua/lua.h @@ -1,6 +1,6 @@ /* -** $Id: lua.h,v 1.218.1.7 2012/01/13 20:36:20 roberto Exp $ -** Lua - An Extensible Extension Language +** $Id: lua.h,v 1.331 2016/05/30 15:53:28 roberto Exp $ +** Lua - A Scripting Language ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** See Copyright Notice at the end of this file */ @@ -16,55 +16,45 @@ #include "luaconf.h" -#define LUA_VERSION "Lua 5.1" -#define LUA_RELEASE "Lua 5.1.5" -#define LUA_VERSION_NUM 501 -#define LUA_COPYRIGHT "Copyright (C) 1994-2012 Lua.org, PUC-Rio" -#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" +#define LUA_VERSION_MAJOR "5" +#define LUA_VERSION_MINOR "3" +#define LUA_VERSION_NUM 503 +#define LUA_VERSION_RELEASE "3" +#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE +#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2016 Lua.org, PUC-Rio" +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" -/* mark for precompiled code (`Lua') */ -#define LUA_SIGNATURE "\033Lua" -/* option for multiple returns in `lua_pcall' and `lua_call' */ +/* mark for precompiled code ('Lua') */ +#define LUA_SIGNATURE "\x1bLua" + +/* option for multiple returns in 'lua_pcall' and 'lua_call' */ #define LUA_MULTRET (-1) /* -** pseudo-indices +** Pseudo-indices +** (-LUAI_MAXSTACK is the minimum valid index; we keep some free empty +** space after that to help overflow detection) */ -#define LUA_REGISTRYINDEX (-10000) -#define LUA_ENVIRONINDEX (-10001) -#define LUA_GLOBALSINDEX (-10002) -#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) +#define LUA_REGISTRYINDEX (-LUAI_MAXSTACK - 1000) +#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) -/* thread status; 0 is OK */ +/* thread status */ +#define LUA_OK 0 #define LUA_YIELD 1 #define LUA_ERRRUN 2 #define LUA_ERRSYNTAX 3 #define LUA_ERRMEM 4 -#define LUA_ERRERR 5 +#define LUA_ERRGCMM 5 +#define LUA_ERRERR 6 typedef struct lua_State lua_State; -typedef int (*lua_CFunction) (lua_State *L); - - -/* -** functions that read/write blocks when loading/dumping Lua chunks -*/ -typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); - -typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); - - -/* -** prototype for memory-allocation functions -*/ -typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); - /* ** basic types @@ -81,18 +71,18 @@ typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); #define LUA_TUSERDATA 7 #define LUA_TTHREAD 8 +#define LUA_NUMTAGS 9 + /* minimum Lua stack available to a C function */ #define LUA_MINSTACK 20 -/* -** generic extra include file -*/ -#if defined(LUA_USER_H) -#include LUA_USER_H -#endif +/* predefined values in the registry */ +#define LUA_RIDX_MAINTHREAD 1 +#define LUA_RIDX_GLOBALS 2 +#define LUA_RIDX_LAST LUA_RIDX_GLOBALS /* type of numbers in Lua */ @@ -102,6 +92,51 @@ typedef LUA_NUMBER lua_Number; /* type for integer functions */ typedef LUA_INTEGER lua_Integer; +/* unsigned integer type */ +typedef LUA_UNSIGNED lua_Unsigned; + +/* type for continuation-function contexts */ +typedef LUA_KCONTEXT lua_KContext; + + +/* +** Type for C functions registered with Lua +*/ +typedef int (*lua_CFunction) (lua_State *L); + +/* +** Type for continuation functions +*/ +typedef int (*lua_KFunction) (lua_State *L, int status, lua_KContext ctx); + + +/* +** Type for functions that read/write blocks when loading/dumping Lua chunks +*/ +typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); + +typedef int (*lua_Writer) (lua_State *L, const void *p, size_t sz, void *ud); + + +/* +** Type for memory-allocation functions +*/ +typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); + + + +/* +** generic extra include file +*/ +#if defined(LUA_USER_H) +#include LUA_USER_H +#endif + + +/* +** RCS ident string +*/ +extern const char lua_ident[]; /* @@ -114,16 +149,19 @@ LUA_API lua_State *(lua_newthread) (lua_State *L); LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); +LUA_API const lua_Number *(lua_version) (lua_State *L); + + /* ** basic stack manipulation */ +LUA_API int (lua_absindex) (lua_State *L, int idx); LUA_API int (lua_gettop) (lua_State *L); LUA_API void (lua_settop) (lua_State *L, int idx); LUA_API void (lua_pushvalue) (lua_State *L, int idx); -LUA_API void (lua_remove) (lua_State *L, int idx); -LUA_API void (lua_insert) (lua_State *L, int idx); -LUA_API void (lua_replace) (lua_State *L, int idx); -LUA_API int (lua_checkstack) (lua_State *L, int sz); +LUA_API void (lua_rotate) (lua_State *L, int idx, int n); +LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx); +LUA_API int (lua_checkstack) (lua_State *L, int n); LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); @@ -135,33 +173,59 @@ LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); LUA_API int (lua_isnumber) (lua_State *L, int idx); LUA_API int (lua_isstring) (lua_State *L, int idx); LUA_API int (lua_iscfunction) (lua_State *L, int idx); +LUA_API int (lua_isinteger) (lua_State *L, int idx); LUA_API int (lua_isuserdata) (lua_State *L, int idx); LUA_API int (lua_type) (lua_State *L, int idx); LUA_API const char *(lua_typename) (lua_State *L, int tp); -LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); -LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); -LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); - -LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx); -LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx); +LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum); +LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum); LUA_API int (lua_toboolean) (lua_State *L, int idx); LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); -LUA_API size_t (lua_objlen) (lua_State *L, int idx); +LUA_API size_t (lua_rawlen) (lua_State *L, int idx); LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); LUA_API void *(lua_touserdata) (lua_State *L, int idx); LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); LUA_API const void *(lua_topointer) (lua_State *L, int idx); +/* +** Comparison and arithmetic functions +*/ + +#define LUA_OPADD 0 /* ORDER TM, ORDER OP */ +#define LUA_OPSUB 1 +#define LUA_OPMUL 2 +#define LUA_OPMOD 3 +#define LUA_OPPOW 4 +#define LUA_OPDIV 5 +#define LUA_OPIDIV 6 +#define LUA_OPBAND 7 +#define LUA_OPBOR 8 +#define LUA_OPBXOR 9 +#define LUA_OPSHL 10 +#define LUA_OPSHR 11 +#define LUA_OPUNM 12 +#define LUA_OPBNOT 13 + +LUA_API void (lua_arith) (lua_State *L, int op); + +#define LUA_OPEQ 0 +#define LUA_OPLT 1 +#define LUA_OPLE 2 + +LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op); + + /* ** push functions (C -> stack) */ -LUA_API void (lua_pushnil) (lua_State *L); -LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); -LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); -LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l); -LUA_API void (lua_pushstring) (lua_State *L, const char *s); +LUA_API void (lua_pushnil) (lua_State *L); +LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); +LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); +LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t len); +LUA_API const char *(lua_pushstring) (lua_State *L, const char *s); LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, va_list argp); LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); @@ -174,45 +238,62 @@ LUA_API int (lua_pushthread) (lua_State *L); /* ** get functions (Lua -> stack) */ -LUA_API void (lua_gettable) (lua_State *L, int idx); -LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); -LUA_API void (lua_rawget) (lua_State *L, int idx); -LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); +LUA_API int (lua_getglobal) (lua_State *L, const char *name); +LUA_API int (lua_gettable) (lua_State *L, int idx); +LUA_API int (lua_getfield) (lua_State *L, int idx, const char *k); +LUA_API int (lua_geti) (lua_State *L, int idx, lua_Integer n); +LUA_API int (lua_rawget) (lua_State *L, int idx); +LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n); +LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p); + LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); LUA_API int (lua_getmetatable) (lua_State *L, int objindex); -LUA_API void (lua_getfenv) (lua_State *L, int idx); +LUA_API int (lua_getuservalue) (lua_State *L, int idx); /* ** set functions (stack -> Lua) */ +LUA_API void (lua_setglobal) (lua_State *L, const char *name); LUA_API void (lua_settable) (lua_State *L, int idx); LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_seti) (lua_State *L, int idx, lua_Integer n); LUA_API void (lua_rawset) (lua_State *L, int idx); -LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); +LUA_API void (lua_rawseti) (lua_State *L, int idx, lua_Integer n); +LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p); LUA_API int (lua_setmetatable) (lua_State *L, int objindex); -LUA_API int (lua_setfenv) (lua_State *L, int idx); +LUA_API void (lua_setuservalue) (lua_State *L, int idx); /* -** `load' and `call' functions (load and run Lua code) +** 'load' and 'call' functions (load and run Lua code) */ -LUA_API void (lua_call) (lua_State *L, int nargs, int nresults); -LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); -LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud); +LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, + lua_KContext ctx, lua_KFunction k); +#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) + +LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, + lua_KContext ctx, lua_KFunction k); +#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) + LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, - const char *chunkname); + const char *chunkname, const char *mode); -LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); +LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip); /* ** coroutine functions */ -LUA_API int (lua_yield) (lua_State *L, int nresults); -LUA_API int (lua_resume) (lua_State *L, int narg); -LUA_API int (lua_status) (lua_State *L); +LUA_API int (lua_yieldk) (lua_State *L, int nresults, lua_KContext ctx, + lua_KFunction k); +LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg); +LUA_API int (lua_status) (lua_State *L); +LUA_API int (lua_isyieldable) (lua_State *L); + +#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) + /* ** garbage-collection function and options @@ -226,6 +307,7 @@ LUA_API int (lua_status) (lua_State *L); #define LUA_GCSTEP 5 #define LUA_GCSETPAUSE 6 #define LUA_GCSETSTEPMUL 7 +#define LUA_GCISRUNNING 9 LUA_API int (lua_gc) (lua_State *L, int what, int data); @@ -239,18 +321,26 @@ LUA_API int (lua_error) (lua_State *L); LUA_API int (lua_next) (lua_State *L, int idx); LUA_API void (lua_concat) (lua_State *L, int n); +LUA_API void (lua_len) (lua_State *L, int idx); + +LUA_API size_t (lua_stringtonumber) (lua_State *L, const char *s); LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); -LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); +LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); -/* -** =============================================================== +/* +** {============================================================== ** some useful macros ** =============================================================== */ +#define lua_getextraspace(L) ((void *)((char *)(L) - LUA_EXTRASPACE)) + +#define lua_tonumber(L,i) lua_tonumberx(L,(i),NULL) +#define lua_tointeger(L,i) lua_tointegerx(L,(i),NULL) + #define lua_pop(L,n) lua_settop(L, -(n)-1) #define lua_newtable(L) lua_createtable(L, 0, 0) @@ -259,8 +349,6 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); #define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) -#define lua_strlen(L,i) lua_objlen(L, (i)) - #define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) #define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) #define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) @@ -270,33 +358,36 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); #define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) #define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) -#define lua_pushliteral(L, s) \ - lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) +#define lua_pushliteral(L, s) lua_pushstring(L, "" s) -#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) -#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s)) +#define lua_pushglobaltable(L) \ + ((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)) #define lua_tostring(L,i) lua_tolstring(L, (i), NULL) +#define lua_insert(L,idx) lua_rotate(L, (idx), 1) -/* -** compatibility macros and functions -*/ - -#define lua_open() luaL_newstate() +#define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1)) -#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) +#define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1)) -#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0) +/* }============================================================== */ -#define lua_Chunkreader lua_Reader -#define lua_Chunkwriter lua_Writer +/* +** {============================================================== +** compatibility macros for unsigned conversions +** =============================================================== +*/ +#if defined(LUA_COMPAT_APIINTCASTS) -/* hack */ -LUA_API void lua_setlevel (lua_State *from, lua_State *to); +#define lua_pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n)) +#define lua_tounsignedx(L,i,is) ((lua_Unsigned)lua_tointegerx(L,i,is)) +#define lua_tounsigned(L,i) lua_tounsignedx(L,(i),NULL) +#endif +/* }============================================================== */ /* ** {====================================================================== @@ -312,7 +403,7 @@ LUA_API void lua_setlevel (lua_State *from, lua_State *to); #define LUA_HOOKRET 1 #define LUA_HOOKLINE 2 #define LUA_HOOKCOUNT 3 -#define LUA_HOOKTAILRET 4 +#define LUA_HOOKTAILCALL 4 /* @@ -326,43 +417,50 @@ LUA_API void lua_setlevel (lua_State *from, lua_State *to); typedef struct lua_Debug lua_Debug; /* activation record */ -/* Functions to be called by the debuger in specific events */ +/* Functions to be called by the debugger in specific events */ typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); -LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); -LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); -LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); -LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); -LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); -LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); +LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar); +LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar); +LUA_API const char *(lua_getlocal) (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *(lua_setlocal) (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *(lua_getupvalue) (lua_State *L, int funcindex, int n); +LUA_API const char *(lua_setupvalue) (lua_State *L, int funcindex, int n); + +LUA_API void *(lua_upvalueid) (lua_State *L, int fidx, int n); +LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1, + int fidx2, int n2); -LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); -LUA_API lua_Hook lua_gethook (lua_State *L); -LUA_API int lua_gethookmask (lua_State *L); -LUA_API int lua_gethookcount (lua_State *L); +LUA_API void (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count); +LUA_API lua_Hook (lua_gethook) (lua_State *L); +LUA_API int (lua_gethookmask) (lua_State *L); +LUA_API int (lua_gethookcount) (lua_State *L); struct lua_Debug { int event; const char *name; /* (n) */ - const char *namewhat; /* (n) `global', `local', `field', `method' */ - const char *what; /* (S) `Lua', `C', `main', `tail' */ + const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */ + const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */ const char *source; /* (S) */ int currentline; /* (l) */ - int nups; /* (u) number of upvalues */ int linedefined; /* (S) */ int lastlinedefined; /* (S) */ + unsigned char nups; /* (u) number of upvalues */ + unsigned char nparams;/* (u) number of parameters */ + char isvararg; /* (u) */ + char istailcall; /* (t) */ char short_src[LUA_IDSIZE]; /* (S) */ /* private part */ - int i_ci; /* active function */ + struct CallInfo *i_ci; /* active function */ }; /* }====================================================================== */ /****************************************************************************** -* Copyright (C) 1994-2012 Lua.org, PUC-Rio. All rights reserved. +* Copyright (C) 1994-2016 Lua.org, PUC-Rio. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/app/src/main/jni/lua/lua.hpp b/app/src/main/jni/lua/lua.hpp new file mode 100644 index 0000000..ec417f5 --- /dev/null +++ b/app/src/main/jni/lua/lua.hpp @@ -0,0 +1,9 @@ +// lua.hpp +// Lua header files for C++ +// <> not supplied automatically because Lua also compiles as C++ + +extern "C" { +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" +} diff --git a/app/src/main/jni/lua/luac.c b/app/src/main/jni/lua/luac.c new file mode 100644 index 0000000..c0c91d0 --- /dev/null +++ b/app/src/main/jni/lua/luac.c @@ -0,0 +1,449 @@ +/* +** $Id: luac.c,v 1.75 2015/03/12 01:58:27 lhf Exp $ +** Lua compiler (saves bytecodes to files; also lists bytecodes) +** See Copyright Notice in lua.h +*/ + +#define luac_c +#define LUA_CORE + +#include "lprefix.h" + +#include +#include +#include +#include +#include + +#include "lua.h" +#include "lauxlib.h" + +#include "lobject.h" +#include "lstate.h" +#include "lundump.h" + +static void PrintFunction(const Proto* f, int full); +#define luaU_print PrintFunction + +#define PROGNAME "luac" /* default program name */ +#define OUTPUT PROGNAME ".out" /* default output file */ + +static int listing=0; /* list bytecodes? */ +static int dumping=1; /* dump bytecodes? */ +static int stripping=0; /* strip debug information? */ +static char Output[]={ OUTPUT }; /* default output file name */ +static const char* output=Output; /* actual output file name */ +static const char* progname=PROGNAME; /* actual program name */ + +static void fatal(const char* message) +{ + fprintf(stderr,"%s: %s\n",progname,message); + exit(EXIT_FAILURE); +} + +static void cannot(const char* what) +{ + fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno)); + exit(EXIT_FAILURE); +} + +static void usage(const char* message) +{ + if (*message=='-') + fprintf(stderr,"%s: unrecognized option '%s'\n",progname,message); + else + fprintf(stderr,"%s: %s\n",progname,message); + fprintf(stderr, + "usage: %s [options] [filenames]\n" + "Available options are:\n" + " -l list (use -l -l for full listing)\n" + " -o name output to file 'name' (default is \"%s\")\n" + " -p parse only\n" + " -s strip debug information\n" + " -v show version information\n" + " -- stop handling options\n" + " - stop handling options and process stdin\n" + ,progname,Output); + exit(EXIT_FAILURE); +} + +#define IS(s) (strcmp(argv[i],s)==0) + +static int doargs(int argc, char* argv[]) +{ + int i; + int version=0; + if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0]; + for (i=1; itop+(i)) + +static const Proto* combine(lua_State* L, int n) +{ + if (n==1) + return toproto(L,-1); + else + { + Proto* f; + int i=n; + if (lua_load(L,reader,&i,"=(" PROGNAME ")",NULL)!=LUA_OK) fatal(lua_tostring(L,-1)); + f=toproto(L,-1); + for (i=0; ip[i]=toproto(L,i-n-1); + if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0; + } + f->sizelineinfo=0; + return f; + } +} + +static int writer(lua_State* L, const void* p, size_t size, void* u) +{ + UNUSED(L); + return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0); +} + +static int pmain(lua_State* L) +{ + int argc=(int)lua_tointeger(L,1); + char** argv=(char**)lua_touserdata(L,2); + const Proto* f; + int i; + if (!lua_checkstack(L,argc)) fatal("too many input files"); + for (i=0; i1); + if (dumping) + { + FILE* D= (output==NULL) ? stdout : fopen(output,"wb"); + if (D==NULL) cannot("open"); + lua_lock(L); + luaU_dump(L,f,writer,D,stripping); + lua_unlock(L); + if (ferror(D)) cannot("write"); + if (fclose(D)) cannot("close"); + } + return 0; +} + +int main(int argc, char* argv[]) +{ + lua_State* L; + int i=doargs(argc,argv); + argc-=i; argv+=i; + if (argc<=0) usage("no input files given"); + L=luaL_newstate(); + if (L==NULL) fatal("cannot create state: not enough memory"); + lua_pushcfunction(L,&pmain); + lua_pushinteger(L,argc); + lua_pushlightuserdata(L,argv); + if (lua_pcall(L,2,0,0)!=LUA_OK) fatal(lua_tostring(L,-1)); + lua_close(L); + return EXIT_SUCCESS; +} + +/* +** $Id: luac.c,v 1.75 2015/03/12 01:58:27 lhf Exp $ +** print bytecodes +** See Copyright Notice in lua.h +*/ + +#include +#include + +#define luac_c +#define LUA_CORE + +#include "ldebug.h" +#include "lobject.h" +#include "lopcodes.h" + +#define VOID(p) ((const void*)(p)) + +static void PrintString(const TString* ts) +{ + const char* s=getstr(ts); + size_t i,n=tsslen(ts); + printf("%c",'"'); + for (i=0; ik[i]; + switch (ttype(o)) + { + case LUA_TNIL: + printf("nil"); + break; + case LUA_TBOOLEAN: + printf(bvalue(o) ? "true" : "false"); + break; + case LUA_TNUMFLT: + { + char buff[100]; + sprintf(buff,LUA_NUMBER_FMT,fltvalue(o)); + printf("%s",buff); + if (buff[strspn(buff,"-0123456789")]=='\0') printf(".0"); + break; + } + case LUA_TNUMINT: + printf(LUA_INTEGER_FMT,ivalue(o)); + break; + case LUA_TSHRSTR: case LUA_TLNGSTR: + PrintString(tsvalue(o)); + break; + default: /* cannot happen */ + printf("? type=%d",ttype(o)); + break; + } +} + +#define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-") +#define MYK(x) (-1-(x)) + +static void PrintCode(const Proto* f) +{ + const Instruction* code=f->code; + int pc,n=f->sizecode; + for (pc=0; pc0) printf("[%d]\t",line); else printf("[-]\t"); + printf("%-9s\t",luaP_opnames[o]); + switch (getOpMode(o)) + { + case iABC: + printf("%d",a); + if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (MYK(INDEXK(b))) : b); + if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (MYK(INDEXK(c))) : c); + break; + case iABx: + printf("%d",a); + if (getBMode(o)==OpArgK) printf(" %d",MYK(bx)); + if (getBMode(o)==OpArgU) printf(" %d",bx); + break; + case iAsBx: + printf("%d %d",a,sbx); + break; + case iAx: + printf("%d",MYK(ax)); + break; + } + switch (o) + { + case OP_LOADK: + printf("\t; "); PrintConstant(f,bx); + break; + case OP_GETUPVAL: + case OP_SETUPVAL: + printf("\t; %s",UPVALNAME(b)); + break; + case OP_GETTABUP: + printf("\t; %s",UPVALNAME(b)); + if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } + break; + case OP_SETTABUP: + printf("\t; %s",UPVALNAME(a)); + if (ISK(b)) { printf(" "); PrintConstant(f,INDEXK(b)); } + if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } + break; + case OP_GETTABLE: + case OP_SELF: + if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); } + break; + case OP_SETTABLE: + case OP_ADD: + case OP_SUB: + case OP_MUL: + case OP_POW: + case OP_DIV: + case OP_IDIV: + case OP_BAND: + case OP_BOR: + case OP_BXOR: + case OP_SHL: + case OP_SHR: + case OP_EQ: + case OP_LT: + case OP_LE: + if (ISK(b) || ISK(c)) + { + printf("\t; "); + if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-"); + printf(" "); + if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-"); + } + break; + case OP_JMP: + case OP_FORLOOP: + case OP_FORPREP: + case OP_TFORLOOP: + printf("\t; to %d",sbx+pc+2); + break; + case OP_CLOSURE: + printf("\t; %p",VOID(f->p[bx])); + break; + case OP_SETLIST: + if (c==0) printf("\t; %d",(int)code[++pc]); else printf("\t; %d",c); + break; + case OP_EXTRAARG: + printf("\t; "); PrintConstant(f,ax); + break; + default: + break; + } + printf("\n"); + } +} + +#define SS(x) ((x==1)?"":"s") +#define S(x) (int)(x),SS(x) + +static void PrintHeader(const Proto* f) +{ + const char* s=f->source ? getstr(f->source) : "=?"; + if (*s=='@' || *s=='=') + s++; + else if (*s==LUA_SIGNATURE[0]) + s="(bstring)"; + else + s="(string)"; + printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n", + (f->linedefined==0)?"main":"function",s, + f->linedefined,f->lastlinedefined, + S(f->sizecode),VOID(f)); + printf("%d%s param%s, %d slot%s, %d upvalue%s, ", + (int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams), + S(f->maxstacksize),S(f->sizeupvalues)); + printf("%d local%s, %d constant%s, %d function%s\n", + S(f->sizelocvars),S(f->sizek),S(f->sizep)); +} + +static void PrintDebug(const Proto* f) +{ + int i,n; + n=f->sizek; + printf("constants (%d) for %p:\n",n,VOID(f)); + for (i=0; isizelocvars; + printf("locals (%d) for %p:\n",n,VOID(f)); + for (i=0; ilocvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1); + } + n=f->sizeupvalues; + printf("upvalues (%d) for %p:\n",n,VOID(f)); + for (i=0; iupvalues[i].instack,f->upvalues[i].idx); + } +} + +static void PrintFunction(const Proto* f, int full) +{ + int i,n=f->sizep; + PrintHeader(f); + PrintCode(f); + if (full) PrintDebug(f); + for (i=0; ip[i],full); +} diff --git a/app/src/main/jni/lua/luaconf.h b/app/src/main/jni/lua/luaconf.h index 8c5c805..acd144d 100644 --- a/app/src/main/jni/lua/luaconf.h +++ b/app/src/main/jni/lua/luaconf.h @@ -1,108 +1,203 @@ /* -** $Id: luaconf.h,v 1.82.1.7 2008/02/11 16:25:08 roberto Exp $ +** $Id: luaconf.h,v 1.255 2016/05/01 20:06:09 roberto Exp $ ** Configuration file for Lua ** See Copyright Notice in lua.h */ -#ifndef lconfig_h -#define lconfig_h +#ifndef luaconf_h +#define luaconf_h #include #include /* -** ================================================================== +** =================================================================== ** Search for "@@" to find all configurable definitions. ** =================================================================== */ /* -@@ LUA_ANSI controls the use of non-ansi features. -** CHANGE it (define it) if you want Lua to avoid the use of any -** non-ansi feature or library. +** {==================================================================== +** System Configuration: macros to adapt (if needed) Lua to some +** particular platform, for instance compiling it with 32-bit numbers or +** restricting it to C89. +** ===================================================================== +*/ + +/* +@@ LUA_32BITS enables Lua with 32-bit integers and 32-bit floats. You +** can also define LUA_32BITS in the make file, but changing here you +** ensure that all software connected to Lua will be compiled with the +** same configuration. +*/ +/* #define LUA_32BITS */ + + +/* +@@ LUA_USE_C89 controls the use of non-ISO-C89 features. +** Define it if you want Lua to avoid the use of a few C99 features +** or Windows-specific features on Windows. */ -#if defined(__STRICT_ANSI__) -#define LUA_ANSI +/* #define LUA_USE_C89 */ + + +/* +** By default, Lua on Windows use (some) specific Windows features +*/ +#if !defined(LUA_USE_C89) && defined(_WIN32) && !defined(_WIN32_WCE) +#define LUA_USE_WINDOWS /* enable goodies for regular Windows */ #endif -#if !defined(LUA_ANSI) && defined(_WIN32) -#define LUA_WIN +#if defined(LUA_USE_WINDOWS) +#define LUA_DL_DLL /* enable support for DLL */ +#define LUA_USE_C89 /* broadly, Windows is C89 */ #endif + #if defined(LUA_USE_LINUX) #define LUA_USE_POSIX #define LUA_USE_DLOPEN /* needs an extra library: -ldl */ #define LUA_USE_READLINE /* needs some extra libraries */ #endif + #if defined(LUA_USE_MACOSX) #define LUA_USE_POSIX -#define LUA_DL_DYLD /* does not need extra library */ +#define LUA_USE_DLOPEN /* MacOS does not need -ldl */ +#define LUA_USE_READLINE /* needs an extra library: -lreadline */ +#endif + + +/* +@@ LUA_C89_NUMBERS ensures that Lua uses the largest types available for +** C89 ('long' and 'double'); Windows always has '__int64', so it does +** not need to use this case. +*/ +#if defined(LUA_USE_C89) && !defined(LUA_USE_WINDOWS) +#define LUA_C89_NUMBERS #endif /* -@@ LUA_USE_POSIX includes all functionallity listed as X/Open System -@* Interfaces Extension (XSI). -** CHANGE it (define it) if your system is XSI compatible. +@@ LUAI_BITSINT defines the (minimum) number of bits in an 'int'. */ -#if defined(LUA_USE_POSIX) -#define LUA_USE_MKSTEMP -#define LUA_USE_ISATTY -#define LUA_USE_POPEN -#define LUA_USE_ULONGJMP +/* avoid undefined shifts */ +#if ((INT_MAX >> 15) >> 15) >= 1 +#define LUAI_BITSINT 32 +#else +/* 'int' always must have at least 16 bits */ +#define LUAI_BITSINT 16 #endif /* -@@ LUA_PATH and LUA_CPATH are the names of the environment variables that -@* Lua check to set its paths. -@@ LUA_INIT is the name of the environment variable that Lua -@* checks for initialization code. -** CHANGE them if you want different names. +@@ LUA_INT_TYPE defines the type for Lua integers. +@@ LUA_FLOAT_TYPE defines the type for Lua floats. +** Lua should work fine with any mix of these options (if supported +** by your C compiler). The usual configurations are 64-bit integers +** and 'double' (the default), 32-bit integers and 'float' (for +** restricted platforms), and 'long'/'double' (for C compilers not +** compliant with C99, which may not have support for 'long long'). */ -#define LUA_PATH "LUA_PATH" -#define LUA_CPATH "LUA_CPATH" -#define LUA_INIT "LUA_INIT" +/* predefined options for LUA_INT_TYPE */ +#define LUA_INT_INT 1 +#define LUA_INT_LONG 2 +#define LUA_INT_LONGLONG 3 + +/* predefined options for LUA_FLOAT_TYPE */ +#define LUA_FLOAT_FLOAT 1 +#define LUA_FLOAT_DOUBLE 2 +#define LUA_FLOAT_LONGDOUBLE 3 + +#if defined(LUA_32BITS) /* { */ +/* +** 32-bit integers and 'float' +*/ +#if LUAI_BITSINT >= 32 /* use 'int' if big enough */ +#define LUA_INT_TYPE LUA_INT_INT +#else /* otherwise use 'long' */ +#define LUA_INT_TYPE LUA_INT_LONG +#endif +#define LUA_FLOAT_TYPE LUA_FLOAT_FLOAT + +#elif defined(LUA_C89_NUMBERS) /* }{ */ +/* +** largest types available for C89 ('long' and 'double') +*/ +#define LUA_INT_TYPE LUA_INT_LONG +#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE + +#endif /* } */ + + +/* +** default configuration for 64-bit Lua ('long long' and 'double') +*/ +#if !defined(LUA_INT_TYPE) +#define LUA_INT_TYPE LUA_INT_LONGLONG +#endif + +#if !defined(LUA_FLOAT_TYPE) +#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE +#endif + +/* }================================================================== */ + + + + +/* +** {================================================================== +** Configuration for Paths. +** =================================================================== +*/ /* @@ LUA_PATH_DEFAULT is the default path that Lua uses to look for -@* Lua libraries. +** Lua libraries. @@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for -@* C libraries. +** C libraries. ** CHANGE them if your machine has a non-conventional directory ** hierarchy or if you want to install your libraries in ** non-conventional directories. */ -#if defined(_WIN32) +#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#if defined(_WIN32) /* { */ /* ** In Windows, any exclamation mark ('!') in the path is replaced by the ** path of the directory of the executable file of the current process. */ #define LUA_LDIR "!\\lua\\" #define LUA_CDIR "!\\" +#define LUA_SHRDIR "!\\..\\share\\lua\\" LUA_VDIR "\\" #define LUA_PATH_DEFAULT \ - ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ - LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua" + LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" \ + LUA_SHRDIR"?.lua;" LUA_SHRDIR"?\\init.lua;" \ + ".\\?.lua;" ".\\?\\init.lua" #define LUA_CPATH_DEFAULT \ - ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" + LUA_CDIR"?.dll;" \ + LUA_CDIR"..\\lib\\lua\\" LUA_VDIR "\\?.dll;" \ + LUA_CDIR"loadall.dll;" ".\\?.dll" + +#else /* }{ */ -#else #define LUA_ROOT "/usr/local/" -#define LUA_LDIR LUA_ROOT "share/lua/5.1/" -#define LUA_CDIR LUA_ROOT "lib/lua/5.1/" +#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR "/" +#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR "/" #define LUA_PATH_DEFAULT \ - "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ - LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua" + LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" \ + "./?.lua;" "./?/init.lua" #define LUA_CPATH_DEFAULT \ - "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so" -#endif + LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" +#endif /* } */ /* @@ -116,637 +211,545 @@ #define LUA_DIRSEP "/" #endif - -/* -@@ LUA_PATHSEP is the character that separates templates in a path. -@@ LUA_PATH_MARK is the string that marks the substitution points in a -@* template. -@@ LUA_EXECDIR in a Windows path is replaced by the executable's -@* directory. -@@ LUA_IGMARK is a mark to ignore all before it when bulding the -@* luaopen_ function name. -** CHANGE them if for some reason your system cannot use those -** characters. (E.g., if one of those characters is a common character -** in file/directory names.) Probably you do not need to change them. -*/ -#define LUA_PATHSEP ";" -#define LUA_PATH_MARK "?" -#define LUA_EXECDIR "!" -#define LUA_IGMARK "-" +/* }================================================================== */ /* -@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. -** CHANGE that if ptrdiff_t is not adequate on your machine. (On most -** machines, ptrdiff_t gives a good choice between int or long.) +** {================================================================== +** Marks for exported symbols in the C code +** =================================================================== */ -#define LUA_INTEGER ptrdiff_t - /* @@ LUA_API is a mark for all core API functions. -@@ LUALIB_API is a mark for all standard library functions. +@@ LUALIB_API is a mark for all auxiliary library functions. +@@ LUAMOD_API is a mark for all standard library opening functions. ** CHANGE them if you need to define those functions in some special way. ** For instance, if you want to create one Windows DLL with the core and ** the libraries, you may want to use the following definition (define ** LUA_BUILD_AS_DLL to get it). */ -#if defined(LUA_BUILD_AS_DLL) +#if defined(LUA_BUILD_AS_DLL) /* { */ -#if defined(LUA_CORE) || defined(LUA_LIB) +#if defined(LUA_CORE) || defined(LUA_LIB) /* { */ #define LUA_API __declspec(dllexport) -#else +#else /* }{ */ #define LUA_API __declspec(dllimport) -#endif +#endif /* } */ -#else +#else /* }{ */ #define LUA_API extern -#endif +#endif /* } */ + /* more often than not the libs go together with the core */ #define LUALIB_API LUA_API +#define LUAMOD_API LUALIB_API /* @@ LUAI_FUNC is a mark for all extern functions that are not to be -@* exported to outside modules. -@@ LUAI_DATA is a mark for all extern (const) variables that are not to -@* be exported to outside modules. +** exported to outside modules. +@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables +** that are not to be exported to outside modules (LUAI_DDEF for +** definitions and LUAI_DDEC for declarations). ** CHANGE them if you need to mark them in some special way. Elf/gcc ** (versions 3.2 and later) mark them as "hidden" to optimize access -** when Lua is compiled as a shared library. -*/ -#if defined(luaall_c) -#define LUAI_FUNC static -#define LUAI_DATA /* empty */ - -#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ - defined(__ELF__) +** when Lua is compiled as a shared library. Not all elf targets support +** this attribute. Unfortunately, gcc does not offer a way to check +** whether the target offers that support, and those without support +** give a warning about it. To avoid these warnings, change to the +** default definition. +*/ +#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ + defined(__ELF__) /* { */ #define LUAI_FUNC __attribute__((visibility("hidden"))) extern -#define LUAI_DATA LUAI_FUNC - -#else +#else /* }{ */ #define LUAI_FUNC extern -#define LUAI_DATA extern -#endif +#endif /* } */ +#define LUAI_DDEC LUAI_FUNC +#define LUAI_DDEF /* empty */ - -/* -@@ LUA_QL describes how error messages quote program elements. -** CHANGE it if you want a different appearance. -*/ -#define LUA_QL(x) "'" x "'" -#define LUA_QS LUA_QL("%s") - - -/* -@@ LUA_IDSIZE gives the maximum size for the description of the source -@* of a function in debug information. -** CHANGE it if you want a different size. -*/ -#define LUA_IDSIZE 60 +/* }================================================================== */ /* ** {================================================================== -** Stand-alone configuration +** Compatibility with previous versions ** =================================================================== */ -#if defined(lua_c) || defined(luaall_c) - /* -@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that -@* is, whether we're running lua interactively). -** CHANGE it if you have a better definition for non-POSIX/non-Windows -** systems. +@@ LUA_COMPAT_5_2 controls other macros for compatibility with Lua 5.2. +@@ LUA_COMPAT_5_1 controls other macros for compatibility with Lua 5.1. +** You can define it to get all options, or change specific options +** to fit your specific needs. */ -#if defined(LUA_USE_ISATTY) -#include -#define lua_stdin_is_tty() isatty(0) -#elif defined(LUA_WIN) -#include -#include -#define lua_stdin_is_tty() _isatty(_fileno(stdin)) -#else -#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ -#endif - +#if defined(LUA_COMPAT_5_2) /* { */ /* -@@ LUA_PROMPT is the default prompt used by stand-alone Lua. -@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua. -** CHANGE them if you want different prompts. (You can also change the -** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.) +@@ LUA_COMPAT_MATHLIB controls the presence of several deprecated +** functions in the mathematical library. */ -#define LUA_PROMPT "> " -#define LUA_PROMPT2 ">> " - +#define LUA_COMPAT_MATHLIB /* -@@ LUA_PROGNAME is the default name for the stand-alone Lua program. -** CHANGE it if your stand-alone interpreter has a different name and -** your system is not able to detect that name automatically. +@@ LUA_COMPAT_BITLIB controls the presence of library 'bit32'. */ -#define LUA_PROGNAME "lua" - +#define LUA_COMPAT_BITLIB /* -@@ LUA_MAXINPUT is the maximum length for an input line in the -@* stand-alone interpreter. -** CHANGE it if you need longer lines. +@@ LUA_COMPAT_IPAIRS controls the effectiveness of the __ipairs metamethod. */ -#define LUA_MAXINPUT 512 - +#define LUA_COMPAT_IPAIRS /* -@@ lua_readline defines how to show a prompt and then read a line from -@* the standard input. -@@ lua_saveline defines how to "save" a read line in a "history". -@@ lua_freeline defines how to free a line read by lua_readline. -** CHANGE them if you want to improve this functionality (e.g., by using -** GNU readline and history facilities). +@@ LUA_COMPAT_APIINTCASTS controls the presence of macros for +** manipulating other integer types (lua_pushunsigned, lua_tounsigned, +** luaL_checkint, luaL_checklong, etc.) */ -#if defined(LUA_USE_READLINE) -#include -#include -#include -#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) -#define lua_saveline(L,idx) \ - if (lua_strlen(L,idx) > 0) /* non-empty line? */ \ - add_history(lua_tostring(L, idx)); /* add it to history */ -#define lua_freeline(L,b) ((void)L, free(b)) -#else -#define lua_readline(L,b,p) \ - ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ - fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ -#define lua_saveline(L,idx) { (void)L; (void)idx; } -#define lua_freeline(L,b) { (void)L; (void)b; } -#endif +#define LUA_COMPAT_APIINTCASTS -#endif +#endif /* } */ -/* }================================================================== */ +#if defined(LUA_COMPAT_5_1) /* { */ -/* -@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles -@* as a percentage. -** CHANGE it if you want the GC to run faster or slower (higher values -** mean larger pauses which mean slower collection.) You can also change -** this value dynamically. -*/ -#define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */ - +/* Incompatibilities from 5.2 -> 5.3 */ +#define LUA_COMPAT_MATHLIB +#define LUA_COMPAT_APIINTCASTS /* -@@ LUAI_GCMUL defines the default speed of garbage collection relative to -@* memory allocation as a percentage. -** CHANGE it if you want to change the granularity of the garbage -** collection. (Higher values mean coarser collections. 0 represents -** infinity, where each step performs a full collection.) You can also -** change this value dynamically. +@@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'. +** You can replace it with 'table.unpack'. */ -#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ - - +#define LUA_COMPAT_UNPACK /* -@@ LUA_COMPAT_GETN controls compatibility with old getn behavior. -** CHANGE it (define it) if you want exact compatibility with the -** behavior of setn/getn in Lua 5.0. +@@ LUA_COMPAT_LOADERS controls the presence of table 'package.loaders'. +** You can replace it with 'package.searchers'. */ -#undef LUA_COMPAT_GETN +#define LUA_COMPAT_LOADERS /* -@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib. -** CHANGE it to undefined as soon as you do not need a global 'loadlib' -** function (the function is still available as 'package.loadlib'). +@@ macro 'lua_cpcall' emulates deprecated function lua_cpcall. +** You can call your C function directly (with light C functions). */ -#undef LUA_COMPAT_LOADLIB +#define lua_cpcall(L,f,u) \ + (lua_pushcfunction(L, (f)), \ + lua_pushlightuserdata(L,(u)), \ + lua_pcall(L,1,0,0)) -/* -@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature. -** CHANGE it to undefined as soon as your programs use only '...' to -** access vararg parameters (instead of the old 'arg' table). -*/ -#define LUA_COMPAT_VARARG /* -@@ LUA_COMPAT_MOD controls compatibility with old math.mod function. -** CHANGE it to undefined as soon as your programs use 'math.fmod' or -** the new '%' operator instead of 'math.mod'. +@@ LUA_COMPAT_LOG10 defines the function 'log10' in the math library. +** You can rewrite 'log10(x)' as 'log(x, 10)'. */ -#define LUA_COMPAT_MOD +#define LUA_COMPAT_LOG10 /* -@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting -@* facility. -** CHANGE it to 2 if you want the old behaviour, or undefine it to turn -** off the advisory error when nesting [[...]]. +@@ LUA_COMPAT_LOADSTRING defines the function 'loadstring' in the base +** library. You can rewrite 'loadstring(s)' as 'load(s)'. */ -#define LUA_COMPAT_LSTR 1 +#define LUA_COMPAT_LOADSTRING /* -@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name. -** CHANGE it to undefined as soon as you rename 'string.gfind' to -** 'string.gmatch'. +@@ LUA_COMPAT_MAXN defines the function 'maxn' in the table library. */ -#define LUA_COMPAT_GFIND +#define LUA_COMPAT_MAXN /* -@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib' -@* behavior. -** CHANGE it to undefined as soon as you replace to 'luaL_register' -** your uses of 'luaL_openlib' +@@ The following macros supply trivial compatibility for some +** changes in the API. The macros themselves document how to +** change your code to avoid using them. */ -#define LUA_COMPAT_OPENLIB +#define lua_strlen(L,i) lua_rawlen(L, (i)) +#define lua_objlen(L,i) lua_rawlen(L, (i)) +#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) +#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT) /* -@@ luai_apicheck is the assert macro used by the Lua-C API. -** CHANGE luai_apicheck if you want Lua to perform some checks in the -** parameters it gets from API calls. This may slow down the interpreter -** a bit, but may be quite useful when debugging C code that interfaces -** with Lua. A useful redefinition is to use assert.h. +@@ LUA_COMPAT_MODULE controls compatibility with previous +** module functions 'module' (Lua) and 'luaL_register' (C). */ -#if defined(LUA_USE_APICHECK) -#include -#define luai_apicheck(L,o) { (void)L; assert(o); } -#else -#define luai_apicheck(L,o) { (void)L; } -#endif +#define LUA_COMPAT_MODULE + +#endif /* } */ /* -@@ LUAI_BITSINT defines the number of bits in an int. -** CHANGE here if Lua cannot automatically detect the number of bits of -** your machine. Probably you do not need to change this. +@@ LUA_COMPAT_FLOATSTRING makes Lua format integral floats without a +@@ a float mark ('.0'). +** This macro is not on by default even in compatibility mode, +** because this is not really an incompatibility. */ -/* avoid overflows in comparison */ -#if INT_MAX-20 < 32760 -#define LUAI_BITSINT 16 -#elif INT_MAX > 2147483640L -/* int has at least 32 bits */ -#define LUAI_BITSINT 32 -#else -#error "you must define LUA_BITSINT with number of bits in an integer" -#endif +/* #define LUA_COMPAT_FLOATSTRING */ +/* }================================================================== */ -/* -@@ LUAI_UINT32 is an unsigned integer with at least 32 bits. -@@ LUAI_INT32 is an signed integer with at least 32 bits. -@@ LUAI_UMEM is an unsigned integer big enough to count the total -@* memory used by Lua. -@@ LUAI_MEM is a signed integer big enough to count the total memory -@* used by Lua. -** CHANGE here if for some weird reason the default definitions are not -** good enough for your machine. (The definitions in the 'else' -** part always works, but may waste space on machines with 64-bit -** longs.) Probably you do not need to change this. -*/ -#if LUAI_BITSINT >= 32 -#define LUAI_UINT32 unsigned int -#define LUAI_INT32 int -#define LUAI_MAXINT32 INT_MAX -#define LUAI_UMEM size_t -#define LUAI_MEM ptrdiff_t -#else -/* 16-bit ints */ -#define LUAI_UINT32 unsigned long -#define LUAI_INT32 long -#define LUAI_MAXINT32 LONG_MAX -#define LUAI_UMEM unsigned long -#define LUAI_MEM long -#endif /* -@@ LUAI_MAXCALLS limits the number of nested calls. -** CHANGE it if you need really deep recursive calls. This limit is -** arbitrary; its only purpose is to stop infinite recursion before -** exhausting memory. +** {================================================================== +** Configuration for Numbers. +** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_* +** satisfy your needs. +** =================================================================== */ -#define LUAI_MAXCALLS 20000 - /* -@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function -@* can use. -** CHANGE it if you need lots of (Lua) stack space for your C -** functions. This limit is arbitrary; its only purpose is to stop C -** functions to consume unlimited stack space. (must be smaller than -** -LUA_REGISTRYINDEX) +@@ LUA_NUMBER is the floating-point type used by Lua. +@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' +@@ over a floating number. +@@ l_mathlim(x) corrects limit name 'x' to the proper float type +** by prefixing it with one of FLT/DBL/LDBL. +@@ LUA_NUMBER_FRMLEN is the length modifier for writing floats. +@@ LUA_NUMBER_FMT is the format for writing floats. +@@ lua_number2str converts a float to a string. +@@ l_mathop allows the addition of an 'l' or 'f' to all math operations. +@@ l_floor takes the floor of a float. +@@ lua_str2number converts a decimal numeric string to a number. */ -#define LUAI_MAXCSTACK 8000 +/* The following definitions are good for most cases here */ -/* -** {================================================================== -** CHANGE (to smaller values) the following definitions if your system -** has a small C stack. (Or you may want to change them to larger -** values if your system has a large C stack and these limits are -** too rigid for you.) Some of these constants control the size of -** stack-allocated arrays used by the compiler or the interpreter, while -** others limit the maximum number of recursive calls that the compiler -** or the interpreter can perform. Values too large may cause a C stack -** overflow for some forms of deep constructs. -** =================================================================== -*/ +#define l_floor(x) (l_mathop(floor)(x)) +#define lua_number2str(s,sz,n) l_sprintf((s), sz, LUA_NUMBER_FMT, (n)) /* -@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and -@* syntactical nested non-terminals in a program. +@@ lua_numbertointeger converts a float number to an integer, or +** returns 0 if float is not within the range of a lua_Integer. +** (The range comparisons are tricky because of rounding. The tests +** here assume a two-complement representation, where MININTEGER always +** has an exact representation as a float; MAXINTEGER may not have one, +** and therefore its conversion to float may have an ill-defined value.) */ -#define LUAI_MAXCCALLS 200 +#define lua_numbertointeger(n,p) \ + ((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \ + (n) < -(LUA_NUMBER)(LUA_MININTEGER) && \ + (*(p) = (LUA_INTEGER)(n), 1)) -/* -@@ LUAI_MAXVARS is the maximum number of local variables per function -@* (must be smaller than 250). -*/ -#define LUAI_MAXVARS 200 +/* now the variable definitions */ +#if LUA_FLOAT_TYPE == LUA_FLOAT_FLOAT /* { single float */ -/* -@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function -@* (must be smaller than 250). -*/ -#define LUAI_MAXUPVALUES 60 +#define LUA_NUMBER float +#define l_mathlim(n) (FLT_##n) -/* -@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. -*/ -#define LUAL_BUFFERSIZE BUFSIZ +#define LUAI_UACNUMBER double -/* }================================================================== */ +#define LUA_NUMBER_FRMLEN "" +#define LUA_NUMBER_FMT "%.7g" +#define l_mathop(op) op##f +#define lua_str2number(s,p) strtof((s), (p)) -/* -** {================================================================== -@@ LUA_NUMBER is the type of numbers in Lua. -** CHANGE the following definitions only if you want to build Lua -** with a number type different from double. You may also need to -** change lua_number2int & lua_number2integer. -** =================================================================== -*/ +#elif LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE /* }{ long double */ + +#define LUA_NUMBER long double + +#define l_mathlim(n) (LDBL_##n) + +#define LUAI_UACNUMBER long double + +#define LUA_NUMBER_FRMLEN "L" +#define LUA_NUMBER_FMT "%.19Lg" + +#define l_mathop(op) op##l + +#define lua_str2number(s,p) strtold((s), (p)) + +#elif LUA_FLOAT_TYPE == LUA_FLOAT_DOUBLE /* }{ double */ -#define LUA_NUMBER_DOUBLE #define LUA_NUMBER double -/* -@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' -@* over a number. -*/ -#define LUAI_UACNUMBER double +#define l_mathlim(n) (DBL_##n) +#define LUAI_UACNUMBER double -/* -@@ LUA_NUMBER_SCAN is the format for reading numbers. -@@ LUA_NUMBER_FMT is the format for writing numbers. -@@ lua_number2str converts a number to a string. -@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. -@@ lua_str2number converts a string to a number. -*/ -#define LUA_NUMBER_SCAN "%lf" +#define LUA_NUMBER_FRMLEN "" #define LUA_NUMBER_FMT "%.14g" -#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) -#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ + +#define l_mathop(op) op + #define lua_str2number(s,p) strtod((s), (p)) +#else /* }{ */ + +#error "numeric float type not defined" + +#endif /* } */ + + /* -@@ The luai_num* macros define the primitive operations over numbers. +@@ LUA_INTEGER is the integer type used by Lua. +** +@@ LUA_UNSIGNED is the unsigned version of LUA_INTEGER. +** +@@ LUAI_UACINT is the result of an 'usual argument conversion' +@@ over a lUA_INTEGER. +@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers. +@@ LUA_INTEGER_FMT is the format for writing integers. +@@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER. +@@ LUA_MININTEGER is the minimum value for a LUA_INTEGER. +@@ lua_integer2str converts an integer to a string. */ -#if defined(LUA_CORE) -#include -#define luai_numadd(a,b) ((a)+(b)) -#define luai_numsub(a,b) ((a)-(b)) -#define luai_nummul(a,b) ((a)*(b)) -#define luai_numdiv(a,b) ((a)/(b)) -#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) -#define luai_numpow(a,b) (pow(a,b)) -#define luai_numunm(a) (-(a)) -#define luai_numeq(a,b) ((a)==(b)) -#define luai_numlt(a,b) ((a)<(b)) -#define luai_numle(a,b) ((a)<=(b)) -#define luai_numisnan(a) (!luai_numeq((a), (a))) -#endif +/* The following definitions are good for most cases here */ + +#define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d" +#define lua_integer2str(s,sz,n) l_sprintf((s), sz, LUA_INTEGER_FMT, (n)) + +#define LUAI_UACINT LUA_INTEGER + /* -@@ lua_number2int is a macro to convert lua_Number to int. -@@ lua_number2integer is a macro to convert lua_Number to lua_Integer. -** CHANGE them if you know a faster way to convert a lua_Number to -** int (with any rounding method and without throwing errors) in your -** system. In Pentium machines, a naive typecast from double to int -** in C is extremely slow, so any alternative is worth trying. +** use LUAI_UACINT here to avoid problems with promotions (which +** can turn a comparison between unsigneds into a signed comparison) */ +#define LUA_UNSIGNED unsigned LUAI_UACINT -/* On a Pentium, resort to a trick */ -#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ - (defined(__i386) || defined (_M_IX86) || defined(__i386__)) -/* On a Microsoft compiler, use assembler */ -#if defined(_MSC_VER) +/* now the variable definitions */ -#define lua_number2int(i,d) __asm fld d __asm fistp i -#define lua_number2integer(i,n) lua_number2int(i, n) +#if LUA_INT_TYPE == LUA_INT_INT /* { int */ -/* the next trick should work on any Pentium, but sometimes clashes - with a DirectX idiosyncrasy */ -#else +#define LUA_INTEGER int +#define LUA_INTEGER_FRMLEN "" -union luai_Cast { double l_d; long l_l; }; -#define lua_number2int(i,d) \ - { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } -#define lua_number2integer(i,n) lua_number2int(i, n) +#define LUA_MAXINTEGER INT_MAX +#define LUA_MININTEGER INT_MIN -#endif +#elif LUA_INT_TYPE == LUA_INT_LONG /* }{ long */ +#define LUA_INTEGER long +#define LUA_INTEGER_FRMLEN "l" -/* this option always works, but may be slow */ -#else -#define lua_number2int(i,d) ((i)=(int)(d)) -#define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) +#define LUA_MAXINTEGER LONG_MAX +#define LUA_MININTEGER LONG_MIN -#endif +#elif LUA_INT_TYPE == LUA_INT_LONGLONG /* }{ long long */ + +/* use presence of macro LLONG_MAX as proxy for C99 compliance */ +#if defined(LLONG_MAX) /* { */ +/* use ISO C99 stuff */ + +#define LUA_INTEGER long long +#define LUA_INTEGER_FRMLEN "ll" + +#define LUA_MAXINTEGER LLONG_MAX +#define LUA_MININTEGER LLONG_MIN + +#elif defined(LUA_USE_WINDOWS) /* }{ */ +/* in Windows, can use specific Windows types */ + +#define LUA_INTEGER __int64 +#define LUA_INTEGER_FRMLEN "I64" + +#define LUA_MAXINTEGER _I64_MAX +#define LUA_MININTEGER _I64_MIN + +#else /* }{ */ + +#error "Compiler does not support 'long long'. Use option '-DLUA_32BITS' \ + or '-DLUA_C89_NUMBERS' (see file 'luaconf.h' for details)" + +#endif /* } */ + +#else /* }{ */ + +#error "numeric integer type not defined" + +#endif /* } */ /* }================================================================== */ /* -@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment. -** CHANGE it if your system requires alignments larger than double. (For -** instance, if your system supports long doubles and they must be -** aligned in 16-byte boundaries, then you should add long double in the -** union.) Probably you do not need to change this. +** {================================================================== +** Dependencies with C99 and other C details +** =================================================================== */ -#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } - /* -@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling. -** CHANGE them if you prefer to use longjmp/setjmp even with C++ -** or if want/don't to use _longjmp/_setjmp instead of regular -** longjmp/setjmp. By default, Lua handles errors with exceptions when -** compiling as C++ code, with _longjmp/_setjmp when asked to use them, -** and with longjmp/setjmp otherwise. +@@ l_sprintf is equivalent to 'snprintf' or 'sprintf' in C89. +** (All uses in Lua have only one format item.) */ -#if defined(__cplusplus) -/* C++ exceptions */ -#define LUAI_THROW(L,c) throw(c) -#define LUAI_TRY(L,c,a) try { a } catch(...) \ - { if ((c)->status == 0) (c)->status = -1; } -#define luai_jmpbuf int /* dummy variable */ - -#elif defined(LUA_USE_ULONGJMP) -/* in Unix, try _longjmp/_setjmp (more efficient) */ -#define LUAI_THROW(L,c) _longjmp((c)->b, 1) -#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } -#define luai_jmpbuf jmp_buf - +#if !defined(LUA_USE_C89) +#define l_sprintf(s,sz,f,i) snprintf(s,sz,f,i) #else -/* default handling with long jumps */ -#define LUAI_THROW(L,c) longjmp((c)->b, 1) -#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } -#define luai_jmpbuf jmp_buf - +#define l_sprintf(s,sz,f,i) ((void)(sz), sprintf(s,f,i)) #endif /* -@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern -@* can do during pattern-matching. -** CHANGE it if you need more captures. This limit is arbitrary. +@@ lua_strx2number converts an hexadecimal numeric string to a number. +** In C99, 'strtod' does that conversion. Otherwise, you can +** leave 'lua_strx2number' undefined and Lua will provide its own +** implementation. */ -#define LUA_MAXCAPTURES 32 +#if !defined(LUA_USE_C89) +#define lua_strx2number(s,p) lua_str2number(s,p) +#endif /* -@@ lua_tmpnam is the function that the OS library uses to create a -@* temporary name. -@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam. -** CHANGE them if you have an alternative to tmpnam (which is considered -** insecure) or if you want the original tmpnam anyway. By default, Lua -** uses tmpnam except when POSIX is available, where it uses mkstemp. +@@ lua_number2strx converts a float to an hexadecimal numeric string. +** In C99, 'sprintf' (with format specifiers '%a'/'%A') does that. +** Otherwise, you can leave 'lua_number2strx' undefined and Lua will +** provide its own implementation. */ -#if defined(loslib_c) || defined(luaall_c) +#if !defined(LUA_USE_C89) +#define lua_number2strx(L,b,sz,f,n) ((void)L, l_sprintf(b,sz,f,n)) +#endif -#if defined(LUA_USE_MKSTEMP) -#include -#define LUA_TMPNAMBUFSIZE 32 -#define lua_tmpnam(b,e) { \ - strcpy(b, "/tmp/lua_XXXXXX"); \ - e = mkstemp(b); \ - if (e != -1) close(e); \ - e = (e == -1); } -#else -#define LUA_TMPNAMBUFSIZE L_tmpnam -#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } +/* +** 'strtof' and 'opf' variants for math functions are not valid in +** C89. Otherwise, the macro 'HUGE_VALF' is a good proxy for testing the +** availability of these variants. ('math.h' is already included in +** all files that use these macros.) +*/ +#if defined(LUA_USE_C89) || (defined(HUGE_VAL) && !defined(HUGE_VALF)) +#undef l_mathop /* variants not available */ +#undef lua_str2number +#define l_mathop(op) (lua_Number)op /* no variant */ +#define lua_str2number(s,p) ((lua_Number)strtod((s), (p))) #endif + +/* +@@ LUA_KCONTEXT is the type of the context ('ctx') for continuation +** functions. It must be a numerical type; Lua will use 'intptr_t' if +** available, otherwise it will use 'ptrdiff_t' (the nearest thing to +** 'intptr_t' in C89) +*/ +#define LUA_KCONTEXT ptrdiff_t + +#if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \ + __STDC_VERSION__ >= 199901L +#include +#if defined(INTPTR_MAX) /* even in C99 this type is optional */ +#undef LUA_KCONTEXT +#define LUA_KCONTEXT intptr_t +#endif #endif /* -@@ lua_popen spawns a new process connected to the current one through -@* the file streams. -** CHANGE it if you have a way to implement it in your system. +@@ lua_getlocaledecpoint gets the locale "radix character" (decimal point). +** Change that if you do not want to use C locales. (Code using this +** macro must include header 'locale.h'.) */ -#if defined(LUA_USE_POPEN) +#if !defined(lua_getlocaledecpoint) +//#define lua_getlocaledecpoint() (localeconv()->decimal_point[0]) +#define lua_getlocaledecpoint() ('.') +#endif -#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) -#define lua_pclose(L,file) ((void)L, (pclose(file) != -1)) +/* }================================================================== */ -#elif defined(LUA_WIN) -#define lua_popen(L,c,m) ((void)L, _popen(c,m)) -#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1)) +/* +** {================================================================== +** Language Variations +** ===================================================================== +*/ -#else +/* +@@ LUA_NOCVTN2S/LUA_NOCVTS2N control how Lua performs some +** coercions. Define LUA_NOCVTN2S to turn off automatic coercion from +** numbers to strings. Define LUA_NOCVTS2N to turn off automatic +** coercion from strings to numbers. +*/ +/* #define LUA_NOCVTN2S */ +/* #define LUA_NOCVTS2N */ -#define lua_popen(L,c,m) ((void)((void)c, m), \ - luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) -#define lua_pclose(L,file) ((void)((void)L, file), 0) +/* +@@ LUA_USE_APICHECK turns on several consistency checks on the C API. +** Define it as a help when debugging C code. +*/ +#if defined(LUA_USE_APICHECK) +#include +#define luai_apicheck(l,e) assert(e) #endif +/* }================================================================== */ + + /* -@@ LUA_DL_* define which dynamic-library system Lua should use. -** CHANGE here if Lua has problems choosing the appropriate -** dynamic-library system for your platform (either Windows' DLL, Mac's -** dyld, or Unix's dlopen). If your system is some kind of Unix, there -** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for -** it. To use dlopen you also need to adapt the src/Makefile (probably -** adding -ldl to the linker options), so Lua does not select it -** automatically. (When you change the makefile to add -ldl, you must -** also add -DLUA_USE_DLOPEN.) -** If you do not want any kind of dynamic library, undefine all these -** options. -** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD. -*/ -#if defined(LUA_USE_DLOPEN) -#define LUA_DL_DLOPEN -#endif +** {================================================================== +** Macros that affect the API and must be stable (that is, must be the +** same when you compile Lua and when you compile code that links to +** Lua). You probably do not want/need to change them. +** ===================================================================== +*/ -#if defined(LUA_WIN) -#define LUA_DL_DLL +/* +@@ LUAI_MAXSTACK limits the size of the Lua stack. +** CHANGE it if you need a different limit. This limit is arbitrary; +** its only purpose is to stop Lua from consuming unlimited stack +** space (and to reserve some numbers for pseudo-indices). +*/ +#if LUAI_BITSINT >= 32 +#define LUAI_MAXSTACK 1000000 +#else +#define LUAI_MAXSTACK 15000 #endif /* -@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State -@* (the data goes just *before* the lua_State pointer). -** CHANGE (define) this if you really need that. This value must be -** a multiple of the maximum alignment required for your machine. +@@ LUA_EXTRASPACE defines the size of a raw memory area associated with +** a Lua state with very fast access. +** CHANGE it if you need a different size. */ -#define LUAI_EXTRASPACE 0 +#define LUA_EXTRASPACE (sizeof(void *)) /* -@@ luai_userstate* allow user-specific actions on threads. -** CHANGE them if you defined LUAI_EXTRASPACE and need to do something -** extra when a thread is created/deleted/resumed/yielded. +@@ LUA_IDSIZE gives the maximum size for the description of the source +@@ of a function in debug information. +** CHANGE it if you want a different size. */ -#define luai_userstateopen(L) ((void)L) -#define luai_userstateclose(L) ((void)L) -#define luai_userstatethread(L,L1) ((void)L) -#define luai_userstatefree(L) ((void)L) -#define luai_userstateresume(L,n) ((void)L) -#define luai_userstateyield(L,n) ((void)L) +#define LUA_IDSIZE 60 /* -@@ LUA_INTFRMLEN is the length modifier for integer conversions -@* in 'string.format'. -@@ LUA_INTFRM_T is the integer type correspoding to the previous length -@* modifier. -** CHANGE them if your system supports long long or does not support long. +@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. +** CHANGE it if it uses too much C-stack space. (For long double, +** 'string.format("%.99f", 1e4932)' needs ~5030 bytes, so a +** smaller buffer would force a memory allocation for each call to +** 'string.format'.) */ +#if defined(LUA_FLOAT_LONGDOUBLE) +#define LUAL_BUFFERSIZE 8192 +#else +#define LUAL_BUFFERSIZE ((int)(0x80 * sizeof(void*) * sizeof(lua_Integer))) +#endif -#if defined(LUA_USELONGLONG) +/* }================================================================== */ -#define LUA_INTFRMLEN "ll" -#define LUA_INTFRM_T long long -#else - -#define LUA_INTFRMLEN "l" -#define LUA_INTFRM_T long +/* +@@ LUA_QL describes how error messages quote program elements. +** Lua does not use these macros anymore; they are here for +** compatibility only. +*/ +#define LUA_QL(x) "'" x "'" +#define LUA_QS LUA_QL("%s") -#endif @@ -758,5 +761,8 @@ union luai_Cast { double l_d; long l_l; }; */ + + + #endif diff --git a/app/src/main/jni/lua/lualib.h b/app/src/main/jni/lua/lualib.h index 469417f..5165c0f 100644 --- a/app/src/main/jni/lua/lualib.h +++ b/app/src/main/jni/lua/lualib.h @@ -1,5 +1,5 @@ /* -** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lualib.h,v 1.44 2014/02/06 17:32:33 roberto Exp $ ** Lua standard libraries ** See Copyright Notice in lua.h */ @@ -11,41 +11,46 @@ #include "lua.h" -/* Key to file-handle type */ -#define LUA_FILEHANDLE "FILE*" +LUAMOD_API int (luaopen_base) (lua_State *L); #define LUA_COLIBNAME "coroutine" -LUALIB_API int (luaopen_base) (lua_State *L); +LUAMOD_API int (luaopen_coroutine) (lua_State *L); #define LUA_TABLIBNAME "table" -LUALIB_API int (luaopen_table) (lua_State *L); +LUAMOD_API int (luaopen_table) (lua_State *L); #define LUA_IOLIBNAME "io" -LUALIB_API int (luaopen_io) (lua_State *L); +LUAMOD_API int (luaopen_io) (lua_State *L); #define LUA_OSLIBNAME "os" -LUALIB_API int (luaopen_os) (lua_State *L); +LUAMOD_API int (luaopen_os) (lua_State *L); #define LUA_STRLIBNAME "string" -LUALIB_API int (luaopen_string) (lua_State *L); +LUAMOD_API int (luaopen_string) (lua_State *L); + +#define LUA_UTF8LIBNAME "utf8" +LUAMOD_API int (luaopen_utf8) (lua_State *L); + +#define LUA_BITLIBNAME "bit32" +LUAMOD_API int (luaopen_bit32) (lua_State *L); #define LUA_MATHLIBNAME "math" -LUALIB_API int (luaopen_math) (lua_State *L); +LUAMOD_API int (luaopen_math) (lua_State *L); #define LUA_DBLIBNAME "debug" -LUALIB_API int (luaopen_debug) (lua_State *L); +LUAMOD_API int (luaopen_debug) (lua_State *L); #define LUA_LOADLIBNAME "package" -LUALIB_API int (luaopen_package) (lua_State *L); +LUAMOD_API int (luaopen_package) (lua_State *L); /* open all previous libraries */ -LUALIB_API void (luaL_openlibs) (lua_State *L); +LUALIB_API void (luaL_openlibs) (lua_State *L); -#ifndef lua_assert +#if !defined(lua_assert) #define lua_assert(x) ((void)0) #endif diff --git a/app/src/main/jni/lua/lundump.c b/app/src/main/jni/lua/lundump.c index 8010a45..4080af9 100644 --- a/app/src/main/jni/lua/lundump.c +++ b/app/src/main/jni/lua/lundump.c @@ -1,14 +1,17 @@ /* -** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $ +** $Id: lundump.c,v 2.44 2015/11/02 16:09:30 roberto Exp $ ** load precompiled Lua chunks ** See Copyright Notice in lua.h */ -#include - #define lundump_c #define LUA_CORE +#include "lprefix.h" + + +#include + #include "lua.h" #include "ldebug.h" @@ -20,208 +23,257 @@ #include "lundump.h" #include "lzio.h" + +#if !defined(luai_verifycode) +#define luai_verifycode(L,b,f) /* empty */ +#endif + + typedef struct { - lua_State* L; - ZIO* Z; - Mbuffer* b; - const char* name; + lua_State *L; + ZIO *Z; + const char *name; } LoadState; -#ifdef LUAC_TRUST_BINARIES -#define IF(c,s) -#define error(S,s) -#else -#define IF(c,s) if (c) error(S,s) -static void error(LoadState* S, const char* why) -{ - luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why); - luaD_throw(S->L,LUA_ERRSYNTAX); +static l_noret error(LoadState *S, const char *why) { + luaO_pushfstring(S->L, "%s: %s precompiled chunk", S->name, why); + luaD_throw(S->L, LUA_ERRSYNTAX); } -#endif -#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) -#define LoadByte(S) (lu_byte)LoadChar(S) -#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) -#define LoadVector(S,b,n,size) LoadMem(S,b,n,size) - -static void LoadBlock(LoadState* S, void* b, size_t size) -{ - size_t r=luaZ_read(S->Z,b,size); - IF (r!=0, "unexpected end"); -} - -static int LoadChar(LoadState* S) -{ - char x; - LoadVar(S,x); - return x; -} - -static int LoadInt(LoadState* S) -{ - int x; - LoadVar(S,x); - IF (x<0, "bad integer"); - return x; -} - -static lua_Number LoadNumber(LoadState* S) -{ - lua_Number x; - LoadVar(S,x); - return x; -} - -static TString* LoadString(LoadState* S) -{ - size_t size; - LoadVar(S,size); - if (size==0) - return NULL; - else - { - char* s=luaZ_openspace(S->L,S->b,size); - LoadBlock(S,s,size); - return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ - } -} - -static void LoadCode(LoadState* S, Proto* f) -{ - int n=LoadInt(S); - f->code=luaM_newvector(S->L,n,Instruction); - f->sizecode=n; - LoadVector(S,f->code,n,sizeof(Instruction)); -} - -static Proto* LoadFunction(LoadState* S, TString* p); - -static void LoadConstants(LoadState* S, Proto* f) -{ - int i,n; - n=LoadInt(S); - f->k=luaM_newvector(S->L,n,TValue); - f->sizek=n; - for (i=0; ik[i]); - for (i=0; ik[i]; - int t=LoadChar(S); - switch (t) - { - case LUA_TNIL: - setnilvalue(o); - break; - case LUA_TBOOLEAN: - setbvalue(o,LoadChar(S)!=0); - break; - case LUA_TNUMBER: - setnvalue(o,LoadNumber(S)); - break; - case LUA_TSTRING: - setsvalue2n(S->L,o,LoadString(S)); - break; - default: - error(S,"bad constant"); - break; - } - } - n=LoadInt(S); - f->p=luaM_newvector(S->L,n,Proto*); - f->sizep=n; - for (i=0; ip[i]=NULL; - for (i=0; ip[i]=LoadFunction(S,f->source); -} - -static void LoadDebug(LoadState* S, Proto* f) -{ - int i,n; - n=LoadInt(S); - f->lineinfo=luaM_newvector(S->L,n,int); - f->sizelineinfo=n; - LoadVector(S,f->lineinfo,n,sizeof(int)); - n=LoadInt(S); - f->locvars=luaM_newvector(S->L,n,LocVar); - f->sizelocvars=n; - for (i=0; ilocvars[i].varname=NULL; - for (i=0; ilocvars[i].varname=LoadString(S); - f->locvars[i].startpc=LoadInt(S); - f->locvars[i].endpc=LoadInt(S); - } - n=LoadInt(S); - f->upvalues=luaM_newvector(S->L,n,TString*); - f->sizeupvalues=n; - for (i=0; iupvalues[i]=NULL; - for (i=0; iupvalues[i]=LoadString(S); -} - -static Proto* LoadFunction(LoadState* S, TString* p) -{ - Proto* f; - if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep"); - f=luaF_newproto(S->L); - setptvalue2s(S->L,S->L->top,f); incr_top(S->L); - f->source=LoadString(S); if (f->source==NULL) f->source=p; - f->linedefined=LoadInt(S); - f->lastlinedefined=LoadInt(S); - f->nups=LoadByte(S); - f->numparams=LoadByte(S); - f->is_vararg=LoadByte(S); - f->maxstacksize=LoadByte(S); - LoadCode(S,f); - LoadConstants(S,f); - LoadDebug(S,f); - IF (!luaG_checkcode(f), "bad code"); - S->L->top--; - S->L->nCcalls--; - return f; -} - -static void LoadHeader(LoadState* S) -{ - char h[LUAC_HEADERSIZE]; - char s[LUAC_HEADERSIZE]; - luaU_header(h); - LoadBlock(S,s,LUAC_HEADERSIZE); - IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header"); -} /* -** load precompiled chunk +** All high-level loads go through LoadVector; you can change it to +** adapt to the endianness of the input */ -Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) -{ - LoadState S; - if (*name=='@' || *name=='=') - S.name=name+1; - else if (*name==LUA_SIGNATURE[0]) - S.name="binary string"; - else - S.name=name; - S.L=L; - S.Z=Z; - S.b=buff; - LoadHeader(&S); - return LoadFunction(&S,luaS_newliteral(L,"=?")); +#define LoadVector(S,b,n) LoadBlock(S,b,(n)*sizeof((b)[0])) + +static void LoadBlock (LoadState *S, void *b, size_t size) { + if (luaZ_read(S->Z, b, size) != 0) + error(S, "truncated"); +} + + +#define LoadVar(S,x) LoadVector(S,&x,1) + + +static lu_byte LoadByte (LoadState *S) { + lu_byte x; + LoadVar(S, x); + return x; +} + + +static int LoadInt (LoadState *S) { + int x; + LoadVar(S, x); + return x; +} + + +static lua_Number LoadNumber (LoadState *S) { + lua_Number x; + LoadVar(S, x); + return x; +} + + +static lua_Integer LoadInteger (LoadState *S) { + lua_Integer x; + LoadVar(S, x); + return x; } + +static TString *LoadString (LoadState *S) { + size_t size = LoadByte(S); + if (size == 0xFF) + LoadVar(S, size); + if (size == 0) + return NULL; + else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */ + char buff[LUAI_MAXSHORTLEN]; + LoadVector(S, buff, size); + return luaS_newlstr(S->L, buff, size); + } + else { /* long string */ + TString *ts = luaS_createlngstrobj(S->L, size); + LoadVector(S, getstr(ts), size); /* load directly in final place */ + return ts; + } +} + + +static void LoadCode (LoadState *S, Proto *f) { + int n = LoadInt(S); + f->code = luaM_newvector(S->L, n, Instruction); + f->sizecode = n; + LoadVector(S, f->code, n); +} + + +static void LoadFunction(LoadState *S, Proto *f, TString *psource); + + +static void LoadConstants (LoadState *S, Proto *f) { + int i; + int n = LoadInt(S); + f->k = luaM_newvector(S->L, n, TValue); + f->sizek = n; + for (i = 0; i < n; i++) + setnilvalue(&f->k[i]); + for (i = 0; i < n; i++) { + TValue *o = &f->k[i]; + int t = LoadByte(S); + switch (t) { + case LUA_TNIL: + setnilvalue(o); + break; + case LUA_TBOOLEAN: + setbvalue(o, LoadByte(S)); + break; + case LUA_TNUMFLT: + setfltvalue(o, LoadNumber(S)); + break; + case LUA_TNUMINT: + setivalue(o, LoadInteger(S)); + break; + case LUA_TSHRSTR: + case LUA_TLNGSTR: + setsvalue2n(S->L, o, LoadString(S)); + break; + default: + lua_assert(0); + } + } +} + + +static void LoadProtos (LoadState *S, Proto *f) { + int i; + int n = LoadInt(S); + f->p = luaM_newvector(S->L, n, Proto *); + f->sizep = n; + for (i = 0; i < n; i++) + f->p[i] = NULL; + for (i = 0; i < n; i++) { + f->p[i] = luaF_newproto(S->L); + LoadFunction(S, f->p[i], f->source); + } +} + + +static void LoadUpvalues (LoadState *S, Proto *f) { + int i, n; + n = LoadInt(S); + f->upvalues = luaM_newvector(S->L, n, Upvaldesc); + f->sizeupvalues = n; + for (i = 0; i < n; i++) + f->upvalues[i].name = NULL; + for (i = 0; i < n; i++) { + f->upvalues[i].instack = LoadByte(S); + f->upvalues[i].idx = LoadByte(S); + } +} + + +static void LoadDebug (LoadState *S, Proto *f) { + int i, n; + n = LoadInt(S); + f->lineinfo = luaM_newvector(S->L, n, int); + f->sizelineinfo = n; + LoadVector(S, f->lineinfo, n); + n = LoadInt(S); + f->locvars = luaM_newvector(S->L, n, LocVar); + f->sizelocvars = n; + for (i = 0; i < n; i++) + f->locvars[i].varname = NULL; + for (i = 0; i < n; i++) { + f->locvars[i].varname = LoadString(S); + f->locvars[i].startpc = LoadInt(S); + f->locvars[i].endpc = LoadInt(S); + } + n = LoadInt(S); + for (i = 0; i < n; i++) + f->upvalues[i].name = LoadString(S); +} + + +static void LoadFunction (LoadState *S, Proto *f, TString *psource) { + f->source = LoadString(S); + if (f->source == NULL) /* no source in dump? */ + f->source = psource; /* reuse parent's source */ + f->linedefined = LoadInt(S); + f->lastlinedefined = LoadInt(S); + f->numparams = LoadByte(S); + f->is_vararg = LoadByte(S); + f->maxstacksize = LoadByte(S); + LoadCode(S, f); + LoadConstants(S, f); + LoadUpvalues(S, f); + LoadProtos(S, f); + LoadDebug(S, f); +} + + +static void checkliteral (LoadState *S, const char *s, const char *msg) { + char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */ + size_t len = strlen(s); + LoadVector(S, buff, len); + if (memcmp(s, buff, len) != 0) + error(S, msg); +} + + +static void fchecksize (LoadState *S, size_t size, const char *tname) { + if (LoadByte(S) != size) + error(S, luaO_pushfstring(S->L, "%s size mismatch in", tname)); +} + + +#define checksize(S,t) fchecksize(S,sizeof(t),#t) + +static void checkHeader (LoadState *S) { + checkliteral(S, LUA_SIGNATURE + 1, "not a"); /* 1st char already checked */ + if (LoadByte(S) != LUAC_VERSION) + error(S, "version mismatch in"); + if (LoadByte(S) != LUAC_FORMAT) + error(S, "format mismatch in"); + checkliteral(S, LUAC_DATA, "corrupted"); + checksize(S, int); + checksize(S, size_t); + checksize(S, Instruction); + checksize(S, lua_Integer); + checksize(S, lua_Number); + if (LoadInteger(S) != LUAC_INT) + error(S, "endianness mismatch in"); + if (LoadNumber(S) != LUAC_NUM) + error(S, "float format mismatch in"); +} + + /* -* make header +** load precompiled chunk */ -void luaU_header (char* h) -{ - int x=1; - memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1); - h+=sizeof(LUA_SIGNATURE)-1; - *h++=(char)LUAC_VERSION; - *h++=(char)LUAC_FORMAT; - *h++=(char)*(char*)&x; /* endianness */ - *h++=(char)sizeof(int); - *h++=(char)sizeof(size_t); - *h++=(char)sizeof(Instruction); - *h++=(char)sizeof(lua_Number); - *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ +LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) { + LoadState S; + LClosure *cl; + if (*name == '@' || *name == '=') + S.name = name + 1; + else if (*name == LUA_SIGNATURE[0]) + S.name = "binary string"; + else + S.name = name; + S.L = L; + S.Z = Z; + checkHeader(&S); + cl = luaF_newLclosure(L, LoadByte(&S)); + setclLvalue(L, L->top, cl); + luaD_inctop(L); + cl->p = luaF_newproto(L); + LoadFunction(&S, cl->p, NULL); + lua_assert(cl->nupvalues == cl->p->sizeupvalues); + luai_verifycode(L, buff, cl->p); + return cl; } + diff --git a/app/src/main/jni/lua/lundump.h b/app/src/main/jni/lua/lundump.h index c80189d..aa5cc82 100644 --- a/app/src/main/jni/lua/lundump.h +++ b/app/src/main/jni/lua/lundump.h @@ -1,5 +1,5 @@ /* -** $Id: lundump.h,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lundump.h,v 1.45 2015/09/08 15:41:05 roberto Exp $ ** load precompiled Lua chunks ** See Copyright Notice in lua.h */ @@ -7,30 +7,26 @@ #ifndef lundump_h #define lundump_h +#include "llimits.h" #include "lobject.h" #include "lzio.h" -/* load one chunk; from lundump.c */ -LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); - -/* make header; from lundump.c */ -LUAI_FUNC void luaU_header (char* h); -/* dump one chunk; from ldump.c */ -LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); +/* data to catch conversion errors */ +#define LUAC_DATA "\x19\x93\r\n\x1a\n" -#ifdef luac_c -/* print one chunk; from print.c */ -LUAI_FUNC void luaU_print (const Proto* f, int full); -#endif +#define LUAC_INT 0x5678 +#define LUAC_NUM cast_num(370.5) -/* for header of binary files -- this is Lua 5.1 */ -#define LUAC_VERSION 0x51 +#define MYINT(s) (s[0]-'0') +#define LUAC_VERSION (MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR)) +#define LUAC_FORMAT 0 /* this is the official format */ -/* for header of binary files -- this is the official format */ -#define LUAC_FORMAT 0 +/* load one chunk; from lundump.c */ +LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name); -/* size of header of binary files */ -#define LUAC_HEADERSIZE 12 +/* dump one chunk; from ldump.c */ +LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, + void* data, int strip); #endif diff --git a/app/src/main/jni/lua/lutf8lib.c b/app/src/main/jni/lua/lutf8lib.c new file mode 100644 index 0000000..9042582 --- /dev/null +++ b/app/src/main/jni/lua/lutf8lib.c @@ -0,0 +1,256 @@ +/* +** $Id: lutf8lib.c,v 1.15 2015/03/28 19:16:55 roberto Exp $ +** Standard library for UTF-8 manipulation +** See Copyright Notice in lua.h +*/ + +#define lutf8lib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + +#define MAXUNICODE 0x10FFFF + +#define iscont(p) ((*(p) & 0xC0) == 0x80) + + +/* from strlib */ +/* translate a relative string position: negative means back from end */ +static lua_Integer u_posrelat (lua_Integer pos, size_t len) { + if (pos >= 0) return pos; + else if (0u - (size_t)pos > len) return 0; + else return (lua_Integer)len + pos + 1; +} + + +/* +** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid. +*/ +static const char *utf8_decode (const char *o, int *val) { + static const unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF}; + const unsigned char *s = (const unsigned char *)o; + unsigned int c = s[0]; + unsigned int res = 0; /* final result */ + if (c < 0x80) /* ascii? */ + res = c; + else { + int count = 0; /* to count number of continuation bytes */ + while (c & 0x40) { /* still have continuation bytes? */ + int cc = s[++count]; /* read next byte */ + if ((cc & 0xC0) != 0x80) /* not a continuation byte? */ + return NULL; /* invalid byte sequence */ + res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ + c <<= 1; /* to test next bit */ + } + res |= ((c & 0x7F) << (count * 5)); /* add first byte */ + if (count > 3 || res > MAXUNICODE || res <= limits[count]) + return NULL; /* invalid byte sequence */ + s += count; /* skip continuation bytes read */ + } + if (val) *val = res; + return (const char *)s + 1; /* +1 to include first byte */ +} + + +/* +** utf8len(s [, i [, j]]) --> number of characters that start in the +** range [i,j], or nil + current position if 's' is not well formed in +** that interval +*/ +static int utflen (lua_State *L) { + int n = 0; + size_t len; + const char *s = luaL_checklstring(L, 1, &len); + lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); + lua_Integer posj = u_posrelat(luaL_optinteger(L, 3, -1), len); + luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2, + "initial position out of string"); + luaL_argcheck(L, --posj < (lua_Integer)len, 3, + "final position out of string"); + while (posi <= posj) { + const char *s1 = utf8_decode(s + posi, NULL); + if (s1 == NULL) { /* conversion error? */ + lua_pushnil(L); /* return nil ... */ + lua_pushinteger(L, posi + 1); /* ... and current position */ + return 2; + } + posi = s1 - s; + n++; + } + lua_pushinteger(L, n); + return 1; +} + + +/* +** codepoint(s, [i, [j]]) -> returns codepoints for all characters +** that start in the range [i,j] +*/ +static int codepoint (lua_State *L) { + size_t len; + const char *s = luaL_checklstring(L, 1, &len); + lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); + lua_Integer pose = u_posrelat(luaL_optinteger(L, 3, posi), len); + int n; + const char *se; + luaL_argcheck(L, posi >= 1, 2, "out of range"); + luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of range"); + if (posi > pose) return 0; /* empty interval; return no values */ + if (pose - posi >= INT_MAX) /* (lua_Integer -> int) overflow? */ + return luaL_error(L, "string slice too long"); + n = (int)(pose - posi) + 1; + luaL_checkstack(L, n, "string slice too long"); + n = 0; + se = s + pose; + for (s += posi - 1; s < se;) { + int code; + s = utf8_decode(s, &code); + if (s == NULL) + return luaL_error(L, "invalid UTF-8 code"); + lua_pushinteger(L, code); + n++; + } + return n; +} + + +static void pushutfchar (lua_State *L, int arg) { + lua_Integer code = luaL_checkinteger(L, arg); + luaL_argcheck(L, 0 <= code && code <= MAXUNICODE, arg, "value out of range"); + lua_pushfstring(L, "%U", (long)code); +} + + +/* +** utfchar(n1, n2, ...) -> char(n1)..char(n2)... +*/ +static int utfchar (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + if (n == 1) /* optimize common case of single char */ + pushutfchar(L, 1); + else { + int i; + luaL_Buffer b; + luaL_buffinit(L, &b); + for (i = 1; i <= n; i++) { + pushutfchar(L, i); + luaL_addvalue(&b); + } + luaL_pushresult(&b); + } + return 1; +} + + +/* +** offset(s, n, [i]) -> index where n-th character counting from +** position 'i' starts; 0 means character at 'i'. +*/ +static int byteoffset (lua_State *L) { + size_t len; + const char *s = luaL_checklstring(L, 1, &len); + lua_Integer n = luaL_checkinteger(L, 2); + lua_Integer posi = (n >= 0) ? 1 : len + 1; + posi = u_posrelat(luaL_optinteger(L, 3, posi), len); + luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 3, + "position out of range"); + if (n == 0) { + /* find beginning of current byte sequence */ + while (posi > 0 && iscont(s + posi)) posi--; + } + else { + if (iscont(s + posi)) + luaL_error(L, "initial position is a continuation byte"); + if (n < 0) { + while (n < 0 && posi > 0) { /* move back */ + do { /* find beginning of previous character */ + posi--; + } while (posi > 0 && iscont(s + posi)); + n++; + } + } + else { + n--; /* do not move for 1st character */ + while (n > 0 && posi < (lua_Integer)len) { + do { /* find beginning of next character */ + posi++; + } while (iscont(s + posi)); /* (cannot pass final '\0') */ + n--; + } + } + } + if (n == 0) /* did it find given character? */ + lua_pushinteger(L, posi + 1); + else /* no such character */ + lua_pushnil(L); + return 1; +} + + +static int iter_aux (lua_State *L) { + size_t len; + const char *s = luaL_checklstring(L, 1, &len); + lua_Integer n = lua_tointeger(L, 2) - 1; + if (n < 0) /* first iteration? */ + n = 0; /* start from here */ + else if (n < (lua_Integer)len) { + n++; /* skip current byte */ + while (iscont(s + n)) n++; /* and its continuations */ + } + if (n >= (lua_Integer)len) + return 0; /* no more codepoints */ + else { + int code; + const char *next = utf8_decode(s + n, &code); + if (next == NULL || iscont(next)) + return luaL_error(L, "invalid UTF-8 code"); + lua_pushinteger(L, n + 1); + lua_pushinteger(L, code); + return 2; + } +} + + +static int iter_codes (lua_State *L) { + luaL_checkstring(L, 1); + lua_pushcfunction(L, iter_aux); + lua_pushvalue(L, 1); + lua_pushinteger(L, 0); + return 3; +} + + +/* pattern to match a single UTF-8 character */ +#define UTF8PATT "[\0-\x7F\xC2-\xF4][\x80-\xBF]*" + + +static const luaL_Reg funcs[] = { + {"offset", byteoffset}, + {"codepoint", codepoint}, + {"char", utfchar}, + {"len", utflen}, + {"codes", iter_codes}, + /* placeholders */ + {"charpattern", NULL}, + {NULL, NULL} +}; + + +LUAMOD_API int luaopen_utf8 (lua_State *L) { + luaL_newlib(L, funcs); + lua_pushlstring(L, UTF8PATT, sizeof(UTF8PATT)/sizeof(char) - 1); + lua_setfield(L, -2, "charpattern"); + return 1; +} + diff --git a/app/src/main/jni/lua/lvm.c b/app/src/main/jni/lua/lvm.c index e0a0cd8..84ade6b 100644 --- a/app/src/main/jni/lua/lvm.c +++ b/app/src/main/jni/lua/lvm.c @@ -1,17 +1,21 @@ /* -** $Id: lvm.c,v 2.63.1.5 2011/08/17 20:43:11 roberto Exp $ +** $Id: lvm.c,v 2.268 2016/02/05 19:59:14 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ +#define lvm_c +#define LUA_CORE + +#include "lprefix.h" +#include +#include +#include #include #include #include -#define lvm_c -#define LUA_CORE - #include "lua.h" #include "ldebug.h" @@ -27,741 +31,1292 @@ #include "lvm.h" - /* limit for table tag-method chains (to avoid loops) */ -#define MAXTAGLOOP 100 +#define MAXTAGLOOP 2000 -const TValue *luaV_tonumber (const TValue *obj, TValue *n) { - lua_Number num; - if (ttisnumber(obj)) return obj; - if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) { - setnvalue(n, num); - return n; - } - else - return NULL; -} +/* +** 'l_intfitsf' checks whether a given integer can be converted to a +** float without rounding. Used in comparisons. Left undefined if +** all integers fit in a float precisely. +*/ +#if !defined(l_intfitsf) -int luaV_tostring (lua_State *L, StkId obj) { - if (!ttisnumber(obj)) - return 0; - else { - char s[LUAI_MAXNUMBER2STR]; - lua_Number n = nvalue(obj); - lua_number2str(s, n); - setsvalue2s(L, obj, luaS_new(L, s)); - return 1; - } -} +/* number of bits in the mantissa of a float */ +#define NBM (l_mathlim(MANT_DIG)) + +/* +** Check whether some integers may not fit in a float, that is, whether +** (maxinteger >> NBM) > 0 (that implies (1 << NBM) <= maxinteger). +** (The shifts are done in parts to avoid shifting by more than the size +** of an integer. In a worst case, NBM == 113 for long double and +** sizeof(integer) == 32.) +*/ +#if ((((LUA_MAXINTEGER >> (NBM / 4)) >> (NBM / 4)) >> (NBM / 4)) \ + >> (NBM - (3 * (NBM / 4)))) > 0 +#define l_intfitsf(i) \ + (-((lua_Integer)1 << NBM) <= (i) && (i) <= ((lua_Integer)1 << NBM)) -static void traceexec (lua_State *L, const Instruction *pc) { - lu_byte mask = L->hookmask; - const Instruction *oldpc = L->savedpc; - L->savedpc = pc; - if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) { - resethookcount(L); - luaD_callhook(L, LUA_HOOKCOUNT, -1); +#endif + +#endif + + + +/* +** Try to convert a value to a float. The float case is already handled +** by the macro 'tonumber'. +*/ +int luaV_tonumber_ (const TValue *obj, lua_Number *n) { + TValue v; + if (ttisinteger(obj)) { + *n = cast_num(ivalue(obj)); + return 1; } - if (mask & LUA_MASKLINE) { - Proto *p = ci_func(L->ci)->l.p; - int npc = pcRel(pc, p); - int newline = getline(p, npc); - /* call linehook when enter a new function, when jump back (loop), - or when enter a new line */ - if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p))) - luaD_callhook(L, LUA_HOOKLINE, newline); + else if (cvt2num(obj) && /* string convertible to number? */ + luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) { + *n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */ + return 1; } + else + return 0; /* conversion failed */ } -static void callTMres (lua_State *L, StkId res, const TValue *f, - const TValue *p1, const TValue *p2) { - ptrdiff_t result = savestack(L, res); - setobj2s(L, L->top, f); /* push function */ - setobj2s(L, L->top+1, p1); /* 1st argument */ - setobj2s(L, L->top+2, p2); /* 2nd argument */ - luaD_checkstack(L, 3); - L->top += 3; - luaD_call(L, L->top - 3, 1); - res = restorestack(L, result); - L->top--; - setobjs2s(L, res, L->top); +/* +** try to convert a value to an integer, rounding according to 'mode': +** mode == 0: accepts only integral values +** mode == 1: takes the floor of the number +** mode == 2: takes the ceil of the number +*/ +int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) { + TValue v; + again: + if (ttisfloat(obj)) { + lua_Number n = fltvalue(obj); + lua_Number f = l_floor(n); + if (n != f) { /* not an integral value? */ + if (mode == 0) return 0; /* fails if mode demands integral value */ + else if (mode > 1) /* needs ceil? */ + f += 1; /* convert floor to ceil (remember: n != f) */ + } + return lua_numbertointeger(f, p); + } + else if (ttisinteger(obj)) { + *p = ivalue(obj); + return 1; + } + else if (cvt2num(obj) && + luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) { + obj = &v; + goto again; /* convert result from 'luaO_str2num' to an integer */ + } + return 0; /* conversion failed */ } - -static void callTM (lua_State *L, const TValue *f, const TValue *p1, - const TValue *p2, const TValue *p3) { - setobj2s(L, L->top, f); /* push function */ - setobj2s(L, L->top+1, p1); /* 1st argument */ - setobj2s(L, L->top+2, p2); /* 2nd argument */ - setobj2s(L, L->top+3, p3); /* 3th argument */ - luaD_checkstack(L, 4); - L->top += 4; - luaD_call(L, L->top - 4, 0); +/* +** Try to convert a 'for' limit to an integer, preserving the +** semantics of the loop. +** (The following explanation assumes a non-negative step; it is valid +** for negative steps mutatis mutandis.) +** If the limit can be converted to an integer, rounding down, that is +** it. +** Otherwise, check whether the limit can be converted to a number. If +** the number is too large, it is OK to set the limit as LUA_MAXINTEGER, +** which means no limit. If the number is too negative, the loop +** should not run, because any initial integer value is larger than the +** limit. So, it sets the limit to LUA_MININTEGER. 'stopnow' corrects +** the extreme case when the initial value is LUA_MININTEGER, in which +** case the LUA_MININTEGER limit would still run the loop once. +*/ +static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step, + int *stopnow) { + *stopnow = 0; /* usually, let loops run */ + if (!luaV_tointeger(obj, p, (step < 0 ? 2 : 1))) { /* not fit in integer? */ + lua_Number n; /* try to convert to float */ + if (!tonumber(obj, &n)) /* cannot convert to float? */ + return 0; /* not a number */ + if (luai_numlt(0, n)) { /* if true, float is larger than max integer */ + *p = LUA_MAXINTEGER; + if (step < 0) *stopnow = 1; + } + else { /* float is smaller than min integer */ + *p = LUA_MININTEGER; + if (step >= 0) *stopnow = 1; + } + } + return 1; } -void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { - int loop; +/* +** Finish the table access 'val = t[key]'. +** if 'slot' is NULL, 't' is not a table; otherwise, 'slot' points to +** t[k] entry (which must be nil). +*/ +void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, + const TValue *slot) { + int loop; /* counter to avoid infinite loops */ + const TValue *tm; /* metamethod */ for (loop = 0; loop < MAXTAGLOOP; loop++) { - const TValue *tm; - if (ttistable(t)) { /* `t' is a table? */ - Table *h = hvalue(t); - const TValue *res = luaH_get(h, key); /* do a primitive get */ - if (!ttisnil(res) || /* result is no nil? */ - (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ - setobj2s(L, val, res); + if (slot == NULL) { /* 't' is not a table? */ + lua_assert(!ttistable(t)); + tm = luaT_gettmbyobj(L, t, TM_INDEX); + if (ttisnil(tm)) + luaG_typeerror(L, t, "index"); /* no metamethod */ + /* else will try the metamethod */ + } + else { /* 't' is a table */ + lua_assert(ttisnil(slot)); + tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */ + if (tm == NULL) { /* no metamethod? */ + setnilvalue(val); /* result is nil */ return; } - /* else will try the tag method */ + /* else will try the metamethod */ } - else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) - luaG_typeerror(L, t, "index"); - if (ttisfunction(tm)) { - callTMres(L, val, tm, t, key); + if (ttisfunction(tm)) { /* is metamethod a function? */ + luaT_callTM(L, tm, t, key, val, 1); /* call it */ return; } - t = tm; /* else repeat with `tm' */ + t = tm; /* else try to access 'tm[key]' */ + if (luaV_fastget(L,t,key,slot,luaH_get)) { /* fast track? */ + setobj2s(L, val, slot); /* done */ + return; + } + /* else repeat (tail call 'luaV_finishget') */ } - luaG_runerror(L, "loop in gettable"); + luaG_runerror(L, "'__index' chain too long; possible loop"); } -void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { - int loop; - TValue temp; +/* +** Finish a table assignment 't[key] = val'. +** If 'slot' is NULL, 't' is not a table. Otherwise, 'slot' points +** to the entry 't[key]', or to 'luaO_nilobject' if there is no such +** entry. (The value at 'slot' must be nil, otherwise 'luaV_fastset' +** would have done the job.) +*/ +void luaV_finishset (lua_State *L, const TValue *t, TValue *key, + StkId val, const TValue *slot) { + int loop; /* counter to avoid infinite loops */ for (loop = 0; loop < MAXTAGLOOP; loop++) { - const TValue *tm; - if (ttistable(t)) { /* `t' is a table? */ - Table *h = hvalue(t); - TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ - if (!ttisnil(oldval) || /* result is no nil? */ - (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ - setobj2t(L, oldval, val); - h->flags = 0; - luaC_barriert(L, h, val); + const TValue *tm; /* '__newindex' metamethod */ + if (slot != NULL) { /* is 't' a table? */ + Table *h = hvalue(t); /* save 't' table */ + lua_assert(ttisnil(slot)); /* old value must be nil */ + tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */ + if (tm == NULL) { /* no metamethod? */ + if (slot == luaO_nilobject) /* no previous entry? */ + slot = luaH_newkey(L, h, key); /* create one */ + /* no metamethod and (now) there is an entry with given key */ + setobj2t(L, cast(TValue *, slot), val); /* set its new value */ + invalidateTMcache(h); + luaC_barrierback(L, h, val); return; } - /* else will try the tag method */ + /* else will try the metamethod */ + } + else { /* not a table; check metamethod */ + if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) + luaG_typeerror(L, t, "index"); } - else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) - luaG_typeerror(L, t, "index"); + /* try the metamethod */ if (ttisfunction(tm)) { - callTM(L, tm, t, key, val); + luaT_callTM(L, tm, t, key, val, 0); return; } - /* else repeat with `tm' */ - setobj(L, &temp, tm); /* avoid pointing inside table (may rehash) */ - t = &temp; + t = tm; /* else repeat assignment over 'tm' */ + if (luaV_fastset(L, t, key, slot, luaH_get, val)) + return; /* done */ + /* else loop */ } - luaG_runerror(L, "loop in settable"); + luaG_runerror(L, "'__newindex' chain too long; possible loop"); } -static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2, - StkId res, TMS event) { - const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ - if (ttisnil(tm)) - tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ - if (ttisnil(tm)) return 0; - callTMres(L, res, tm, p1, p2); - return 1; +/* +** Compare two strings 'ls' x 'rs', returning an integer smaller-equal- +** -larger than zero if 'ls' is smaller-equal-larger than 'rs'. +** The code is a little tricky because it allows '\0' in the strings +** and it uses 'strcoll' (to respect locales) for each segments +** of the strings. +*/ +static int l_strcmp (const TString *ls, const TString *rs) { + const char *l = getstr(ls); + size_t ll = tsslen(ls); + const char *r = getstr(rs); + size_t lr = tsslen(rs); + for (;;) { /* for each segment */ + int temp = strcoll(l, r); + if (temp != 0) /* not equal? */ + return temp; /* done */ + else { /* strings are equal up to a '\0' */ + size_t len = strlen(l); /* index of first '\0' in both strings */ + if (len == lr) /* 'rs' is finished? */ + return (len == ll) ? 0 : 1; /* check 'ls' */ + else if (len == ll) /* 'ls' is finished? */ + return -1; /* 'ls' is smaller than 'rs' ('rs' is not finished) */ + /* both strings longer than 'len'; go on comparing after the '\0' */ + len++; + l += len; ll -= len; r += len; lr -= len; + } + } } -static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2, - TMS event) { - const TValue *tm1 = fasttm(L, mt1, event); - const TValue *tm2; - if (tm1 == NULL) return NULL; /* no metamethod */ - if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ - tm2 = fasttm(L, mt2, event); - if (tm2 == NULL) return NULL; /* no metamethod */ - if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */ - return tm1; - return NULL; +/* +** Check whether integer 'i' is less than float 'f'. If 'i' has an +** exact representation as a float ('l_intfitsf'), compare numbers as +** floats. Otherwise, if 'f' is outside the range for integers, result +** is trivial. Otherwise, compare them as integers. (When 'i' has no +** float representation, either 'f' is "far away" from 'i' or 'f' has +** no precision left for a fractional part; either way, how 'f' is +** truncated is irrelevant.) When 'f' is NaN, comparisons must result +** in false. +*/ +static int LTintfloat (lua_Integer i, lua_Number f) { +#if defined(l_intfitsf) + if (!l_intfitsf(i)) { + if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */ + return 1; /* f >= maxint + 1 > i */ + else if (f > cast_num(LUA_MININTEGER)) /* minint < f <= maxint ? */ + return (i < cast(lua_Integer, f)); /* compare them as integers */ + else /* f <= minint <= i (or 'f' is NaN) --> not(i < f) */ + return 0; + } +#endif + return luai_numlt(cast_num(i), f); /* compare them as floats */ } -static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, - TMS event) { - const TValue *tm1 = luaT_gettmbyobj(L, p1, event); - const TValue *tm2; - if (ttisnil(tm1)) return -1; /* no metamethod? */ - tm2 = luaT_gettmbyobj(L, p2, event); - if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */ - return -1; - callTMres(L, L->top, tm1, p1, p2); - return !l_isfalse(L->top); +/* +** Check whether integer 'i' is less than or equal to float 'f'. +** See comments on previous function. +*/ +static int LEintfloat (lua_Integer i, lua_Number f) { +#if defined(l_intfitsf) + if (!l_intfitsf(i)) { + if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */ + return 1; /* f >= maxint + 1 > i */ + else if (f >= cast_num(LUA_MININTEGER)) /* minint <= f <= maxint ? */ + return (i <= cast(lua_Integer, f)); /* compare them as integers */ + else /* f < minint <= i (or 'f' is NaN) --> not(i <= f) */ + return 0; + } +#endif + return luai_numle(cast_num(i), f); /* compare them as floats */ } -static int l_strcmp (const TString *ls, const TString *rs) { - const char *l = getstr(ls); - size_t ll = ls->tsv.len; - const char *r = getstr(rs); - size_t lr = rs->tsv.len; - for (;;) { - int temp = strcoll(l, r); - if (temp != 0) return temp; - else { /* strings are equal up to a `\0' */ - size_t len = strlen(l); /* index of first `\0' in both strings */ - if (len == lr) /* r is finished? */ - return (len == ll) ? 0 : 1; - else if (len == ll) /* l is finished? */ - return -1; /* l is smaller than r (because r is not finished) */ - /* both strings longer than `len'; go on comparing (after the `\0') */ - len++; - l += len; ll -= len; r += len; lr -= len; - } +/* +** Return 'l < r', for numbers. +*/ +static int LTnum (const TValue *l, const TValue *r) { + if (ttisinteger(l)) { + lua_Integer li = ivalue(l); + if (ttisinteger(r)) + return li < ivalue(r); /* both are integers */ + else /* 'l' is int and 'r' is float */ + return LTintfloat(li, fltvalue(r)); /* l < r ? */ + } + else { + lua_Number lf = fltvalue(l); /* 'l' must be float */ + if (ttisfloat(r)) + return luai_numlt(lf, fltvalue(r)); /* both are float */ + else if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */ + return 0; /* NaN < i is always false */ + else /* without NaN, (l < r) <--> not(r <= l) */ + return !LEintfloat(ivalue(r), lf); /* not (r <= l) ? */ } } +/* +** Return 'l <= r', for numbers. +*/ +static int LEnum (const TValue *l, const TValue *r) { + if (ttisinteger(l)) { + lua_Integer li = ivalue(l); + if (ttisinteger(r)) + return li <= ivalue(r); /* both are integers */ + else /* 'l' is int and 'r' is float */ + return LEintfloat(li, fltvalue(r)); /* l <= r ? */ + } + else { + lua_Number lf = fltvalue(l); /* 'l' must be float */ + if (ttisfloat(r)) + return luai_numle(lf, fltvalue(r)); /* both are float */ + else if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */ + return 0; /* NaN <= i is always false */ + else /* without NaN, (l <= r) <--> not(r < l) */ + return !LTintfloat(ivalue(r), lf); /* not (r < l) ? */ + } +} + + +/* +** Main operation less than; return 'l < r'. +*/ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { int res; - if (ttype(l) != ttype(r)) - return luaG_ordererror(L, l, r); - else if (ttisnumber(l)) - return luai_numlt(nvalue(l), nvalue(r)); - else if (ttisstring(l)) - return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; - else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) - return res; - return luaG_ordererror(L, l, r); + if (ttisnumber(l) && ttisnumber(r)) /* both operands are numbers? */ + return LTnum(l, r); + else if (ttisstring(l) && ttisstring(r)) /* both are strings? */ + return l_strcmp(tsvalue(l), tsvalue(r)) < 0; + else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0) /* no metamethod? */ + luaG_ordererror(L, l, r); /* error */ + return res; } -static int lessequal (lua_State *L, const TValue *l, const TValue *r) { +/* +** Main operation less than or equal to; return 'l <= r'. If it needs +** a metamethod and there is no '__le', try '__lt', based on +** l <= r iff !(r < l) (assuming a total order). If the metamethod +** yields during this substitution, the continuation has to know +** about it (to negate the result of r= 0) /* try 'le' */ return res; - else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ - return !res; - return luaG_ordererror(L, l, r); + else { /* try 'lt': */ + L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */ + res = luaT_callorderTM(L, r, l, TM_LT); + L->ci->callstatus ^= CIST_LEQ; /* clear mark */ + if (res < 0) + luaG_ordererror(L, l, r); + return !res; /* result is negated */ + } } -int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { +/* +** Main operation for equality of Lua values; return 't1 == t2'. +** L == NULL means raw equality (no metamethods) +*/ +int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { const TValue *tm; - lua_assert(ttype(t1) == ttype(t2)); + if (ttype(t1) != ttype(t2)) { /* not the same variant? */ + if (ttnov(t1) != ttnov(t2) || ttnov(t1) != LUA_TNUMBER) + return 0; /* only numbers can be equal with different variants */ + else { /* two numbers with different variants */ + lua_Integer i1, i2; /* compare them as integers */ + return (tointeger(t1, &i1) && tointeger(t2, &i2) && i1 == i2); + } + } + /* values have same type and same variant */ switch (ttype(t1)) { case LUA_TNIL: return 1; - case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); + case LUA_TNUMINT: return (ivalue(t1) == ivalue(t2)); + case LUA_TNUMFLT: return luai_numeq(fltvalue(t1), fltvalue(t2)); case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); + case LUA_TLCF: return fvalue(t1) == fvalue(t2); + case LUA_TSHRSTR: return eqshrstr(tsvalue(t1), tsvalue(t2)); + case LUA_TLNGSTR: return luaS_eqlngstr(tsvalue(t1), tsvalue(t2)); case LUA_TUSERDATA: { if (uvalue(t1) == uvalue(t2)) return 1; - tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, - TM_EQ); + else if (L == NULL) return 0; + tm = fasttm(L, uvalue(t1)->metatable, TM_EQ); + if (tm == NULL) + tm = fasttm(L, uvalue(t2)->metatable, TM_EQ); break; /* will try TM */ } case LUA_TTABLE: { if (hvalue(t1) == hvalue(t2)) return 1; - tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); + else if (L == NULL) return 0; + tm = fasttm(L, hvalue(t1)->metatable, TM_EQ); + if (tm == NULL) + tm = fasttm(L, hvalue(t2)->metatable, TM_EQ); break; /* will try TM */ } - default: return gcvalue(t1) == gcvalue(t2); + default: + return gcvalue(t1) == gcvalue(t2); } - if (tm == NULL) return 0; /* no TM? */ - callTMres(L, L->top, tm, t1, t2); /* call TM */ + if (tm == NULL) /* no TM? */ + return 0; /* objects are different */ + luaT_callTM(L, tm, t1, t2, L->top, 1); /* call TM */ return !l_isfalse(L->top); } -void luaV_concat (lua_State *L, int total, int last) { +/* macro used by 'luaV_concat' to ensure that element at 'o' is a string */ +#define tostring(L,o) \ + (ttisstring(o) || (cvt2str(o) && (luaO_tostring(L, o), 1))) + +#define isemptystr(o) (ttisshrstring(o) && tsvalue(o)->shrlen == 0) + +/* copy strings in stack from top - n up to top - 1 to buffer */ +static void copy2buff (StkId top, int n, char *buff) { + size_t tl = 0; /* size already copied */ + do { + size_t l = vslen(top - n); /* length of string being copied */ + memcpy(buff + tl, svalue(top - n), l * sizeof(char)); + tl += l; + } while (--n > 0); +} + + +/* +** Main operation for concatenation: concat 'total' values in the stack, +** from 'L->top - total' up to 'L->top - 1'. +*/ +void luaV_concat (lua_State *L, int total) { + lua_assert(total >= 2); do { - StkId top = L->base + last + 1; + StkId top = L->top; int n = 2; /* number of elements handled in this pass (at least 2) */ - if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { - if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) - luaG_concaterror(L, top-2, top-1); - } else if (tsvalue(top-1)->len == 0) /* second op is empty? */ - (void)tostring(L, top - 2); /* result is first op (as string) */ + if (!(ttisstring(top-2) || cvt2str(top-2)) || !tostring(L, top-1)) + luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT); + else if (isemptystr(top - 1)) /* second operand is empty? */ + cast_void(tostring(L, top - 2)); /* result is first operand */ + else if (isemptystr(top - 2)) { /* first operand is an empty string? */ + setobjs2s(L, top - 2, top - 1); /* result is second op. */ + } else { - /* at least two string values; get as many as possible */ - size_t tl = tsvalue(top-1)->len; - char *buffer; - int i; - /* collect total length */ - for (n = 1; n < total && tostring(L, top-n-1); n++) { - size_t l = tsvalue(top-n-1)->len; - if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); + /* at least two non-empty string values; get as many as possible */ + size_t tl = vslen(top - 1); + TString *ts; + /* collect total length and number of strings */ + for (n = 1; n < total && tostring(L, top - n - 1); n++) { + size_t l = vslen(top - n - 1); + if (l >= (MAX_SIZE/sizeof(char)) - tl) + luaG_runerror(L, "string length overflow"); tl += l; } - buffer = luaZ_openspace(L, &G(L)->buff, tl); - tl = 0; - for (i=n; i>0; i--) { /* concat all strings */ - size_t l = tsvalue(top-i)->len; - memcpy(buffer+tl, svalue(top-i), l); - tl += l; + if (tl <= LUAI_MAXSHORTLEN) { /* is result a short string? */ + char buff[LUAI_MAXSHORTLEN]; + copy2buff(top, n, buff); /* copy strings to buffer */ + ts = luaS_newlstr(L, buff, tl); + } + else { /* long string; copy strings directly to final result */ + ts = luaS_createlngstrobj(L, tl); + copy2buff(top, n, getstr(ts)); } - setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); + setsvalue2s(L, top - n, ts); /* create result */ } - total -= n-1; /* got `n' strings to create 1 new */ - last -= n-1; + total -= n-1; /* got 'n' strings to create 1 new */ + L->top -= n-1; /* popped 'n' strings and pushed one */ } while (total > 1); /* repeat until only 1 result left */ } -static void Arith (lua_State *L, StkId ra, const TValue *rb, - const TValue *rc, TMS op) { - TValue tempb, tempc; - const TValue *b, *c; - if ((b = luaV_tonumber(rb, &tempb)) != NULL && - (c = luaV_tonumber(rc, &tempc)) != NULL) { - lua_Number nb = nvalue(b), nc = nvalue(c); - switch (op) { - case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break; - case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break; - case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break; - case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break; - case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break; - case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; - case TM_UNM: setnvalue(ra, luai_numunm(nb)); break; - default: lua_assert(0); break; +/* +** Main operation 'ra' = #rb'. +*/ +void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { + const TValue *tm; + switch (ttype(rb)) { + case LUA_TTABLE: { + Table *h = hvalue(rb); + tm = fasttm(L, h->metatable, TM_LEN); + if (tm) break; /* metamethod? break switch to call it */ + setivalue(ra, luaH_getn(h)); /* else primitive len */ + return; + } + case LUA_TSHRSTR: { + setivalue(ra, tsvalue(rb)->shrlen); + return; + } + case LUA_TLNGSTR: { + setivalue(ra, tsvalue(rb)->u.lnglen); + return; + } + default: { /* try metamethod */ + tm = luaT_gettmbyobj(L, rb, TM_LEN); + if (ttisnil(tm)) /* no metamethod? */ + luaG_typeerror(L, rb, "get length of"); + break; + } + } + luaT_callTM(L, tm, rb, rb, ra, 1); +} + + +/* +** Integer division; return 'm // n', that is, floor(m/n). +** C division truncates its result (rounds towards zero). +** 'floor(q) == trunc(q)' when 'q >= 0' or when 'q' is integer, +** otherwise 'floor(q) == trunc(q) - 1'. +*/ +lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n) { + if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */ + if (n == 0) + luaG_runerror(L, "attempt to divide by zero"); + return intop(-, 0, m); /* n==-1; avoid overflow with 0x80000...//-1 */ + } + else { + lua_Integer q = m / n; /* perform C division */ + if ((m ^ n) < 0 && m % n != 0) /* 'm/n' would be negative non-integer? */ + q -= 1; /* correct result for different rounding */ + return q; + } +} + + +/* +** Integer modulus; return 'm % n'. (Assume that C '%' with +** negative operands follows C99 behavior. See previous comment +** about luaV_div.) +*/ +lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) { + if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */ + if (n == 0) + luaG_runerror(L, "attempt to perform 'n%%0'"); + return 0; /* m % -1 == 0; avoid overflow with 0x80000...%-1 */ + } + else { + lua_Integer r = m % n; + if (r != 0 && (m ^ n) < 0) /* 'm/n' would be non-integer negative? */ + r += n; /* correct result for different rounding */ + return r; + } +} + + +/* number of bits in an integer */ +#define NBITS cast_int(sizeof(lua_Integer) * CHAR_BIT) + +/* +** Shift left operation. (Shift right just negates 'y'.) +*/ +lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) { + if (y < 0) { /* shift right? */ + if (y <= -NBITS) return 0; + else return intop(>>, x, -y); + } + else { /* shift left */ + if (y >= NBITS) return 0; + else return intop(<<, x, y); + } +} + + +/* +** check whether cached closure in prototype 'p' may be reused, that is, +** whether there is a cached closure with the same upvalues needed by +** new closure to be created. +*/ +static LClosure *getcached (Proto *p, UpVal **encup, StkId base) { + LClosure *c = p->cache; + if (c != NULL) { /* is there a cached closure? */ + int nup = p->sizeupvalues; + Upvaldesc *uv = p->upvalues; + int i; + for (i = 0; i < nup; i++) { /* check whether it has right upvalues */ + TValue *v = uv[i].instack ? base + uv[i].idx : encup[uv[i].idx]->v; + if (c->upvals[i]->v != v) + return NULL; /* wrong upvalue; cannot reuse closure */ } } - else if (!call_binTM(L, rb, rc, ra, op)) - luaG_aritherror(L, rb, rc); + return c; /* return cached closure (or NULL if no cached closure) */ } +/* +** create a new Lua closure, push it in the stack, and initialize +** its upvalues. Note that the closure is not cached if prototype is +** already black (which means that 'cache' was already cleared by the +** GC). +*/ +static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, + StkId ra) { + int nup = p->sizeupvalues; + Upvaldesc *uv = p->upvalues; + int i; + LClosure *ncl = luaF_newLclosure(L, nup); + ncl->p = p; + setclLvalue(L, ra, ncl); /* anchor new closure in stack */ + for (i = 0; i < nup; i++) { /* fill in its upvalues */ + if (uv[i].instack) /* upvalue refers to local variable? */ + ncl->upvals[i] = luaF_findupval(L, base + uv[i].idx); + else /* get upvalue from enclosing function */ + ncl->upvals[i] = encup[uv[i].idx]; + ncl->upvals[i]->refcount++; + /* new closure is white, so we do not need a barrier here */ + } + if (!isblack(p)) /* cache will not break GC invariant? */ + p->cache = ncl; /* save it on cache for reuse */ +} + /* -** some macros for common tasks in `luaV_execute' +** finish execution of an opcode interrupted by an yield +*/ +void luaV_finishOp (lua_State *L) { + CallInfo *ci = L->ci; + StkId base = ci->u.l.base; + Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ + OpCode op = GET_OPCODE(inst); + switch (op) { /* finish its execution */ + case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_IDIV: + case OP_BAND: case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: + case OP_MOD: case OP_POW: + case OP_UNM: case OP_BNOT: case OP_LEN: + case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: { + setobjs2s(L, base + GETARG_A(inst), --L->top); + break; + } + case OP_LE: case OP_LT: case OP_EQ: { + int res = !l_isfalse(L->top - 1); + L->top--; + if (ci->callstatus & CIST_LEQ) { /* "<=" using "<" instead? */ + lua_assert(op == OP_LE); + ci->callstatus ^= CIST_LEQ; /* clear mark */ + res = !res; /* negate result */ + } + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); + if (res != GETARG_A(inst)) /* condition failed? */ + ci->u.l.savedpc++; /* skip jump instruction */ + break; + } + case OP_CONCAT: { + StkId top = L->top - 1; /* top when 'luaT_trybinTM' was called */ + int b = GETARG_B(inst); /* first element to concatenate */ + int total = cast_int(top - 1 - (base + b)); /* yet to concatenate */ + setobj2s(L, top - 2, top); /* put TM result in proper position */ + if (total > 1) { /* are there elements to concat? */ + L->top = top - 1; /* top is one after last element (at top-2) */ + luaV_concat(L, total); /* concat them (may yield again) */ + } + /* move final result to final position */ + setobj2s(L, ci->u.l.base + GETARG_A(inst), L->top - 1); + L->top = ci->top; /* restore top */ + break; + } + case OP_TFORCALL: { + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP); + L->top = ci->top; /* correct top */ + break; + } + case OP_CALL: { + if (GETARG_C(inst) - 1 >= 0) /* nresults >= 0? */ + L->top = ci->top; /* adjust results */ + break; + } + case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE: + break; + default: lua_assert(0); + } +} + + + + +/* +** {================================================================== +** Function 'luaV_execute': main interpreter loop +** =================================================================== +*/ + + +/* +** some macros for common tasks in 'luaV_execute' */ -#define runtime_check(L, c) { if (!(c)) break; } #define RA(i) (base+GETARG_A(i)) -/* to be used after possible stack reallocation */ #define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) #define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) #define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) #define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) -#define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i)) -#define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);} +/* execute a jump instruction */ +#define dojump(ci,i,e) \ + { int a = GETARG_A(i); \ + if (a != 0) luaF_close(L, ci->u.l.base + a - 1); \ + ci->u.l.savedpc += GETARG_sBx(i) + e; } +/* for test instructions, execute the jump instruction that follows it */ +#define donextjump(ci) { i = *ci->u.l.savedpc; dojump(ci, i, 1); } -#define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } +#define Protect(x) { {x;}; base = ci->u.l.base; } -#define arith_op(op,tm) { \ - TValue *rb = RKB(i); \ - TValue *rc = RKC(i); \ - if (ttisnumber(rb) && ttisnumber(rc)) { \ - lua_Number nb = nvalue(rb), nc = nvalue(rc); \ - setnvalue(ra, op(nb, nc)); \ - } \ - else \ - Protect(Arith(L, ra, rb, rc, tm)); \ - } +#define checkGC(L,c) \ + { luaC_condGC(L, L->top = (c), /* limit of live values */ \ + Protect(L->top = ci->top)); /* restore top */ \ + luai_threadyield(L); } + + +/* fetch an instruction and prepare its execution */ +#define vmfetch() { \ + i = *(ci->u.l.savedpc++); \ + if (L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) \ + Protect(luaG_traceexec(L)); \ + ra = RA(i); /* WARNING: any stack reallocation invalidates 'ra' */ \ + lua_assert(base == ci->u.l.base); \ + lua_assert(base <= L->top && L->top < L->stack + L->stacksize); \ +} +#define vmdispatch(o) switch(o) +#define vmcase(l) case l: +#define vmbreak break + + +/* +** copy of 'luaV_gettable', but protecting the call to potential +** metamethod (which can reallocate the stack) +*/ +#define gettableProtected(L,t,k,v) { const TValue *slot; \ + if (luaV_fastget(L,t,k,slot,luaH_get)) { setobj2s(L, v, slot); } \ + else Protect(luaV_finishget(L,t,k,v,slot)); } -void luaV_execute (lua_State *L, int nexeccalls) { +/* same for 'luaV_settable' */ +#define settableProtected(L,t,k,v) { const TValue *slot; \ + if (!luaV_fastset(L,t,k,slot,luaH_get,v)) \ + Protect(luaV_finishset(L,t,k,v,slot)); } + + + +void luaV_execute (lua_State *L) { + CallInfo *ci = L->ci; LClosure *cl; - StkId base; TValue *k; - const Instruction *pc; - reentry: /* entry point */ - lua_assert(isLua(L->ci)); - pc = L->savedpc; - cl = &clvalue(L->ci->func)->l; - base = L->base; - k = cl->p->k; + StkId base; + ci->callstatus |= CIST_FRESH; /* fresh invocation of 'luaV_execute" */ + newframe: /* reentry point when frame changes (call/return) */ + lua_assert(ci == L->ci); + cl = clLvalue(ci->func); /* local reference to function's closure */ + k = cl->p->k; /* local reference to function's constant table */ + base = ci->u.l.base; /* local copy of function's base */ /* main loop of interpreter */ for (;;) { - const Instruction i = *pc++; + Instruction i; StkId ra; - if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && - (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { - traceexec(L, pc); - if (L->status == LUA_YIELD) { /* did hook yield? */ - L->savedpc = pc - 1; - return; - } - base = L->base; - } - /* warning!! several calls may realloc the stack and invalidate `ra' */ - ra = RA(i); - lua_assert(base == L->base && L->base == L->ci->base); - lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); - lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); - switch (GET_OPCODE(i)) { - case OP_MOVE: { + vmfetch(); + vmdispatch (GET_OPCODE(i)) { + vmcase(OP_MOVE) { setobjs2s(L, ra, RB(i)); - continue; + vmbreak; + } + vmcase(OP_LOADK) { + TValue *rb = k + GETARG_Bx(i); + setobj2s(L, ra, rb); + vmbreak; } - case OP_LOADK: { - setobj2s(L, ra, KBx(i)); - continue; + vmcase(OP_LOADKX) { + TValue *rb; + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); + rb = k + GETARG_Ax(*ci->u.l.savedpc++); + setobj2s(L, ra, rb); + vmbreak; } - case OP_LOADBOOL: { + vmcase(OP_LOADBOOL) { setbvalue(ra, GETARG_B(i)); - if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ - continue; + if (GETARG_C(i)) ci->u.l.savedpc++; /* skip next instruction (if C) */ + vmbreak; } - case OP_LOADNIL: { - TValue *rb = RB(i); + vmcase(OP_LOADNIL) { + int b = GETARG_B(i); do { - setnilvalue(rb--); - } while (rb >= ra); - continue; + setnilvalue(ra++); + } while (b--); + vmbreak; } - case OP_GETUPVAL: { + vmcase(OP_GETUPVAL) { int b = GETARG_B(i); setobj2s(L, ra, cl->upvals[b]->v); - continue; - } - case OP_GETGLOBAL: { - TValue g; - TValue *rb = KBx(i); - sethvalue(L, &g, cl->env); - lua_assert(ttisstring(rb)); - Protect(luaV_gettable(L, &g, rb, ra)); - continue; - } - case OP_GETTABLE: { - Protect(luaV_gettable(L, RB(i), RKC(i), ra)); - continue; - } - case OP_SETGLOBAL: { - TValue g; - sethvalue(L, &g, cl->env); - lua_assert(ttisstring(KBx(i))); - Protect(luaV_settable(L, &g, KBx(i), ra)); - continue; - } - case OP_SETUPVAL: { + vmbreak; + } + vmcase(OP_GETTABUP) { + TValue *upval = cl->upvals[GETARG_B(i)]->v; + TValue *rc = RKC(i); + gettableProtected(L, upval, rc, ra); + vmbreak; + } + vmcase(OP_GETTABLE) { + StkId rb = RB(i); + TValue *rc = RKC(i); + gettableProtected(L, rb, rc, ra); + vmbreak; + } + vmcase(OP_SETTABUP) { + TValue *upval = cl->upvals[GETARG_A(i)]->v; + TValue *rb = RKB(i); + TValue *rc = RKC(i); + settableProtected(L, upval, rb, rc); + vmbreak; + } + vmcase(OP_SETUPVAL) { UpVal *uv = cl->upvals[GETARG_B(i)]; setobj(L, uv->v, ra); - luaC_barrier(L, uv, ra); - continue; + luaC_upvalbarrier(L, uv); + vmbreak; } - case OP_SETTABLE: { - Protect(luaV_settable(L, ra, RKB(i), RKC(i))); - continue; + vmcase(OP_SETTABLE) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + settableProtected(L, ra, rb, rc); + vmbreak; } - case OP_NEWTABLE: { + vmcase(OP_NEWTABLE) { int b = GETARG_B(i); int c = GETARG_C(i); - sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); - Protect(luaC_checkGC(L)); - continue; + Table *t = luaH_new(L); + sethvalue(L, ra, t); + if (b != 0 || c != 0) + luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c)); + checkGC(L, ra + 1); + vmbreak; } - case OP_SELF: { + vmcase(OP_SELF) { + const TValue *aux; StkId rb = RB(i); - setobjs2s(L, ra+1, rb); - Protect(luaV_gettable(L, rb, RKC(i), ra)); - continue; + TValue *rc = RKC(i); + TString *key = tsvalue(rc); /* key must be a string */ + setobjs2s(L, ra + 1, rb); + if (luaV_fastget(L, rb, key, aux, luaH_getstr)) { + setobj2s(L, ra, aux); + } + else Protect(luaV_finishget(L, rb, rc, ra, aux)); + vmbreak; + } + vmcase(OP_ADD) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Number nb; lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) { + lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); + setivalue(ra, intop(+, ib, ic)); + } + else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { + setfltvalue(ra, luai_numadd(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_ADD)); } + vmbreak; + } + vmcase(OP_SUB) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Number nb; lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) { + lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); + setivalue(ra, intop(-, ib, ic)); + } + else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { + setfltvalue(ra, luai_numsub(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SUB)); } + vmbreak; + } + vmcase(OP_MUL) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Number nb; lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) { + lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); + setivalue(ra, intop(*, ib, ic)); + } + else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { + setfltvalue(ra, luai_nummul(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MUL)); } + vmbreak; } - case OP_ADD: { - arith_op(luai_numadd, TM_ADD); - continue; + vmcase(OP_DIV) { /* float division (always with floats) */ + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Number nb; lua_Number nc; + if (tonumber(rb, &nb) && tonumber(rc, &nc)) { + setfltvalue(ra, luai_numdiv(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_DIV)); } + vmbreak; } - case OP_SUB: { - arith_op(luai_numsub, TM_SUB); - continue; + vmcase(OP_BAND) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Integer ib; lua_Integer ic; + if (tointeger(rb, &ib) && tointeger(rc, &ic)) { + setivalue(ra, intop(&, ib, ic)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BAND)); } + vmbreak; } - case OP_MUL: { - arith_op(luai_nummul, TM_MUL); - continue; + vmcase(OP_BOR) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Integer ib; lua_Integer ic; + if (tointeger(rb, &ib) && tointeger(rc, &ic)) { + setivalue(ra, intop(|, ib, ic)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BOR)); } + vmbreak; } - case OP_DIV: { - arith_op(luai_numdiv, TM_DIV); - continue; + vmcase(OP_BXOR) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Integer ib; lua_Integer ic; + if (tointeger(rb, &ib) && tointeger(rc, &ic)) { + setivalue(ra, intop(^, ib, ic)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BXOR)); } + vmbreak; } - case OP_MOD: { - arith_op(luai_nummod, TM_MOD); - continue; + vmcase(OP_SHL) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Integer ib; lua_Integer ic; + if (tointeger(rb, &ib) && tointeger(rc, &ic)) { + setivalue(ra, luaV_shiftl(ib, ic)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHL)); } + vmbreak; } - case OP_POW: { - arith_op(luai_numpow, TM_POW); - continue; + vmcase(OP_SHR) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Integer ib; lua_Integer ic; + if (tointeger(rb, &ib) && tointeger(rc, &ic)) { + setivalue(ra, luaV_shiftl(ib, -ic)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHR)); } + vmbreak; + } + vmcase(OP_MOD) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Number nb; lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) { + lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); + setivalue(ra, luaV_mod(L, ib, ic)); + } + else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { + lua_Number m; + luai_nummod(L, nb, nc, m); + setfltvalue(ra, m); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MOD)); } + vmbreak; + } + vmcase(OP_IDIV) { /* floor division */ + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Number nb; lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) { + lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); + setivalue(ra, luaV_div(L, ib, ic)); + } + else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { + setfltvalue(ra, luai_numidiv(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_IDIV)); } + vmbreak; } - case OP_UNM: { + vmcase(OP_POW) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Number nb; lua_Number nc; + if (tonumber(rb, &nb) && tonumber(rc, &nc)) { + setfltvalue(ra, luai_numpow(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_POW)); } + vmbreak; + } + vmcase(OP_UNM) { TValue *rb = RB(i); - if (ttisnumber(rb)) { - lua_Number nb = nvalue(rb); - setnvalue(ra, luai_numunm(nb)); + lua_Number nb; + if (ttisinteger(rb)) { + lua_Integer ib = ivalue(rb); + setivalue(ra, intop(-, 0, ib)); + } + else if (tonumber(rb, &nb)) { + setfltvalue(ra, luai_numunm(L, nb)); } else { - Protect(Arith(L, ra, rb, rb, TM_UNM)); + Protect(luaT_trybinTM(L, rb, rb, ra, TM_UNM)); } - continue; + vmbreak; } - case OP_NOT: { - int res = l_isfalse(RB(i)); /* next assignment may change this value */ - setbvalue(ra, res); - continue; - } - case OP_LEN: { - const TValue *rb = RB(i); - switch (ttype(rb)) { - case LUA_TTABLE: { - setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); - break; - } - case LUA_TSTRING: { - setnvalue(ra, cast_num(tsvalue(rb)->len)); - break; - } - default: { /* try metamethod */ - Protect( - if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) - luaG_typeerror(L, rb, "get length of"); - ) - } + vmcase(OP_BNOT) { + TValue *rb = RB(i); + lua_Integer ib; + if (tointeger(rb, &ib)) { + setivalue(ra, intop(^, ~l_castS2U(0), ib)); } - continue; + else { + Protect(luaT_trybinTM(L, rb, rb, ra, TM_BNOT)); + } + vmbreak; + } + vmcase(OP_NOT) { + TValue *rb = RB(i); + int res = l_isfalse(rb); /* next assignment may change this value */ + setbvalue(ra, res); + vmbreak; } - case OP_CONCAT: { + vmcase(OP_LEN) { + Protect(luaV_objlen(L, ra, RB(i))); + vmbreak; + } + vmcase(OP_CONCAT) { int b = GETARG_B(i); int c = GETARG_C(i); - Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); - setobjs2s(L, RA(i), base+b); - continue; + StkId rb; + L->top = base + c + 1; /* mark the end of concat operands */ + Protect(luaV_concat(L, c - b + 1)); + ra = RA(i); /* 'luaV_concat' may invoke TMs and move the stack */ + rb = base + b; + setobjs2s(L, ra, rb); + checkGC(L, (ra >= rb ? ra + 1 : rb)); + L->top = ci->top; /* restore top */ + vmbreak; } - case OP_JMP: { - dojump(L, pc, GETARG_sBx(i)); - continue; + vmcase(OP_JMP) { + dojump(ci, i, 0); + vmbreak; } - case OP_EQ: { + vmcase(OP_EQ) { TValue *rb = RKB(i); TValue *rc = RKC(i); Protect( - if (equalobj(L, rb, rc) == GETARG_A(i)) - dojump(L, pc, GETARG_sBx(*pc)); + if (luaV_equalobj(L, rb, rc) != GETARG_A(i)) + ci->u.l.savedpc++; + else + donextjump(ci); ) - pc++; - continue; + vmbreak; } - case OP_LT: { + vmcase(OP_LT) { Protect( - if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) - dojump(L, pc, GETARG_sBx(*pc)); + if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) + ci->u.l.savedpc++; + else + donextjump(ci); ) - pc++; - continue; + vmbreak; } - case OP_LE: { + vmcase(OP_LE) { Protect( - if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) - dojump(L, pc, GETARG_sBx(*pc)); + if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) + ci->u.l.savedpc++; + else + donextjump(ci); ) - pc++; - continue; + vmbreak; } - case OP_TEST: { - if (l_isfalse(ra) != GETARG_C(i)) - dojump(L, pc, GETARG_sBx(*pc)); - pc++; - continue; + vmcase(OP_TEST) { + if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra)) + ci->u.l.savedpc++; + else + donextjump(ci); + vmbreak; } - case OP_TESTSET: { + vmcase(OP_TESTSET) { TValue *rb = RB(i); - if (l_isfalse(rb) != GETARG_C(i)) { + if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb)) + ci->u.l.savedpc++; + else { setobjs2s(L, ra, rb); - dojump(L, pc, GETARG_sBx(*pc)); + donextjump(ci); } - pc++; - continue; + vmbreak; } - case OP_CALL: { + vmcase(OP_CALL) { int b = GETARG_B(i); int nresults = GETARG_C(i) - 1; if (b != 0) L->top = ra+b; /* else previous instruction set top */ - L->savedpc = pc; - switch (luaD_precall(L, ra, nresults)) { - case PCRLUA: { - nexeccalls++; - goto reentry; /* restart luaV_execute over new Lua function */ - } - case PCRC: { - /* it was a C function (`precall' called it); adjust results */ - if (nresults >= 0) L->top = L->ci->top; - base = L->base; - continue; - } - default: { - return; /* yield */ - } + if (luaD_precall(L, ra, nresults)) { /* C function? */ + if (nresults >= 0) + L->top = ci->top; /* adjust results */ + Protect((void)0); /* update 'base' */ } + else { /* Lua function */ + ci = L->ci; + goto newframe; /* restart luaV_execute over new Lua function */ + } + vmbreak; } - case OP_TAILCALL: { + vmcase(OP_TAILCALL) { int b = GETARG_B(i); if (b != 0) L->top = ra+b; /* else previous instruction set top */ - L->savedpc = pc; lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); - switch (luaD_precall(L, ra, LUA_MULTRET)) { - case PCRLUA: { - /* tail call: put new frame in place of previous one */ - CallInfo *ci = L->ci - 1; /* previous frame */ - int aux; - StkId func = ci->func; - StkId pfunc = (ci+1)->func; /* previous function index */ - if (L->openupval) luaF_close(L, ci->base); - L->base = ci->base = ci->func + ((ci+1)->base - pfunc); - for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ - setobjs2s(L, func+aux, pfunc+aux); - ci->top = L->top = func+aux; /* correct top */ - lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize); - ci->savedpc = L->savedpc; - ci->tailcalls++; /* one more call lost */ - L->ci--; /* remove new frame */ - goto reentry; - } - case PCRC: { /* it was a C function (`precall' called it) */ - base = L->base; - continue; + if (luaD_precall(L, ra, LUA_MULTRET)) { /* C function? */ + Protect((void)0); /* update 'base' */ + } + else { + /* tail call: put called frame (n) in place of caller one (o) */ + CallInfo *nci = L->ci; /* called frame */ + CallInfo *oci = nci->previous; /* caller frame */ + StkId nfunc = nci->func; /* called function */ + StkId ofunc = oci->func; /* caller function */ + /* last stack slot filled by 'precall' */ + StkId lim = nci->u.l.base + getproto(nfunc)->numparams; + int aux; + /* close all upvalues from previous call */ + if (cl->p->sizep > 0) luaF_close(L, oci->u.l.base); + /* move new frame into old one */ + for (aux = 0; nfunc + aux < lim; aux++) + setobjs2s(L, ofunc + aux, nfunc + aux); + oci->u.l.base = ofunc + (nci->u.l.base - nfunc); /* correct base */ + oci->top = L->top = ofunc + (L->top - nfunc); /* correct top */ + oci->u.l.savedpc = nci->u.l.savedpc; + oci->callstatus |= CIST_TAIL; /* function was tail called */ + ci = L->ci = oci; /* remove new frame */ + lua_assert(L->top == oci->u.l.base + getproto(ofunc)->maxstacksize); + goto newframe; /* restart luaV_execute over new Lua function */ + } + vmbreak; + } + vmcase(OP_RETURN) { + int b = GETARG_B(i); + if (cl->p->sizep > 0) luaF_close(L, base); + b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra))); + if (ci->callstatus & CIST_FRESH) /* local 'ci' still from callee */ + return; /* external invocation: return */ + else { /* invocation via reentry: continue execution */ + ci = L->ci; + if (b) L->top = ci->top; + lua_assert(isLua(ci)); + lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL); + goto newframe; /* restart luaV_execute over new Lua function */ + } + } + vmcase(OP_FORLOOP) { + if (ttisinteger(ra)) { /* integer loop? */ + lua_Integer step = ivalue(ra + 2); + lua_Integer idx = intop(+, ivalue(ra), step); /* increment index */ + lua_Integer limit = ivalue(ra + 1); + if ((0 < step) ? (idx <= limit) : (limit <= idx)) { + ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ + chgivalue(ra, idx); /* update internal index... */ + setivalue(ra + 3, idx); /* ...and external index */ } - default: { - return; /* yield */ + } + else { /* floating loop */ + lua_Number step = fltvalue(ra + 2); + lua_Number idx = luai_numadd(L, fltvalue(ra), step); /* inc. index */ + lua_Number limit = fltvalue(ra + 1); + if (luai_numlt(0, step) ? luai_numle(idx, limit) + : luai_numle(limit, idx)) { + ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ + chgfltvalue(ra, idx); /* update internal index... */ + setfltvalue(ra + 3, idx); /* ...and external index */ } } + vmbreak; } - case OP_RETURN: { - int b = GETARG_B(i); - if (b != 0) L->top = ra+b-1; - if (L->openupval) luaF_close(L, base); - L->savedpc = pc; - b = luaD_poscall(L, ra); - if (--nexeccalls == 0) /* was previous function running `here'? */ - return; /* no: return */ - else { /* yes: continue its execution */ - if (b) L->top = L->ci->top; - lua_assert(isLua(L->ci)); - lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL); - goto reentry; - } - } - case OP_FORLOOP: { - lua_Number step = nvalue(ra+2); - lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ - lua_Number limit = nvalue(ra+1); - if (luai_numlt(0, step) ? luai_numle(idx, limit) - : luai_numle(limit, idx)) { - dojump(L, pc, GETARG_sBx(i)); /* jump back */ - setnvalue(ra, idx); /* update internal index... */ - setnvalue(ra+3, idx); /* ...and external index */ - } - continue; - } - case OP_FORPREP: { - const TValue *init = ra; - const TValue *plimit = ra+1; - const TValue *pstep = ra+2; - L->savedpc = pc; /* next steps may throw errors */ - if (!tonumber(init, ra)) - luaG_runerror(L, LUA_QL("for") " initial value must be a number"); - else if (!tonumber(plimit, ra+1)) - luaG_runerror(L, LUA_QL("for") " limit must be a number"); - else if (!tonumber(pstep, ra+2)) - luaG_runerror(L, LUA_QL("for") " step must be a number"); - setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); - dojump(L, pc, GETARG_sBx(i)); - continue; - } - case OP_TFORLOOP: { + vmcase(OP_FORPREP) { + TValue *init = ra; + TValue *plimit = ra + 1; + TValue *pstep = ra + 2; + lua_Integer ilimit; + int stopnow; + if (ttisinteger(init) && ttisinteger(pstep) && + forlimit(plimit, &ilimit, ivalue(pstep), &stopnow)) { + /* all values are integer */ + lua_Integer initv = (stopnow ? 0 : ivalue(init)); + setivalue(plimit, ilimit); + setivalue(init, intop(-, initv, ivalue(pstep))); + } + else { /* try making all values floats */ + lua_Number ninit; lua_Number nlimit; lua_Number nstep; + if (!tonumber(plimit, &nlimit)) + luaG_runerror(L, "'for' limit must be a number"); + setfltvalue(plimit, nlimit); + if (!tonumber(pstep, &nstep)) + luaG_runerror(L, "'for' step must be a number"); + setfltvalue(pstep, nstep); + if (!tonumber(init, &ninit)) + luaG_runerror(L, "'for' initial value must be a number"); + setfltvalue(init, luai_numsub(L, ninit, nstep)); + } + ci->u.l.savedpc += GETARG_sBx(i); + vmbreak; + } + vmcase(OP_TFORCALL) { StkId cb = ra + 3; /* call base */ setobjs2s(L, cb+2, ra+2); setobjs2s(L, cb+1, ra+1); setobjs2s(L, cb, ra); - L->top = cb+3; /* func. + 2 args (state and index) */ + L->top = cb + 3; /* func. + 2 args (state and index) */ Protect(luaD_call(L, cb, GETARG_C(i))); - L->top = L->ci->top; - cb = RA(i) + 3; /* previous call may change the stack */ - if (!ttisnil(cb)) { /* continue loop? */ - setobjs2s(L, cb-1, cb); /* save control variable */ - dojump(L, pc, GETARG_sBx(*pc)); /* jump back */ + L->top = ci->top; + i = *(ci->u.l.savedpc++); /* go to next instruction */ + ra = RA(i); + lua_assert(GET_OPCODE(i) == OP_TFORLOOP); + goto l_tforloop; + } + vmcase(OP_TFORLOOP) { + l_tforloop: + if (!ttisnil(ra + 1)) { /* continue loop? */ + setobjs2s(L, ra, ra + 1); /* save control variable */ + ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ } - pc++; - continue; + vmbreak; } - case OP_SETLIST: { + vmcase(OP_SETLIST) { int n = GETARG_B(i); int c = GETARG_C(i); - int last; + unsigned int last; Table *h; - if (n == 0) { - n = cast_int(L->top - ra) - 1; - L->top = L->ci->top; + if (n == 0) n = cast_int(L->top - ra) - 1; + if (c == 0) { + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); + c = GETARG_Ax(*ci->u.l.savedpc++); } - if (c == 0) c = cast_int(*pc++); - runtime_check(L, ttistable(ra)); h = hvalue(ra); last = ((c-1)*LFIELDS_PER_FLUSH) + n; if (last > h->sizearray) /* needs more space? */ - luaH_resizearray(L, h, last); /* pre-alloc it at once */ + luaH_resizearray(L, h, last); /* preallocate it at once */ for (; n > 0; n--) { TValue *val = ra+n; - setobj2t(L, luaH_setnum(L, h, last--), val); - luaC_barriert(L, h, val); - } - continue; - } - case OP_CLOSE: { - luaF_close(L, ra); - continue; - } - case OP_CLOSURE: { - Proto *p; - Closure *ncl; - int nup, j; - p = cl->p->p[GETARG_Bx(i)]; - nup = p->nups; - ncl = luaF_newLclosure(L, nup, cl->env); - ncl->l.p = p; - for (j=0; jl.upvals[j] = cl->upvals[GETARG_B(*pc)]; - else { - lua_assert(GET_OPCODE(*pc) == OP_MOVE); - ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); - } + luaH_setint(L, h, last--, val); + luaC_barrierback(L, h, val); } - setclvalue(L, ra, ncl); - Protect(luaC_checkGC(L)); - continue; + L->top = ci->top; /* correct top (in case of previous open call) */ + vmbreak; } - case OP_VARARG: { - int b = GETARG_B(i) - 1; + vmcase(OP_CLOSURE) { + Proto *p = cl->p->p[GETARG_Bx(i)]; + LClosure *ncl = getcached(p, cl->upvals, base); /* cached closure */ + if (ncl == NULL) /* no match? */ + pushclosure(L, p, cl->upvals, base, ra); /* create a new one */ + else + setclLvalue(L, ra, ncl); /* push cashed closure */ + checkGC(L, ra + 1); + vmbreak; + } + vmcase(OP_VARARG) { + int b = GETARG_B(i) - 1; /* required results */ int j; - CallInfo *ci = L->ci; - int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1; - if (b == LUA_MULTRET) { + int n = cast_int(base - ci->func) - cl->p->numparams - 1; + if (n < 0) /* less arguments than parameters? */ + n = 0; /* no vararg arguments */ + if (b < 0) { /* B == 0? */ + b = n; /* get all var. arguments */ Protect(luaD_checkstack(L, n)); ra = RA(i); /* previous call may change the stack */ - b = n; L->top = ra + n; } - for (j = 0; j < b; j++) { - if (j < n) { - setobjs2s(L, ra + j, ci->base - n + j); - } - else { - setnilvalue(ra + j); - } - } - continue; + for (j = 0; j < b && j < n; j++) + setobjs2s(L, ra + j, base - n + j); + for (; j < b; j++) /* complete required results with nil */ + setnilvalue(ra + j); + vmbreak; + } + vmcase(OP_EXTRAARG) { + lua_assert(0); + vmbreak; } } } } +/* }================================================================== */ + diff --git a/app/src/main/jni/lua/lvm.h b/app/src/main/jni/lua/lvm.h index bfe4f56..bcf52d2 100644 --- a/app/src/main/jni/lua/lvm.h +++ b/app/src/main/jni/lua/lvm.h @@ -1,5 +1,5 @@ /* -** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lvm.h,v 2.40 2016/01/05 16:07:21 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -13,24 +13,101 @@ #include "ltm.h" -#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) +#if !defined(LUA_NOCVTN2S) +#define cvt2str(o) ttisnumber(o) +#else +#define cvt2str(o) 0 /* no conversion from numbers to strings */ +#endif + + +#if !defined(LUA_NOCVTS2N) +#define cvt2num(o) ttisstring(o) +#else +#define cvt2num(o) 0 /* no conversion from strings to numbers */ +#endif + + +/* +** You can define LUA_FLOORN2I if you want to convert floats to integers +** by flooring them (instead of raising an error if they are not +** integral values) +*/ +#if !defined(LUA_FLOORN2I) +#define LUA_FLOORN2I 0 +#endif + + +#define tonumber(o,n) \ + (ttisfloat(o) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n)) + +#define tointeger(o,i) \ + (ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger(o,i,LUA_FLOORN2I)) + +#define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2)) + +#define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2) + + +/* +** fast track for 'gettable': if 't' is a table and 't[k]' is not nil, +** return 1 with 'slot' pointing to 't[k]' (final result). Otherwise, +** return 0 (meaning it will have to check metamethod) with 'slot' +** pointing to a nil 't[k]' (if 't' is a table) or NULL (otherwise). +** 'f' is the raw get function to use. +*/ +#define luaV_fastget(L,t,k,slot,f) \ + (!ttistable(t) \ + ? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \ + : (slot = f(hvalue(t), k), /* else, do raw access */ \ + !ttisnil(slot))) /* result not nil? */ + +/* +** standard implementation for 'gettable' +*/ +#define luaV_gettable(L,t,k,v) { const TValue *slot; \ + if (luaV_fastget(L,t,k,slot,luaH_get)) { setobj2s(L, v, slot); } \ + else luaV_finishget(L,t,k,v,slot); } + + +/* +** Fast track for set table. If 't' is a table and 't[k]' is not nil, +** call GC barrier, do a raw 't[k]=v', and return true; otherwise, +** return false with 'slot' equal to NULL (if 't' is not a table) or +** 'nil'. (This is needed by 'luaV_finishget'.) Note that, if the macro +** returns true, there is no need to 'invalidateTMcache', because the +** call is not creating a new entry. +*/ +#define luaV_fastset(L,t,k,slot,f,v) \ + (!ttistable(t) \ + ? (slot = NULL, 0) \ + : (slot = f(hvalue(t), k), \ + ttisnil(slot) ? 0 \ + : (luaC_barrierback(L, hvalue(t), v), \ + setobj2t(L, cast(TValue *,slot), v), \ + 1))) -#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ - (((o) = luaV_tonumber(o,n)) != NULL)) -#define equalobj(L,o1,o2) \ - (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) +#define luaV_settable(L,t,k,v) { const TValue *slot; \ + if (!luaV_fastset(L,t,k,slot,luaH_get,v)) \ + luaV_finishset(L,t,k,v,slot); } + +LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); -LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2); -LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n); -LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); -LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, - StkId val); -LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, - StkId val); -LUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls); -LUAI_FUNC void luaV_concat (lua_State *L, int total, int last); +LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); +LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n); +LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode); +LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key, + StkId val, const TValue *slot); +LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key, + StkId val, const TValue *slot); +LUAI_FUNC void luaV_finishOp (lua_State *L); +LUAI_FUNC void luaV_execute (lua_State *L); +LUAI_FUNC void luaV_concat (lua_State *L, int total); +LUAI_FUNC lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y); +LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y); +LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y); +LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); #endif diff --git a/app/src/main/jni/lua/lzio.c b/app/src/main/jni/lua/lzio.c index 293edd5..c9e1f49 100644 --- a/app/src/main/jni/lua/lzio.c +++ b/app/src/main/jni/lua/lzio.c @@ -1,15 +1,17 @@ /* -** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ -** a generic input stream interface +** $Id: lzio.c,v 1.37 2015/09/08 15:41:05 roberto Exp $ +** Buffered streams ** See Copyright Notice in lua.h */ - -#include - #define lzio_c #define LUA_CORE +#include "lprefix.h" + + +#include + #include "lua.h" #include "llimits.h" @@ -25,23 +27,11 @@ int luaZ_fill (ZIO *z) { lua_unlock(L); buff = z->reader(L, z->data, &size); lua_lock(L); - if (buff == NULL || size == 0) return EOZ; - z->n = size - 1; + if (buff == NULL || size == 0) + return EOZ; + z->n = size - 1; /* discount char being returned */ z->p = buff; - return char2int(*(z->p++)); -} - - -int luaZ_lookahead (ZIO *z) { - if (z->n == 0) { - if (luaZ_fill(z) == EOZ) - return EOZ; - else { - z->n++; /* luaZ_fill removed first byte; put back it */ - z->p--; - } - } - return char2int(*z->p); + return cast_uchar(*(z->p++)); } @@ -58,8 +48,14 @@ void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { size_t luaZ_read (ZIO *z, void *b, size_t n) { while (n) { size_t m; - if (luaZ_lookahead(z) == EOZ) - return n; /* return number of missing bytes */ + if (z->n == 0) { /* no bytes in buffer? */ + if (luaZ_fill(z) == EOZ) /* try to read more */ + return n; /* no more input; return number of missing bytes */ + else { + z->n++; /* luaZ_fill consumed first byte; put it back */ + z->p--; + } + } m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ memcpy(b, z->p, m); z->n -= m; @@ -70,13 +66,3 @@ size_t luaZ_read (ZIO *z, void *b, size_t n) { return 0; } -/* ------------------------------------------------------------------------ */ -char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) { - if (n > buff->buffsize) { - if (n < LUA_MINBUFFER) n = LUA_MINBUFFER; - luaZ_resizebuffer(L, buff, n); - } - return buff->buffer; -} - - diff --git a/app/src/main/jni/lua/lzio.h b/app/src/main/jni/lua/lzio.h index 51d695d..e7b6f34 100644 --- a/app/src/main/jni/lua/lzio.h +++ b/app/src/main/jni/lua/lzio.h @@ -1,5 +1,5 @@ /* -** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lzio.h,v 1.31 2015/09/08 15:41:05 roberto Exp $ ** Buffered streams ** See Copyright Notice in lua.h */ @@ -17,9 +17,8 @@ typedef struct Zio ZIO; -#define char2int(c) cast(int, cast(unsigned char, (c))) +#define zgetc(z) (((z)->n--)>0 ? cast_uchar(*(z)->p++) : luaZ_fill(z)) -#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z)) typedef struct Mbuffer { char *buffer; @@ -33,21 +32,21 @@ typedef struct Mbuffer { #define luaZ_sizebuffer(buff) ((buff)->buffsize) #define luaZ_bufflen(buff) ((buff)->n) +#define luaZ_buffremove(buff,i) ((buff)->n -= (i)) #define luaZ_resetbuffer(buff) ((buff)->n = 0) #define luaZ_resizebuffer(L, buff, size) \ - (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \ + ((buff)->buffer = luaM_reallocvchar(L, (buff)->buffer, \ + (buff)->buffsize, size), \ (buff)->buffsize = size) #define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) -LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data); -LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ -LUAI_FUNC int luaZ_lookahead (ZIO *z); +LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n); /* read next n bytes */ @@ -56,8 +55,8 @@ LUAI_FUNC int luaZ_lookahead (ZIO *z); struct Zio { size_t n; /* bytes still unread */ const char *p; /* current position in buffer */ - lua_Reader reader; - void* data; /* additional data */ + lua_Reader reader; /* reader function */ + void *data; /* additional data */ lua_State *L; /* Lua state (for reader) */ }; diff --git a/app/src/main/jni/luajava/Android.mk b/app/src/main/jni/luajava/Android.mk index c2bcd7b..cb84099 100644 --- a/app/src/main/jni/luajava/Android.mk +++ b/app/src/main/jni/luajava/Android.mk @@ -7,4 +7,8 @@ LOCAL_MODULE := luajava LOCAL_SRC_FILES := luajava.c LOCAL_STATIC_LIBRARIES := liblua +LOCAL_LDLIBS := -llog + +LOCAL_CFLAGS += -DLUA_DL_DLOPEN -DLUA_USE_C89 -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 -DLUA_USE_LINUX + include $(BUILD_SHARED_LIBRARY) diff --git a/app/src/main/jni/luajava/log.h b/app/src/main/jni/luajava/log.h new file mode 100644 index 0000000..6c0c368 --- /dev/null +++ b/app/src/main/jni/luajava/log.h @@ -0,0 +1,17 @@ +// +// Created by leon on 16/3/10. +// + +#ifndef LUA_LOG_H +#define LUA_LOG_H + +#include + +#define LOG_LEVEL 10 +#define LOG_TAG "LUA-JNI" + +#define LOGI(level, ...) if (level <= LOG_LEVEL) {__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__);} +#define LOGE(level, ...) if (level <= LOG_LEVEL + 10) {__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__);} +#define LOGW(level, ...) if (level <= LOG_LEVEL + 5) {__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__);} + +#endif //LUA_LOG_H diff --git a/app/src/main/jni/luajava/luajava.c b/app/src/main/jni/luajava/luajava.c index c7639e5..a7f5599 100644 --- a/app/src/main/jni/luajava/luajava.c +++ b/app/src/main/jni/luajava/luajava.c @@ -1,45 +1,13 @@ - -/****************************************************************************** -* $Id$ -* Copyright (C) 2003-2007 Kepler Project. -* -* Permission is hereby granted, free of charge, to any person obtaining -* a copy of this software and associated documentation files (the -* "Software"), to deal in the Software without restriction, including -* without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to -* permit persons to whom the Software is furnished to do so, subject to -* the following conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -******************************************************************************/ - -/*************************************************************************** -* -* $ED -* This module is the implementation of luajava's dinamic library. -* In this module lua's functions are exported to be used in java by jni, -* and also the functions that will be used and exported to lua so that -* Java Objects' functions can be called. -* -*****************************************************************************/ - #include #include #include #include "lua.h" -#include "lualib.h" + #include "lauxlib.h" +#include "lualib.h" +#include "luajava.h" + /* Constant that is used to index the JNI Environment */ @@ -70,17 +38,17 @@ static jclass java_lang_class = NULL; /*************************************************************************** * * $FC Function objectIndex -* +* * $ED Description * Function to be called by the metamethod __index of the java object -* +* * $EP Function Parameters * $P L - lua State * $P Stack - Parameters will be received by the stack -* +* * $FV Returned Value * int - Number of values to be returned by the function -* +* *$. **********************************************************************/ static int objectIndex( lua_State * L ); @@ -89,18 +57,18 @@ static jclass java_lang_class = NULL; /*************************************************************************** * * $FC Function objectIndexReturn -* +* * $ED Description -* Function returned by the metamethod __index of a java Object. It is +* Function returned by the metamethod __index of a java Object. It is * the actual function that is going to call the java method. -* +* * $EP Function Parameters * $P L - lua State * $P Stack - Parameters will be received by the stack -* +* * $FV Returned Value * int - Number of values to be returned by the function -* +* *$. **********************************************************************/ static int objectIndexReturn( lua_State * L ); @@ -109,17 +77,17 @@ static jclass java_lang_class = NULL; /*************************************************************************** * * $FC Function classIndex -* +* * $ED Description * Function to be called by the metamethod __index of the java class -* +* * $EP Function Parameters * $P L - lua State * $P Stack - Parameters will be received by the stack -* +* * $FV Returned Value * int - Number of values to be returned by the function -* +* *$. **********************************************************************/ static int classIndex( lua_State * L ); @@ -128,17 +96,17 @@ static jclass java_lang_class = NULL; /*************************************************************************** * * $FC Function GC -* +* * $ED Description * Function to be called by the metamethod __gc of the java object -* +* * $EP Function Parameters * $P L - lua State * $P Stack - Parameters will be received by the stack -* +* * $FV Returned Value * int - Number of values to be returned by the function -* +* *$. **********************************************************************/ static int gc( lua_State * L ); @@ -147,16 +115,16 @@ static jclass java_lang_class = NULL; /*************************************************************************** * * $FC Function javaBindClass -* +* * $ED Description * Implementation of lua function luajava.BindClass -* +* * $EP Function Parameters * $P L - lua State -* +* * $FV Returned Value * int - Number of values to be returned by the function -* +* *$. **********************************************************************/ static int javaBindClass( lua_State * L ); @@ -164,19 +132,19 @@ static jclass java_lang_class = NULL; /*************************************************************************** * * $FC Function createProxy -* +* * $ED Description * Implementation of lua function luajava.createProxy. -* Transform a lua table into a java class that implements a list +* Transform a lua table into a java class that implements a list * of interfaces -* +* * $EP Function Parameters * $P L - lua State * $P Stack - Parameters will be received by the stack -* +* * $FV Returned Value * int - Number of values to be returned by the function -* +* *$. **********************************************************************/ static int createProxy( lua_State * L ); @@ -184,17 +152,17 @@ static jclass java_lang_class = NULL; /*************************************************************************** * * $FC Function javaNew -* +* * $ED Description * Implementation of lua function luajava.new -* +* * $EP Function Parameters * $P L - lua State * $P Stack - Parameters will be received by the stack -* +* * $FV Returned Value * int - Number of values to be returned by the function -* +* *$. **********************************************************************/ static int javaNew( lua_State * L ); @@ -203,17 +171,17 @@ static jclass java_lang_class = NULL; /*************************************************************************** * * $FC Function javaNewInstance -* +* * $ED Description * Implementation of lua function luajava.newInstance -* +* * $EP Function Parameters * $P L - lua State * $P Stack - Parameters will be received by the stack -* +* * $FV Returned Value * int - Number of values to be returned by the function -* +* *$. **********************************************************************/ static int javaNewInstance( lua_State * L ); @@ -222,17 +190,17 @@ static jclass java_lang_class = NULL; /*************************************************************************** * * $FC Function javaLoadLib -* +* * $ED Description * Implementation of lua function luajava.loadLib -* +* * $EP Function Parameters * $P L - lua State * $P Stack - Parameters will be received by the stack -* +* * $FV Returned Value * int - Number of values to be returned by the function -* +* *$. **********************************************************************/ static int javaLoadLib( lua_State * L ); @@ -241,17 +209,17 @@ static jclass java_lang_class = NULL; /*************************************************************************** /* * $FC pushJavaObject -* +* * $ED Description * Function to create a lua proxy to a java object -* +* * $EP Function Parameters * $P L - lua State * $P javaObject - Java Object to be pushed on the stack -* +* * $FV Returned Value * int - Number of values to be returned by the function -* +* *$. **********************************************************************/ static int pushJavaObject( lua_State * L , jobject javaObject ); @@ -260,17 +228,17 @@ static jclass java_lang_class = NULL; /*************************************************************************** * * $FC pushJavaClass -* +* * $ED Description * Function to create a lua proxy to a java class -* +* * $EP Function Parameters * $P L - lua State * $P javaObject - Java Class to be pushed on the stack -* +* * $FV Returned Value * int - Number of values to be returned by the function -* +* *$. **********************************************************************/ static int pushJavaClass( lua_State * L , jobject javaObject ); @@ -279,17 +247,17 @@ static jclass java_lang_class = NULL; /*************************************************************************** * * $FC isJavaObject -* +* * $ED Description * Returns 1 is given index represents a java object -* +* * $EP Function Parameters * $P L - lua State * $P idx - index on the stack -* +* * $FV Returned Value * int - Boolean. -* +* *$. **********************************************************************/ static int isJavaObject( lua_State * L , int idx ); @@ -298,17 +266,17 @@ static jclass java_lang_class = NULL; /*************************************************************************** * * $FC getStateFromCPtr -* +* * $ED Description * Returns the lua_State from the CPtr Java Object -* +* * $EP Function Parameters * $P L - lua State * $P cptr - CPtr object -* +* * $FV Returned Value * int - Number of values to be returned by the function. -* +* *$. **********************************************************************/ static lua_State * getStateFromCPtr( JNIEnv * env , jobject cptr ); @@ -317,17 +285,17 @@ static jclass java_lang_class = NULL; /*************************************************************************** * * $FC luaJavaFunctionCall -* +* * $ED Description * function called by metamethod __call of instances of JavaFunctionWrapper -* +* * $EP Function Parameters * $P L - lua State * $P Stack - Parameters will be received by the stack -* +* * $FV Returned Value * int - Number of values to be returned by the function. -* +* *$. **********************************************************************/ static int luaJavaFunctionCall( lua_State * L ); @@ -336,17 +304,17 @@ static jclass java_lang_class = NULL; /*************************************************************************** * * $FC pushJNIEnv -* +* * $ED Description * function that pushes the jni environment into the lua state -* +* * $EP Function Parameters * $P env - java environment * $P L - lua State -* +* * $FV Returned Value * void -* +* *$. **********************************************************************/ static void pushJNIEnv( JNIEnv * env , lua_State * L ); @@ -355,20 +323,20 @@ static jclass java_lang_class = NULL; /*************************************************************************** * * $FC getEnvFromState -* +* * $ED Description * auxiliar function to get the JNIEnv from the lua state -* +* * $EP Function Parameters * $P L - lua State -* +* * $FV Returned Value * JNIEnv * - JNI environment -* +* *$. **********************************************************************/ static JNIEnv * getEnvFromState( lua_State * L ); - + /********************* Implementations ***************************/ @@ -439,7 +407,7 @@ int objectIndex( lua_State * L ) { jobject jstr; const char * cStr; - + ( *javaEnv )->ExceptionClear( javaEnv ); jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); @@ -570,7 +538,7 @@ int objectIndexReturn( lua_State * L ) str = ( *javaEnv )->NewStringUTF( javaEnv , methodName ); - ret = ( *javaEnv )->CallStaticIntMethod( javaEnv , luajava_api_class , method , (jint)stateIndex , + ret = ( *javaEnv )->CallStaticIntMethod( javaEnv , luajava_api_class , method , (jint)stateIndex , *pObject , str ); exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); @@ -580,7 +548,7 @@ int objectIndexReturn( lua_State * L ) { jobject jstr; const char * cStr; - + ( *javaEnv )->ExceptionClear( javaEnv ); jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); @@ -672,7 +640,7 @@ int classIndex( lua_State * L ) str = ( *javaEnv )->NewStringUTF( javaEnv , fieldName ); /* Return 1 for field, 2 for method or 0 for error */ - ret = ( *javaEnv )->CallStaticIntMethod( javaEnv , luajava_api_class , method, (jint)stateIndex , + ret = ( *javaEnv )->CallStaticIntMethod( javaEnv , luajava_api_class , method, (jint)stateIndex , *obj , str ); exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); @@ -682,7 +650,7 @@ int classIndex( lua_State * L ) { jobject jstr; const char * cStr; - + ( *javaEnv )->ExceptionClear( javaEnv ); jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); @@ -800,7 +768,7 @@ int javaBindClass( lua_State * L ) } className = lua_tostring( L , 1 ); - method = ( *javaEnv )->GetStaticMethodID( javaEnv , java_lang_class , "forName" , + method = ( *javaEnv )->GetStaticMethodID( javaEnv , java_lang_class , "forName" , "(Ljava/lang/String;)Ljava/lang/Class;" ); javaClassName = ( *javaEnv )->NewStringUTF( javaEnv , className ); @@ -815,7 +783,7 @@ int javaBindClass( lua_State * L ) { jobject jstr; const char * cStr; - + ( *javaEnv )->ExceptionClear( javaEnv ); jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); @@ -901,7 +869,7 @@ int createProxy( lua_State * L ) str = ( *javaEnv )->NewStringUTF( javaEnv , impl ); ret = ( *javaEnv )->CallStaticIntMethod( javaEnv , luajava_api_class , method, (jint)stateIndex , str ); - + exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); /* Handles exception */ @@ -909,7 +877,7 @@ int createProxy( lua_State * L ) { jobject jstr; const char * cStr; - + ( *javaEnv )->ExceptionClear( javaEnv ); jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); @@ -1002,7 +970,7 @@ int javaNew( lua_State * L ) lua_error( L ); } - method = ( *javaEnv )->GetStaticMethodID( javaEnv , luajava_api_class , "javaNew" , + method = ( *javaEnv )->GetStaticMethodID( javaEnv , luajava_api_class , "javaNew" , "(ILjava/lang/Class;)I" ); if ( clazz == NULL || method == NULL ) @@ -1020,7 +988,7 @@ int javaNew( lua_State * L ) { jobject jstr; const char * str; - + ( *javaEnv )->ExceptionClear( javaEnv ); jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); @@ -1093,8 +1061,8 @@ int javaNewInstance( lua_State * L ) "(ILjava/lang/String;)I" ); javaClassName = ( *javaEnv )->NewStringUTF( javaEnv , className ); - - ret = ( *javaEnv )->CallStaticIntMethod( javaEnv , luajava_api_class , method, (jint)stateIndex , + + ret = ( *javaEnv )->CallStaticIntMethod( javaEnv , luajava_api_class , method, (jint)stateIndex , javaClassName ); exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); @@ -1104,7 +1072,7 @@ int javaNewInstance( lua_State * L ) { jobject jstr; const char * str; - + ( *javaEnv )->ExceptionClear( javaEnv ); jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); @@ -1193,8 +1161,8 @@ int javaLoadLib( lua_State * L ) javaClassName = ( *javaEnv )->NewStringUTF( javaEnv , className ); javaMethodName = ( *javaEnv )->NewStringUTF( javaEnv , methodName ); - - ret = ( *javaEnv )->CallStaticIntMethod( javaEnv , luajava_api_class , method, (jint)stateIndex , + + ret = ( *javaEnv )->CallStaticIntMethod( javaEnv , luajava_api_class , method, (jint)stateIndex , javaClassName , javaMethodName ); exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); @@ -1204,7 +1172,7 @@ int javaLoadLib( lua_State * L ) { jobject jstr; const char * str; - + ( *javaEnv )->ExceptionClear( javaEnv ); jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); @@ -1393,7 +1361,7 @@ int luaJavaFunctionCall( lua_State * L ) jthrowable exp; int ret; JNIEnv * javaEnv; - + if ( !isJavaObject( L , 1 ) ) { lua_pushstring( L , "Not a java Function." ); @@ -1427,7 +1395,7 @@ int luaJavaFunctionCall( lua_State * L ) { jobject jstr; const char * str; - + ( *javaEnv )->ExceptionClear( javaEnv ); jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); @@ -1532,7 +1500,7 @@ static void set_info (lua_State *L) { * LuaJava API Functin ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState_luajava_1open +void jni_luajavaOpen ( JNIEnv * env , jobject jobj , jobject cptr , jint stateId ) { lua_State* L; @@ -1551,9 +1519,9 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState_luajava_1open lua_setglobal( L , "luajava" ); lua_getglobal( L , "luajava" ); - + set_info( L); - + lua_pushstring( L , "bindClass" ); lua_pushcfunction( L , &javaBindClass ); lua_settable( L , -3 ); @@ -1678,7 +1646,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState_luajava_1open * LuaJava API Functin ************************************************************************/ -JNIEXPORT jobject JNICALL Java_org_keplerproject_luajava_LuaState__1getObjectFromUserdata +jobject jni_getObjectFromUserdata (JNIEnv * env , jobject jobj , jobject cptr , jint index ) { /* Get luastate */ @@ -1703,7 +1671,7 @@ JNIEXPORT jobject JNICALL Java_org_keplerproject_luajava_LuaState__1getObjectFro * LuaJava API Functin ************************************************************************/ -JNIEXPORT jboolean JNICALL Java_org_keplerproject_luajava_LuaState__1isObject +jboolean jni_isObject (JNIEnv * env , jobject jobj , jobject cptr , jint index ) { /* Get luastate */ @@ -1718,7 +1686,7 @@ JNIEXPORT jboolean JNICALL Java_org_keplerproject_luajava_LuaState__1isObject * LuaJava API Functin ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushJavaObject +void jni_pushJavaObject (JNIEnv * env , jobject jobj , jobject cptr , jobject obj ) { /* Get luastate */ @@ -1733,7 +1701,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushJavaObject * LuaJava API Functin ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushJavaFunction +void jni_pushJavaFunction (JNIEnv * env , jobject jobj , jobject cptr , jobject obj ) { /* Get luastate */ @@ -1776,7 +1744,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushJavaFunctio * LuaJava API Functin ************************************************************************/ -JNIEXPORT jboolean JNICALL Java_org_keplerproject_luajava_LuaState__1isJavaFunction +jboolean jni_isJavaFunction (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { /* Get luastate */ @@ -1802,16 +1770,16 @@ JNIEXPORT jboolean JNICALL Java_org_keplerproject_luajava_LuaState__1isJavaFunct * Lua Exported Function ************************************************************************/ -JNIEXPORT jobject JNICALL Java_org_keplerproject_luajava_LuaState__1open +jobject jni_open (JNIEnv * env , jobject jobj) { - lua_State * L = lua_open(); + lua_State * L = luaL_newstate(); jobject obj; jclass tempClass; tempClass = ( *env )->FindClass( env , "org/keplerproject/luajava/CPtr" ); - + obj = ( *env )->AllocObject( env , tempClass ); if ( obj ) { @@ -1827,7 +1795,7 @@ JNIEXPORT jobject JNICALL Java_org_keplerproject_luajava_LuaState__1open * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openBase +void jni_openBase (JNIEnv * env , jobject jobj , jobject cptr) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -1844,7 +1812,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openBase * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openTable +void jni_openTable (JNIEnv * env , jobject jobj , jobject cptr) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -1861,7 +1829,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openTable * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openIo +void jni_openIo (JNIEnv * env , jobject jobj , jobject cptr) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -1878,7 +1846,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openIo * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openOs +void jni_openOs (JNIEnv * env , jobject jobj , jobject cptr) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -1895,7 +1863,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openOs * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openString +void jni_openString (JNIEnv * env , jobject jobj , jobject cptr) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -1912,7 +1880,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openString * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openMath +void jni_openMath (JNIEnv * env , jobject jobj , jobject cptr) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -1929,7 +1897,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openMath * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openDebug +void jni_openDebug (JNIEnv * env, jobject jobj , jobject cptr) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -1946,7 +1914,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openDebug * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openPackage +void jni_openPackage (JNIEnv * env, jobject jobj , jobject cptr) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -1963,7 +1931,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openPackage * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openLibs +void jni_openLibs (JNIEnv * env, jobject jobj , jobject cptr) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -1977,7 +1945,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1openLibs * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1close +void jni_close (JNIEnv * env , jobject jobj , jobject cptr) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -1991,15 +1959,15 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1close * Lua Exported Function ************************************************************************/ -JNIEXPORT jobject JNICALL Java_org_keplerproject_luajava_LuaState__1newthread +jobject jni_newthread (JNIEnv * env , jobject jobj , jobject cptr) { lua_State * L = getStateFromCPtr( env , cptr ); lua_State * newThread; - + jobject obj; jclass tempClass; - + newThread = lua_newthread( L ); tempClass = ( *env )->FindClass( env , "org/keplerproject/luajava/CPtr" ); @@ -2020,7 +1988,7 @@ JNIEXPORT jobject JNICALL Java_org_keplerproject_luajava_LuaState__1newthread * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1getTop +jint jni_getTop (JNIEnv * env , jobject jobj , jobject cptr) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2034,7 +2002,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1getTop * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1setTop +void jni_setTop (JNIEnv * env , jobject jobj , jobject cptr , jint top) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2048,7 +2016,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1setTop * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushValue +void jni_pushValue (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2062,7 +2030,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushValue * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1remove +void jni_remove (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2076,7 +2044,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1remove * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1insert +void jni_insert (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2090,7 +2058,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1insert * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1replace +void jni_replace (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2104,7 +2072,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1replace * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1checkStack +jint jni_checkStack (JNIEnv * env , jobject jobj , jobject cptr , jint sz) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2118,7 +2086,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1checkStack * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1xmove +void jni_xmove (JNIEnv * env , jobject jobj , jobject from , jobject to , jint n) { lua_State * fr = getStateFromCPtr( env , from ); @@ -2133,7 +2101,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1xmove * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isNumber +jint jni_isNumber (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2147,7 +2115,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isNumber * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isString +jint jni_isString (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2161,7 +2129,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isString * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isFunction +jint jni_isFunction (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2175,7 +2143,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isFunction * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isCFunction +jint jni_isCFunction (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2189,7 +2157,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isCFunction * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isUserdata +jint jni_isUserdata (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2203,7 +2171,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isUserdata * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isTable +jint jni_isTable (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2217,7 +2185,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isTable * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isBoolean +jint jni_isBoolean (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2231,7 +2199,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isBoolean * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isNil +jint jni_isNil (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2245,7 +2213,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isNil * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isNone +jint jni_isNone (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2259,7 +2227,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isNone * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isNoneOrNil +jint jni_isNoneOrNil (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2273,7 +2241,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1isNoneOrNil * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1type +jint jni_type (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2287,7 +2255,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1type * Lua Exported Function ************************************************************************/ -JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1typeName +jstring jni_typeName (JNIEnv * env , jobject jobj , jobject cptr , jint tp) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2303,7 +2271,7 @@ JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1typeName * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1equal +jint jni_equal (JNIEnv * env , jobject jobj , jobject cptr , jint idx1 , jint idx2) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2317,7 +2285,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1equal * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1rawequal +jint jni_rawequal (JNIEnv * env , jobject jobj , jobject cptr , jint idx1 , jint idx2) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2325,13 +2293,13 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1rawequal return ( jint ) lua_rawequal( L , idx1 , idx2 ); } - + /************************************************************************ * JNI Called function * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1lessthan +jint jni_lessthan (JNIEnv * env , jobject jobj , jobject cptr , jint idx1 , jint idx2) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2345,7 +2313,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1lessthan * Lua Exported Function ************************************************************************/ -JNIEXPORT jdouble JNICALL Java_org_keplerproject_luajava_LuaState__1toNumber +jdouble jni_toNumber (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2359,7 +2327,7 @@ JNIEXPORT jdouble JNICALL Java_org_keplerproject_luajava_LuaState__1toNumber * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1toInteger +jint jni_toInteger (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2373,7 +2341,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1toInteger * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1toBoolean +jint jni_toBoolean (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2387,7 +2355,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1toBoolean * Lua Exported Function ************************************************************************/ -JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1toString +jstring jni_toString (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2403,7 +2371,7 @@ JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1toString * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1strlen +jint jni_strlen (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2417,7 +2385,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1strlen * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1objlen +jint jni_objlen (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2431,7 +2399,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1objlen * Lua Exported Function ************************************************************************/ -JNIEXPORT jobject JNICALL Java_org_keplerproject_luajava_LuaState__1toThread +jobject jni_toThread (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L , * thr; @@ -2444,7 +2412,7 @@ JNIEXPORT jobject JNICALL Java_org_keplerproject_luajava_LuaState__1toThread thr = lua_tothread( L , ( int ) idx ); tempClass = ( *env )->FindClass( env , "org/keplerproject/luajava/CPtr" ); - + obj = ( *env )->AllocObject( env , tempClass ); if ( obj ) { @@ -2460,7 +2428,7 @@ JNIEXPORT jobject JNICALL Java_org_keplerproject_luajava_LuaState__1toThread * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushNil +void jni_pushNil (JNIEnv * env , jobject jobj , jobject cptr) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2474,7 +2442,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushNil * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushNumber +void jni_pushNumber (JNIEnv * env , jobject jobj , jobject cptr , jdouble number) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2488,7 +2456,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushNumber * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushString__Lorg_keplerproject_luajava_CPtr_2Ljava_lang_String_2 +void jni_pushString (JNIEnv * env , jobject jobj , jobject cptr , jstring str) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2497,7 +2465,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushString__Lor uniStr = ( *env )->GetStringUTFChars( env , str , NULL ); lua_pushstring( L , uniStr ); - + ( *env )->ReleaseStringUTFChars( env , str , uniStr ); } @@ -2507,16 +2475,16 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushString__Lor * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushString__Lorg_keplerproject_luajava_CPtr_2_3BI +void jni_pushString2 (JNIEnv * env , jobject jobj , jobject cptr , jbyteArray bytes , jint n) { lua_State * L = getStateFromCPtr( env , cptr ); char * cBytes; - + cBytes = ( char * ) ( *env )->GetByteArrayElements( env , bytes, NULL ); - + lua_pushlstring( L , cBytes , n ); - + ( *env )->ReleaseByteArrayElements( env , bytes , cBytes , 0 ); } @@ -2526,7 +2494,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushString__Lor * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushBoolean +void jni_pushBoolean (JNIEnv * env , jobject jobj , jobject cptr , jint jbool) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2540,7 +2508,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushBoolean * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1getTable +void jni_getTable (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2554,7 +2522,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1getTable * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1getField +void jni_getField (JNIEnv * env , jobject jobj , jobject cptr , jint idx , jstring k) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2563,7 +2531,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1getField uniStr = ( *env )->GetStringUTFChars( env , k , NULL ); lua_getfield( L , ( int ) idx , uniStr ); - + ( *env )->ReleaseStringUTFChars( env , k , uniStr ); } @@ -2572,7 +2540,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1getField * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1rawGet +void jni_rawGet (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2586,7 +2554,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1rawGet * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1rawGetI +void jni_rawGetI (JNIEnv * env , jobject jobj , jobject cptr , jint idx, jint n) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2600,7 +2568,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1rawGetI * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1createTable +void jni_createTable (JNIEnv * env , jobject jobj , jobject cptr , jint narr , jint nrec) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2614,7 +2582,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1createTable * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1newTable +void jni_newTable (JNIEnv * env , jobject jobj , jobject cptr) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2628,7 +2596,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1newTable * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1getMetaTable +jint jni_getMetaTable (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2642,21 +2610,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1getMetaTable * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1getFEnv - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - lua_getfenv( L , ( int ) idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1setTable +void jni_setTable (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2670,7 +2624,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1setTable * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1setField +void jni_setField (JNIEnv * env , jobject jobj , jobject cptr , jint idx , jstring k) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2679,7 +2633,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1setField uniStr = ( *env )->GetStringUTFChars( env , k , NULL ); lua_setfield( L , ( int ) idx , uniStr ); - + ( *env )->ReleaseStringUTFChars( env , k , uniStr ); } @@ -2689,7 +2643,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1setField * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1rawSet +void jni_rawSet (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2703,7 +2657,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1rawSet * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1rawSetI +void jni_rawSetI (JNIEnv * env , jobject jobj , jobject cptr , jint idx, jint n) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2717,7 +2671,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1rawSetI * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1setMetaTable +jint jni_setMetaTable (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2725,27 +2679,12 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1setMetaTable return lua_setmetatable( L , idx ); } - /************************************************************************ * JNI Called function * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1setFEnv - (JNIEnv * env , jobject jobj , jobject cptr , jint idx) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return lua_setfenv( L , idx ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1call +void jni_call (JNIEnv * env , jobject jobj , jobject cptr , jint nArgs , jint nResults) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2759,7 +2698,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1call * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1pcall +jint jni_pcall (JNIEnv * env , jobject jobj , jobject cptr , jint nArgs , jint nResults , jint errFunc) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2773,7 +2712,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1pcall * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1yield +jint jni_yield (JNIEnv * env , jobject jobj , jobject cptr , jint nResults) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2787,12 +2726,13 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1yield * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1resume - (JNIEnv * env , jobject jobj , jobject cptr , jint nArgs) +jint jni_resume + (JNIEnv * env , jobject jobj , jobject cptr, jobject cptrFrom, jint nArgs) { lua_State * L = getStateFromCPtr( env , cptr ); + lua_State * From = getStateFromCPtr( env , cptrFrom ); - return ( jint ) lua_resume( L , nArgs ); + return ( jint ) lua_resume( L, From, nArgs ); } @@ -2801,7 +2741,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1resume * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1status +jint jni_status (JNIEnv * env , jobject jobj , jobject cptr) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2815,7 +2755,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1status * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1gc +jint jni_gc (JNIEnv * env , jobject jobj , jobject cptr , jint what , jint data) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2829,21 +2769,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1gc * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1getGcCount - (JNIEnv * env , jobject jobj , jobject cptr) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) lua_getgccount( L ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1next +jint jni_next (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2857,7 +2783,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1next * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1error +jint jni_error (JNIEnv * env , jobject jobj , jobject cptr) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2871,7 +2797,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1error * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1concat +void jni_concat (JNIEnv * env , jobject jobj , jobject cptr , jint n) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2885,7 +2811,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1concat * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pop +void jni_pop (JNIEnv * env , jobject jobj , jobject cptr , jint idx) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2899,7 +2825,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pop * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1setGlobal +void jni_setGlobal (JNIEnv * env , jobject jobj , jobject cptr , jstring name) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2917,7 +2843,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1setGlobal * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1getGlobal +void jni_getGlobal (JNIEnv * env , jobject jobj , jobject cptr , jstring name) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2935,7 +2861,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1getGlobal * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LdoFile +jint jni_LdoFile (JNIEnv * env , jobject jobj , jobject cptr , jstring fileName) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2957,7 +2883,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LdoFile * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LdoString +jint jni_LdoString (JNIEnv * env , jobject jobj , jobject cptr , jstring str) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2977,7 +2903,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LdoString * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LgetMetaField +jint jni_LgetMetaField (JNIEnv * env , jobject jobj , jobject cptr , jint obj , jstring e) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -2997,7 +2923,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LgetMetaField * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LcallMeta +jint jni_LcallMeta (JNIEnv * env , jobject jobj , jobject cptr , jint obj , jstring e) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -3011,33 +2937,12 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LcallMeta return ( jint ) ret; } - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1Ltyperror - (JNIEnv * env , jobject jobj , jobject cptr , jint nArg , jstring tName) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - const char * name = ( *env )->GetStringUTFChars( env , tName , NULL ); - int ret; - - ret = luaL_typerror( L , ( int ) nArg , name ); - - ( *env )->ReleaseStringUTFChars( env , tName , name ); - - return ( jint ) ret; -} - - /************************************************************************ * JNI Called function * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LargError +jint jni_LargError (JNIEnv * env , jobject jobj , jobject cptr , jint numArg , jstring extraMsg) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -3057,7 +2962,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LargError * Lua Exported Function ************************************************************************/ -JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckString +jstring jni_LcheckString (JNIEnv * env , jobject jobj , jobject cptr , jint numArg) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -3074,7 +2979,7 @@ JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckString * Lua Exported Function ************************************************************************/ -JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1LoptString +jstring jni_LoptString (JNIEnv * env , jobject jobj , jobject cptr , jint numArg , jstring def) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -3097,7 +3002,7 @@ JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1LoptString * Lua Exported Function ************************************************************************/ -JNIEXPORT jdouble JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckNumber +jdouble jni_LcheckNumber (JNIEnv * env , jobject jobj , jobject cptr , jint numArg) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -3111,7 +3016,7 @@ JNIEXPORT jdouble JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckNumber * Lua Exported Function ************************************************************************/ -JNIEXPORT jdouble JNICALL Java_org_keplerproject_luajava_LuaState__1LoptNumber +jdouble jni_LoptNumber (JNIEnv * env , jobject jobj , jobject cptr , jint numArg , jdouble def) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -3125,7 +3030,7 @@ JNIEXPORT jdouble JNICALL Java_org_keplerproject_luajava_LuaState__1LoptNumber * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckInteger +jint jni_LcheckInteger (JNIEnv * env , jobject jobj , jobject cptr , jint numArg) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -3139,7 +3044,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckInteger * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LoptInteger +jint jni_LoptInteger (JNIEnv * env , jobject jobj , jobject cptr , jint numArg , jint def) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -3153,7 +3058,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LoptInteger * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckStack +void jni_LcheckStack (JNIEnv * env , jobject jobj , jobject cptr , jint sz , jstring msg) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -3170,7 +3075,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckStack * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckType +void jni_LcheckType (JNIEnv * env , jobject jobj , jobject cptr , jint nArg , jint t) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -3184,7 +3089,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckType * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckAny +void jni_LcheckAny (JNIEnv * env , jobject jobj , jobject cptr , jint nArg) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -3198,7 +3103,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1LcheckAny * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LnewMetatable +jint jni_LnewMetatable (JNIEnv * env , jobject jobj , jobject cptr , jstring tName) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -3218,7 +3123,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LnewMetatable * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1LgetMetatable +void jni_LgetMetatable (JNIEnv * env , jobject jobj , jobject cptr , jstring tName) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -3235,7 +3140,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1LgetMetatable * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1Lwhere +void jni_Lwhere (JNIEnv * env , jobject jobj , jobject cptr , jint lvl) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -3249,7 +3154,7 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1Lwhere * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1Lref +jint jni_Lref (JNIEnv * env , jobject jobj , jobject cptr , jint t) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -3263,7 +3168,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1Lref * Lua Exported Function ************************************************************************/ -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1LunRef +void jni_LunRef (JNIEnv * env , jobject jobj , jobject cptr , jint t , jint ref) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -3271,41 +3176,12 @@ JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1LunRef luaL_unref( L , ( int ) t , ( int ) ref ); } - /************************************************************************ * JNI Called function * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LgetN - (JNIEnv * env , jobject jobj , jobject cptr , jint t) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - return ( jint ) luaL_getn( L , ( int ) t ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1LsetN - (JNIEnv * env , jobject jobj , jobject cptr , jint t , jint n) -{ - lua_State * L = getStateFromCPtr( env , cptr ); - - luaL_setn( L , ( int ) t , ( int ) n ); -} - - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LloadFile +jint jni_LloadFile (JNIEnv * env , jobject jobj , jobject cptr , jstring fileName) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -3325,7 +3201,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LloadFile * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LloadBuffer +jint jni_LloadBuffer (JNIEnv * env , jobject jobj , jobject cptr , jbyteArray buff , jlong sz , jstring n) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -3348,7 +3224,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LloadBuffer * Lua Exported Function ************************************************************************/ -JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LloadString +jint jni_LloadString (JNIEnv * env , jobject jobj , jobject cptr , jstring str) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -3368,7 +3244,7 @@ JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1LloadString * Lua Exported Function ************************************************************************/ -JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1Lgsub +jstring jni_Lgsub (JNIEnv * env , jobject jobj , jobject cptr , jstring s , jstring p , jstring r) { lua_State * L = getStateFromCPtr( env , cptr ); @@ -3385,21 +3261,36 @@ JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1Lgsub return ( *env )->NewStringUTF( env , sub ); } - -/************************************************************************ -* JNI Called function -* Lua Exported Function -************************************************************************/ - -JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1LfindTable - (JNIEnv * env , jobject jobj , jobject cptr , jint idx , jstring fname , jint szhint) +jint jni_registryIndex(JNIEnv * env) { - lua_State * L = getStateFromCPtr( env , cptr ); - const char * name = ( *env )->GetStringUTFChars( env , fname , NULL ); + return LUA_REGISTRYINDEX; +} - const char * sub = luaL_findtable( L , ( int ) idx , name , ( int ) szhint ); +jint JNI_OnLoad(JavaVM* vm, void* reserved) +{ + JNIEnv* env = NULL; - ( *env )->ReleaseStringUTFChars( env , fname , name ); + jint result = -1; + LOGI(8, "start load") + if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) + { + LOGW(1, "get env failed") + return JNI_ERR; + } + jclass cls = (*env)->FindClass(env, LUASTATE_CLASS); + if (cls == NULL) + { + LOGW(1, "get class failed") + return JNI_ERR; + } - return ( *env )->NewStringUTF( env , sub ); + int len = sizeof(jni_methods) / sizeof(jni_methods[0]); + LOGW(1, "methods len:%d", len) + if ((*env)->RegisterNatives(env, cls, jni_methods, len) < 0) + { + LOGW(1, "register method failed") + return JNI_ERR; + } + LOGI(8, "load success") + return JNI_VERSION_1_4; } diff --git a/app/src/main/jni/luajava/luajava.h b/app/src/main/jni/luajava/luajava.h new file mode 100644 index 0000000..b3c8bf6 --- /dev/null +++ b/app/src/main/jni/luajava/luajava.h @@ -0,0 +1,219 @@ +#ifndef LUA_JNI_H +#define LUA_JNI_H + +#define LUASTATE_CLASS "org/keplerproject/luajava/LuaState" +#define CPTR_CLASS_PATH "Lorg/keplerproject/luajava/CPtr;" +#define OBJECT_CLASS_PATH "Ljava/lang/Object;" +#define STRING_CLASS_PATH "Ljava/lang/String;" + + +#include +#include "log.h" + +void jni_luajavaOpen (JNIEnv * env , jobject jobj , jobject cptr , jint stateId ); +jobject jni_getObjectFromUserdata (JNIEnv * env , jobject jobj , jobject cptr , jint index ); +jboolean jni_isObject (JNIEnv * env , jobject jobj , jobject cptr , jint index ); +void jni_pushJavaObject (JNIEnv * env , jobject jobj , jobject cptr , jobject obj ); +void jni_pushJavaFunction (JNIEnv * env , jobject jobj , jobject cptr , jobject obj ); +jboolean jni_isJavaFunction (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +jobject jni_open (JNIEnv * env , jobject jobj); +void jni_openBase (JNIEnv * env , jobject jobj , jobject cptr); +void jni_openTable (JNIEnv * env , jobject jobj , jobject cptr); +void jni_openIo (JNIEnv * env , jobject jobj , jobject cptr); +void jni_openOs (JNIEnv * env , jobject jobj , jobject cptr); +void jni_openString (JNIEnv * env , jobject jobj , jobject cptr); +void jni_openMath (JNIEnv * env , jobject jobj , jobject cptr); +void jni_openDebug (JNIEnv * env, jobject jobj , jobject cptr); +void jni_openPackage (JNIEnv * env, jobject jobj , jobject cptr); +void jni_openLibs (JNIEnv * env, jobject jobj , jobject cptr); +void jni_close (JNIEnv * env , jobject jobj , jobject cptr); +jobject jni_newthread (JNIEnv * env , jobject jobj , jobject cptr); +jint jni_getTop (JNIEnv * env , jobject jobj , jobject cptr); +void jni_setTop (JNIEnv * env , jobject jobj , jobject cptr , jint top); +void jni_pushValue (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +void jni_remove (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +void jni_insert (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +void jni_replace (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +jint jni_checkStack (JNIEnv * env , jobject jobj , jobject cptr , jint sz); +void jni_xmove (JNIEnv * env , jobject jobj , jobject from , jobject to , jint n); +jint jni_isNumber (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +jint jni_isString (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +jint jni_isFunction (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +jint jni_isCFunction (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +jint jni_isUserdata (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +jint jni_isTable (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +jint jni_isBoolean (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +jint jni_isNil (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +jint jni_isNone (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +jint jni_isNoneOrNil (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +jint jni_type (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +jstring jni_typeName (JNIEnv * env , jobject jobj , jobject cptr , jint tp); +jint jni_equal (JNIEnv * env , jobject jobj , jobject cptr , jint idx1 , jint idx2); +jint jni_rawequal (JNIEnv * env , jobject jobj , jobject cptr , jint idx1 , jint idx2); +jint jni_lessthan (JNIEnv * env , jobject jobj , jobject cptr , jint idx1 , jint idx2); +jdouble jni_toNumber (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +jint jni_toInteger (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +jint jni_toBoolean (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +jstring jni_toString (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +jint jni_strlen (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +jint jni_objlen (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +jobject jni_toThread (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +void jni_pushNil (JNIEnv * env , jobject jobj , jobject cptr); +void jni_pushNumber (JNIEnv * env , jobject jobj , jobject cptr , jdouble number); +void jni_pushString (JNIEnv * env , jobject jobj , jobject cptr , jstring str); +void jni_pushString2 (JNIEnv * env , jobject jobj , jobject cptr , jbyteArray bytes , jint n); +void jni_pushBoolean (JNIEnv * env , jobject jobj , jobject cptr , jint jbool); +void jni_getTable (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +void jni_getField (JNIEnv * env , jobject jobj , jobject cptr , jint idx , jstring k); +void jni_rawGet (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +void jni_rawGetI (JNIEnv * env , jobject jobj , jobject cptr , jint idx, jint n); +void jni_createTable (JNIEnv * env , jobject jobj , jobject cptr , jint narr , jint nrec); +void jni_newTable (JNIEnv * env , jobject jobj , jobject cptr); +jint jni_getMetaTable (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +void jni_setTable (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +void jni_setField (JNIEnv * env , jobject jobj , jobject cptr , jint idx , jstring k); +void jni_rawSet (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +void jni_rawSetI (JNIEnv * env , jobject jobj , jobject cptr , jint idx, jint n); +jint jni_setMetaTable (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +void jni_call (JNIEnv * env , jobject jobj , jobject cptr , jint nArgs , jint nResults); +jint jni_pcall (JNIEnv * env , jobject jobj , jobject cptr , jint nArgs , jint nResults , jint errFunc); +jint jni_yield (JNIEnv * env , jobject jobj , jobject cptr , jint nResults); +jint jni_resume (JNIEnv * env , jobject jobj , jobject cptr, jobject cptrFrom, jint nArgs); +jint jni_status (JNIEnv * env , jobject jobj , jobject cptr); +jint jni_gc (JNIEnv * env , jobject jobj , jobject cptr , jint what , jint data); +jint jni_next (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +jint jni_error (JNIEnv * env , jobject jobj , jobject cptr); +void jni_concat (JNIEnv * env , jobject jobj , jobject cptr , jint n); +void jni_pop (JNIEnv * env , jobject jobj , jobject cptr , jint idx); +void jni_setGlobal (JNIEnv * env , jobject jobj , jobject cptr , jstring name); +void jni_getGlobal (JNIEnv * env , jobject jobj , jobject cptr , jstring name); +jint jni_LdoFile (JNIEnv * env , jobject jobj , jobject cptr , jstring fileName); +jint jni_LdoString (JNIEnv * env , jobject jobj , jobject cptr , jstring str); +jint jni_LgetMetaField (JNIEnv * env , jobject jobj , jobject cptr , jint obj , jstring e); +jint jni_LcallMeta (JNIEnv * env , jobject jobj , jobject cptr , jint obj , jstring e); +jint jni_LargError (JNIEnv * env , jobject jobj , jobject cptr , jint numArg , jstring extraMsg); +jstring jni_LcheckString (JNIEnv * env , jobject jobj , jobject cptr , jint numArg); +jstring jni_LoptString (JNIEnv * env , jobject jobj , jobject cptr , jint numArg , jstring def); +jdouble jni_LcheckNumber (JNIEnv * env , jobject jobj , jobject cptr , jint numArg); +jdouble jni_LoptNumber (JNIEnv * env , jobject jobj , jobject cptr , jint numArg , jdouble def); +jint jni_LcheckInteger (JNIEnv * env , jobject jobj , jobject cptr , jint numArg); +jint jni_LoptInteger (JNIEnv * env , jobject jobj , jobject cptr , jint numArg , jint def); +void jni_LcheckStack (JNIEnv * env , jobject jobj , jobject cptr , jint sz , jstring msg); +void jni_LcheckType (JNIEnv * env , jobject jobj , jobject cptr , jint nArg , jint t); +void jni_LcheckAny (JNIEnv * env , jobject jobj , jobject cptr , jint nArg); +jint jni_LnewMetatable (JNIEnv * env , jobject jobj , jobject cptr , jstring tName); +void jni_LgetMetatable (JNIEnv * env , jobject jobj , jobject cptr , jstring tName); +void jni_Lwhere (JNIEnv * env , jobject jobj , jobject cptr , jint lvl); +jint jni_Lref (JNIEnv * env , jobject jobj , jobject cptr , jint t); +void jni_LunRef (JNIEnv * env , jobject jobj , jobject cptr , jint t , jint ref); +jint jni_LloadFile (JNIEnv * env , jobject jobj , jobject cptr , jstring fileName); +jint jni_LloadBuffer (JNIEnv * env , jobject jobj , jobject cptr , jbyteArray buff , jlong sz , jstring n); +jint jni_LloadString (JNIEnv * env , jobject jobj , jobject cptr , jstring str); +jstring jni_Lgsub (JNIEnv * env , jobject jobj , jobject cptr , jstring s , jstring p , jstring r); +jint jni_registryIndex(JNIEnv * env); + +static JNINativeMethod jni_methods[] = { + {"_luajavaOpen", "("CPTR_CLASS_PATH"I)V", (void*)jni_luajavaOpen}, + {"_getObjectFromUserdata", "("CPTR_CLASS_PATH"I)"OBJECT_CLASS_PATH, (void*)jni_getObjectFromUserdata}, + {"_isObject", "("CPTR_CLASS_PATH"I)Z", (void*)jni_isObject}, + {"_pushJavaObject", "("CPTR_CLASS_PATH""OBJECT_CLASS_PATH")V", (void*)jni_pushJavaObject}, + {"_pushJavaFunction", "("CPTR_CLASS_PATH""OBJECT_CLASS_PATH")V", (void*)jni_pushJavaFunction}, + {"_isJavaFunction", "("CPTR_CLASS_PATH"I)Z", (void*)jni_isJavaFunction}, + {"_open", "()"OBJECT_CLASS_PATH, (void*)jni_open}, + {"_openBase", "("CPTR_CLASS_PATH")V", (void*)jni_openBase}, + {"_openTable", "("CPTR_CLASS_PATH")V", (void*)jni_openTable}, + {"_openIo", "("CPTR_CLASS_PATH")V", (void*)jni_openIo}, + {"_openOs", "("CPTR_CLASS_PATH")V", (void*)jni_openOs}, + {"_openString", "("CPTR_CLASS_PATH")V", (void*)jni_openString}, + {"_openMath", "("CPTR_CLASS_PATH")V", (void*)jni_openMath}, + {"_openDebug", "("CPTR_CLASS_PATH")V", (void*)jni_openDebug}, + {"_openPackage", "("CPTR_CLASS_PATH")V", (void*)jni_openPackage}, + {"_openLibs", "("CPTR_CLASS_PATH")V", (void*)jni_openLibs}, + {"_close", "("CPTR_CLASS_PATH")V", (void*)jni_close}, + {"_newthread", "("CPTR_CLASS_PATH")"OBJECT_CLASS_PATH, (void*)jni_newthread}, + {"_getTop", "("CPTR_CLASS_PATH")I", (void*)jni_getTop}, + {"_setTop", "("CPTR_CLASS_PATH"I)V", (void*)jni_setTop}, + {"_pushValue", "("CPTR_CLASS_PATH"I)V", (void*)jni_pushValue}, + {"_remove", "("CPTR_CLASS_PATH"I)V", (void*)jni_remove}, + {"_insert", "("CPTR_CLASS_PATH"I)V", (void*)jni_insert}, + {"_replace", "("CPTR_CLASS_PATH"I)V", (void*)jni_replace}, + {"_checkStack", "("CPTR_CLASS_PATH"I)I", (void*)jni_checkStack}, + {"_xmove", "("CPTR_CLASS_PATH""CPTR_CLASS_PATH"I)V", (void*)jni_xmove}, + {"_isNumber", "("CPTR_CLASS_PATH"I)I", (void*)jni_isNumber}, + {"_isString", "("CPTR_CLASS_PATH"I)I", (void*)jni_isString}, + {"_isFunction", "("CPTR_CLASS_PATH"I)I", (void*)jni_isFunction}, + {"_isCFunction", "("CPTR_CLASS_PATH"I)I", (void*)jni_isCFunction}, + {"_isUserdata", "("CPTR_CLASS_PATH"I)I", (void*)jni_isUserdata}, + {"_isTable", "("CPTR_CLASS_PATH"I)I", (void*)jni_isTable}, + {"_isBoolean", "("CPTR_CLASS_PATH"I)I", (void*)jni_isBoolean}, + {"_isNil", "("CPTR_CLASS_PATH"I)I", (void*)jni_isNil}, + {"_isNone", "("CPTR_CLASS_PATH"I)I", (void*)jni_isNone}, + {"_isNoneOrNil", "("CPTR_CLASS_PATH"I)I", (void*)jni_isNoneOrNil}, + {"_type", "("CPTR_CLASS_PATH"I)I", (void*)jni_type}, + {"_typeName", "("CPTR_CLASS_PATH"I)"STRING_CLASS_PATH, (void*)jni_typeName}, + {"_equal", "("CPTR_CLASS_PATH"II)I", (void*)jni_equal}, + {"_rawequal", "("CPTR_CLASS_PATH"II)I", (void*)jni_rawequal}, + {"_lessthan", "("CPTR_CLASS_PATH"II)I", (void*)jni_lessthan}, + {"_toNumber", "("CPTR_CLASS_PATH"I)D", (void*)jni_toNumber}, + {"_toInteger", "("CPTR_CLASS_PATH"I)I", (void*)jni_toInteger}, + {"_toBoolean", "("CPTR_CLASS_PATH"I)I", (void*)jni_toBoolean}, + {"_toString", "("CPTR_CLASS_PATH"I)"STRING_CLASS_PATH, (void*)jni_toString}, + {"_strlen", "("CPTR_CLASS_PATH"I)I", (void*)jni_strlen}, + {"_objlen", "("CPTR_CLASS_PATH"I)I", (void*)jni_objlen}, + {"_toThread", "("CPTR_CLASS_PATH"I)"OBJECT_CLASS_PATH, (void*)jni_toThread}, + {"_pushNil", "("CPTR_CLASS_PATH")V", (void*)jni_pushNil}, + {"_pushNumber", "("CPTR_CLASS_PATH"D)V", (void*)jni_pushNumber}, + {"_pushString", "("CPTR_CLASS_PATH""STRING_CLASS_PATH")V", (void*)jni_pushString}, + {"_pushString2", "("CPTR_CLASS_PATH"[BI)V", (void*)jni_pushString2}, + {"_pushBoolean", "("CPTR_CLASS_PATH"I)V", (void*)jni_pushBoolean}, + {"_getTable", "("CPTR_CLASS_PATH"I)V", (void*)jni_getTable}, + {"_getField", "("CPTR_CLASS_PATH"I"STRING_CLASS_PATH")V", (void*)jni_getField}, + {"_rawGet", "("CPTR_CLASS_PATH"I)V", (void*)jni_rawGet}, + {"_rawGetI", "("CPTR_CLASS_PATH"II)V", (void*)jni_rawGetI}, + {"_createTable", "("CPTR_CLASS_PATH"II)V", (void*)jni_createTable}, + {"_newTable", "("CPTR_CLASS_PATH")V", (void*)jni_newTable}, + {"_getMetaTable", "("CPTR_CLASS_PATH"I)I", (void*)jni_getMetaTable}, + {"_setTable", "("CPTR_CLASS_PATH"I)V", (void*)jni_setTable}, + {"_setField", "("CPTR_CLASS_PATH"I"STRING_CLASS_PATH")V", (void*)jni_setField}, + {"_rawSet", "("CPTR_CLASS_PATH"I)V", (void*)jni_rawSet}, + {"_rawSetI", "("CPTR_CLASS_PATH"II)V", (void*)jni_rawSetI}, + {"_setMetaTable", "("CPTR_CLASS_PATH"I)I", (void*)jni_setMetaTable}, + {"_call", "("CPTR_CLASS_PATH"II)V", (void*)jni_call}, + {"_pcall", "("CPTR_CLASS_PATH"III)I", (void*)jni_pcall}, + {"_yield", "("CPTR_CLASS_PATH"I)I", (void*)jni_yield}, + {"_resume", "("CPTR_CLASS_PATH""CPTR_CLASS_PATH"I)I", (void*)jni_resume}, + {"_status", "("CPTR_CLASS_PATH")I", (void*)jni_status}, + {"_gc", "("CPTR_CLASS_PATH"II)I", (void*)jni_gc}, + {"_next", "("CPTR_CLASS_PATH"I)I", (void*)jni_next}, + {"_error", "("CPTR_CLASS_PATH")I", (void*)jni_error}, + {"_concat", "("CPTR_CLASS_PATH"I)V", (void*)jni_concat}, + {"_pop", "("CPTR_CLASS_PATH"I)V", (void*)jni_pop}, + {"_setGlobal", "("CPTR_CLASS_PATH""STRING_CLASS_PATH")V", (void*)jni_setGlobal}, + {"_getGlobal", "("CPTR_CLASS_PATH""STRING_CLASS_PATH")V", (void*)jni_getGlobal}, + {"_LdoFile", "("CPTR_CLASS_PATH""STRING_CLASS_PATH")I", (void*)jni_LdoFile}, + {"_LdoString", "("CPTR_CLASS_PATH""STRING_CLASS_PATH")I", (void*)jni_LdoString}, + {"_LgetMetaField", "("CPTR_CLASS_PATH"I"STRING_CLASS_PATH")I", (void*)jni_LgetMetaField}, + {"_LcallMeta", "("CPTR_CLASS_PATH"I"STRING_CLASS_PATH")I", (void*)jni_LcallMeta}, + {"_LargError", "("CPTR_CLASS_PATH"I"STRING_CLASS_PATH")I", (void*)jni_LargError}, + {"_LcheckString", "("CPTR_CLASS_PATH"I)"STRING_CLASS_PATH, (void*)jni_LcheckString}, + {"_LoptString", "("CPTR_CLASS_PATH"I"STRING_CLASS_PATH")"STRING_CLASS_PATH, (void*)jni_LoptString}, + {"_LcheckNumber", "("CPTR_CLASS_PATH"I)D", (void*)jni_LcheckNumber}, + {"_LoptNumber", "("CPTR_CLASS_PATH"ID)D", (void*)jni_LoptNumber}, + {"_LcheckInteger", "("CPTR_CLASS_PATH"I)I", (void*)jni_LcheckInteger}, + {"_LoptInteger", "("CPTR_CLASS_PATH"II)I", (void*)jni_LoptInteger}, + {"_LcheckStack", "("CPTR_CLASS_PATH"I"STRING_CLASS_PATH")V", (void*)jni_LcheckStack}, + {"_LcheckType", "("CPTR_CLASS_PATH"II)V", (void*)jni_LcheckType}, + {"_LcheckAny", "("CPTR_CLASS_PATH"I)V", (void*)jni_LcheckAny}, + {"_LnewMetatable", "("CPTR_CLASS_PATH""STRING_CLASS_PATH")I", (void*)jni_LnewMetatable}, + {"_LgetMetatable", "("CPTR_CLASS_PATH""STRING_CLASS_PATH")V", (void*)jni_LgetMetatable}, + {"_Lwhere", "("CPTR_CLASS_PATH"I)V", (void*)jni_Lwhere}, + {"_Lref", "("CPTR_CLASS_PATH"I)I", (void*)jni_Lref}, + {"_LunRef", "("CPTR_CLASS_PATH"II)V", (void*)jni_LunRef}, + {"_LloadFile", "("CPTR_CLASS_PATH""STRING_CLASS_PATH")I", (void*)jni_LloadFile}, + {"_LloadBuffer", "("CPTR_CLASS_PATH"[BJ"STRING_CLASS_PATH")I", (void*)jni_LloadBuffer}, + {"_LloadString", "("CPTR_CLASS_PATH""STRING_CLASS_PATH")I", (void*)jni_LloadString}, + {"_Lgsub", "("CPTR_CLASS_PATH""STRING_CLASS_PATH""STRING_CLASS_PATH""STRING_CLASS_PATH")"STRING_CLASS_PATH, (void*)jni_Lgsub}, + {"_registryIndex", "()I", (void*)jni_registryIndex}, +}; + +#endif //LUA_JNI_H diff --git a/app/src/main/libs/armeabi-v7a/libluajava.so b/app/src/main/libs/armeabi-v7a/libluajava.so new file mode 100755 index 0000000000000000000000000000000000000000..2bd8d936ac7dcd2c57e4c141ac93aa7097e4d4db GIT binary patch literal 142032 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 literal 0 HcmV?d00001

-LuaJava allows Java components to be accessed from Lua using the same syntax -that is used for accessing Lua`s native objects, without any need for -declarations or any kind of preprocessing. -For this check LuaJava's Lua Reference. -