Commit e593fb8d authored by Vinicius Jarina's avatar Vinicius Jarina
Browse files

Removed local KopiLua

parent 8d677060
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>10.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{23997AB1-C4A3-49BA-A7B5-4C14F97C236B}</ProjectGuid>
<ProjectTypeGuids>{6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<RootNamespace>KopiLua</RootNamespace>
<IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
<AssemblyName>KopiLua</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>True</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>False</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>TRACE;DEBUG;LUA_CORE;_WIN32;LUA_COMPAT_VARARG;LUA_COMPAT_MOD;LUA_COMPAT_GFIND;CATCH_EXCEPTIONS</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>False</ConsolePause>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>True</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>False</ConsolePause>
<DefineConstants>TRACE;LUA_CORE;_WIN32;LUA_COMPAT_VARARG;LUA_COMPAT_MOD;LUA_COMPAT_GFIND;CATCH_EXCEPTIONS</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<Folder Include="printf\" />
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<Compile Include="printf\Tools.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="lapi.cs" />
<Compile Include="lauxlib.cs" />
<Compile Include="lbaselib.cs" />
<Compile Include="lcode.cs" />
<Compile Include="ldblib.cs" />
<Compile Include="ldebug.cs" />
<Compile Include="ldo.cs" />
<Compile Include="ldump.cs" />
<Compile Include="lfunc.cs" />
<Compile Include="lgc.cs" />
<Compile Include="linit.cs" />
<Compile Include="liolib.cs" />
<Compile Include="llex.cs" />
<Compile Include="llimits.cs" />
<Compile Include="lmathlib.cs" />
<Compile Include="lmem.cs" />
<Compile Include="lobject.cs" />
<Compile Include="lopcodes.cs" />
<Compile Include="loslib.cs" />
<Compile Include="lparser.cs" />
<Compile Include="lstate.cs" />
<Compile Include="lstring.cs" />
<Compile Include="lstrlib.cs" />
<Compile Include="ltable.cs" />
<Compile Include="ltablib.cs" />
<Compile Include="ltm.cs" />
<Compile Include="luaconf.cs" />
<Compile Include="lualib.cs" />
<Compile Include="lundump.cs" />
<Compile Include="lvm.cs" />
<Compile Include="lzio.cs" />
<Compile Include="print.cs" />
<Compile Include="loadlib.cs" />
<Compile Include="lua.cs" />
</ItemGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{E8DDBC21-EF74-4ABA-9C49-BFC702BE25D8}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Lua</RootNamespace>
<AssemblyName>KopiLua</AssemblyName>
<ReleaseVersion>2.x</ReleaseVersion>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>True</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>False</Optimize>
<OutputPath>..\..\Run\Debug</OutputPath>
<DefineConstants>TRACE;DEBUG;LUA_CORE;_WIN32;LUA_COMPAT_VARARG;LUA_COMPAT_MOD;LUA_COMPAT_GFIND;CATCH_EXCEPTIONS</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>True</Optimize>
<OutputPath>..\..\Run\Release</OutputPath>
<DefineConstants>TRACE;RELEASE;LUA_CORE;_WIN32;LUA_COMPAT_VARARG;LUA_COMPAT_MOD;LUA_COMPAT_GFIND;CATCH_EXCEPTIONS</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
</ItemGroup>
<ItemGroup>
<Compile Include="lapi.cs" />
<Compile Include="lauxlib.cs" />
<Compile Include="lbaselib.cs" />
<Compile Include="lcode.cs" />
<Compile Include="ldblib.cs" />
<Compile Include="ldebug.cs" />
<Compile Include="ldo.cs" />
<Compile Include="ldump.cs" />
<Compile Include="lfunc.cs" />
<Compile Include="lgc.cs" />
<Compile Include="linit.cs" />
<Compile Include="liolib.cs" />
<Compile Include="llex.cs" />
<Compile Include="llimits.cs" />
<Compile Include="lmathlib.cs" />
<Compile Include="lmem.cs" />
<Compile Include="loadlib.cs" />
<Compile Include="lobject.cs" />
<Compile Include="lopcodes.cs" />
<Compile Include="loslib.cs" />
<Compile Include="lparser.cs" />
<Compile Include="lstate.cs" />
<Compile Include="lstring.cs" />
<Compile Include="lstrlib.cs" />
<Compile Include="ltable.cs" />
<Compile Include="ltablib.cs" />
<Compile Include="ltm.cs" />
<Compile Include="lua.cs" />
<Compile Include="luaconf.cs" />
<Compile Include="lualib.cs" />
<Compile Include="lundump.cs" />
<Compile Include="lvm.cs" />
<Compile Include="lzio.cs" />
<Compile Include="print.cs" />
<Compile Include="printf\Tools.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>Клиентский профиль .NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Установщик Windows 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
EXTRA_DIST =
# Warning: This is an automatically generated file, do not edit!
if ENABLE_DEBUG_X86
ASSEMBLY_COMPILER_COMMAND = dmcs
ASSEMBLY_COMPILER_FLAGS = -noconfig -codepage:utf8 -warn:4 -optimize- -debug "-define:TRACE;DEBUG;LUA_CORE;_WIN32;LUA_COMPAT_VARARG;LUA_COMPAT_MOD;LUA_COMPAT_GFIND;CATCH_EXCEPTIONS"
ASSEMBLY = ../../Run/Debug/KopiLua.dll
ASSEMBLY_MDB = $(ASSEMBLY).mdb
COMPILE_TARGET = library
PROJECT_REFERENCES =
BUILD_DIR = ../../Run/Debug
KOPILUA_DLL_MDB_SOURCE=../../Run/Debug/KopiLua.dll.mdb
KOPILUA_DLL_MDB=$(BUILD_DIR)/KopiLua.dll.mdb
endif
if ENABLE_RELEASE_X86
ASSEMBLY_COMPILER_COMMAND = dmcs
ASSEMBLY_COMPILER_FLAGS = -noconfig -codepage:utf8 -warn:4 -optimize+ "-define:TRACE;RELEASE;LUA_CORE;_WIN32;LUA_COMPAT_VARARG;LUA_COMPAT_MOD;LUA_COMPAT_GFIND;CATCH_EXCEPTIONS"
ASSEMBLY = ../../Run/Release/KopiLua.dll
ASSEMBLY_MDB =
COMPILE_TARGET = library
PROJECT_REFERENCES =
BUILD_DIR = ../../Run/Release
KOPILUA_DLL_MDB=
endif
if ENABLE_DEBUG_X64
ASSEMBLY_COMPILER_COMMAND = dmcs
ASSEMBLY_COMPILER_FLAGS = -noconfig -codepage:utf8 -warn:4 -optimize- -debug "-define:TRACE;DEBUG;LUA_CORE;_WIN32;LUA_COMPAT_VARARG;LUA_COMPAT_MOD;LUA_COMPAT_GFIND;CATCH_EXCEPTIONS"
ASSEMBLY = ../../Run/Debug_x64/KopiLua.dll
ASSEMBLY_MDB = $(ASSEMBLY).mdb
COMPILE_TARGET = library
PROJECT_REFERENCES =
BUILD_DIR = ../../Run/Debug_x64
KOPILUA_DLL_MDB_SOURCE=../../Run/Debug_x64/KopiLua.dll.mdb
KOPILUA_DLL_MDB=$(BUILD_DIR)/KopiLua.dll.mdb
endif
if ENABLE_RELEASE_X64
ASSEMBLY_COMPILER_COMMAND = dmcs
ASSEMBLY_COMPILER_FLAGS = -noconfig -codepage:utf8 -warn:4 -optimize+ "-define:TRACE;RELEASE;LUA_CORE;_WIN32;LUA_COMPAT_VARARG;LUA_COMPAT_MOD;LUA_COMPAT_GFIND;CATCH_EXCEPTIONS"
ASSEMBLY = ../../Run/Release_x64/KopiLua.dll
ASSEMBLY_MDB =
COMPILE_TARGET = library
PROJECT_REFERENCES =
BUILD_DIR = ../../Run/Release_x64
KOPILUA_DLL_MDB=
endif
AL=al
SATELLITE_ASSEMBLY_NAME=$(notdir $(basename $(ASSEMBLY))).resources.dll
PROGRAMFILES = \
$(KOPILUA_DLL_MDB)
LINUX_PKGCONFIG = \
$(KOPILUA_PC)
RESGEN=resgen2
all: $(ASSEMBLY) $(PROGRAMFILES) $(LINUX_PKGCONFIG)
FILES = \
lapi.cs \
lauxlib.cs \
lbaselib.cs \
lcode.cs \
ldblib.cs \
ldebug.cs \
ldo.cs \
ldump.cs \
lfunc.cs \
lgc.cs \
linit.cs \
liolib.cs \
llex.cs \
llimits.cs \
lmathlib.cs \
lmem.cs \
loadlib.cs \
lobject.cs \
lopcodes.cs \
loslib.cs \
lparser.cs \
lstate.cs \
lstring.cs \
lstrlib.cs \
ltable.cs \
ltablib.cs \
ltm.cs \
lua.cs \
luaconf.cs \
lualib.cs \
lundump.cs \
lvm.cs \
lzio.cs \
print.cs \
printf/Tools.cs \
Properties/AssemblyInfo.cs
DATA_FILES =
RESOURCES =
EXTRAS = \
kopilua.pc.in
REFERENCES = \
System \
System.Core \
System.Data.DataSetExtensions \
System.Data
DLL_REFERENCES =
CLEANFILES = $(PROGRAMFILES) $(LINUX_PKGCONFIG)
include $(top_srcdir)/Makefile.include
KOPILUA_PC = $(BUILD_DIR)/kopilua.pc
$(eval $(call emit-deploy-wrapper,KOPILUA_PC,kopilua.pc))
$(eval $(call emit_resgen_targets))
$(build_xamlg_list): %.xaml.g.cs: %.xaml
xamlg '$<'
$(ASSEMBLY_MDB): $(ASSEMBLY)
$(ASSEMBLY): $(build_sources) $(build_resources) $(build_datafiles) $(DLL_REFERENCES) $(PROJECT_REFERENCES) $(build_xamlg_list) $(build_satellite_assembly_list)
mkdir -p $(shell dirname $(ASSEMBLY))
$(ASSEMBLY_COMPILER_COMMAND) $(ASSEMBLY_COMPILER_FLAGS) -out:$(ASSEMBLY) -target:$(COMPILE_TARGET) $(build_sources_embed) $(build_resources_embed) $(build_references_ref)
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("KopiLua")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("KopiLua")]
[assembly: AssemblyCopyright("Copyright © 2009 Mark Feldman")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: CLSCompliantAttribute(true)]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("1a9cd761-692f-40db-8566-c0217e5d3e0a")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
\ No newline at end of file
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Resources;
// Управление общими сведениями о сборке осуществляется с помощью следующего
// набора атрибутов. Измените значения этих атрибутов для изменения
// сведений о сборке.
[assembly: AssemblyTitle("KopiLua_wp7")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("MICROSOFT")]
[assembly: AssemblyProduct("KopiLua_wp7")]
[assembly: AssemblyCopyright("Copyright © 2012 Gerasimov Sergey")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Если для ComVisible установить значение false, типы в этой сборке не будут поддерживаться
// COM-компонентами. При необходимости доступа к какому-либо типу в этой сборке
// из модели COM задайте для атрибута ComVisible этого типа значение true.
[assembly: ComVisible(false)]
// Следующий GUID служит для идентификации библиотеки типов, если данный проект видим для COM
[assembly: Guid("63906a16-e4d0-4ad7-ba8f-cb4d6c29d2d5")]
// Сведения о версии сборки состоят из следующих четырех значений:
//
// Основной номер версии
// Дополнительный номер версии
// Номер построения
// Редакция
//
// Можно указать все значения или задать для номеров редакции и построения значения по умолчанию
// с помощью символа '*', как показано ниже:
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: NeutralResourcesLanguageAttribute("ru-RU")]
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Lua")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Lua")]
[assembly: AssemblyCopyright("Copyright © Mark Feldman 2009")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("42f29687-47be-4860-a332-c7c4c75b7119")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Luac")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Luac")]
[assembly: AssemblyCopyright("Copyright © Mark Feldman 2009")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("403d5192-280f-4171-98e6-c818dd6b9981")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Name: KopiLua
Description: KopiLua
Version: 2.x
Requires:
Libs: -r:@expanded_libdir@/@PACKAGE@/KopiLua.dll
/*
** $Id: lapi.c,v 2.55.1.5 2008/07/04 18:41:18 roberto Exp $
** Lua API
** See Copyright Notice in lua.h
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
namespace KopiLua
{
using lu_mem = System.UInt32;
using TValue = Lua.lua_TValue;
using StkId = Lua.lua_TValue;
using lua_Integer = System.Int32;
using lua_Number = System.Double;
using ptrdiff_t = System.Int32;
using ZIO = Lua.Zio;
public partial class Lua
{
public const string lua_ident =
"$Lua: " + LUA_RELEASE + " " + LUA_COPYRIGHT + " $\n" +
"$Authors: " + LUA_AUTHORS + " $\n" +
"$URL: www.lua.org $\n";
public static void api_checknelems(lua_State L, int n)
{
api_check(L, n <= L.top - L.base_);
}
public static void api_checkvalidindex(lua_State L, StkId i)
{
api_check(L, i != luaO_nilobject);
}
public static void api_incr_top(lua_State L)
{
api_check(L, L.top < L.ci.top);
StkId.inc(ref L.top);
}
static TValue index2adr (lua_State L, int idx) {
if (idx > 0) {
TValue o = L.base_ + (idx - 1);
api_check(L, idx <= L.ci.top - L.base_);
if (o >= L.top) return luaO_nilobject;
else return o;
}
else if (idx > LUA_REGISTRYINDEX) {
api_check(L, idx != 0 && -idx <= L.top - L.base_);
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]
: (TValue)luaO_nilobject;
}
}
}
private static Table getcurrenv (lua_State L) {
if (L.ci == L.base_ci[0]) /* no enclosing function? */
return hvalue(gt(L)); /* use global table as environment */
else {
Closure func = curr_func(L);
return func.c.env;
}
}
public static void luaA_pushobject (lua_State L, TValue o) {
setobj2s(L, L.top, o);
api_incr_top(L);
}
public static int lua_checkstack (lua_State L, int size) {
int res = 1;
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;
}
lua_unlock(L);
return res;
}
public static void lua_xmove (lua_State from, lua_State to, int n) {
int i;
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);
from.top -= n;
for (i = 0; i < n; i++) {
setobj2s(to, StkId.inc(ref to.top), from.top + i);
}
lua_unlock(to);
}
public static void lua_setlevel (lua_State from, lua_State to) {
to.nCcalls = from.nCcalls;
}
public static lua_CFunction lua_atpanic (lua_State L, lua_CFunction panicf) {
lua_CFunction old;
lua_lock(L);
old = G(L).panic;
G(L).panic = panicf;
lua_unlock(L);
return old;
}
public static 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;
}
/*
** basic stack manipulation
*/
public static int lua_gettop (lua_State L) {
return cast_int(L.top - L.base_);
}
public static void lua_settop (lua_State L, int idx) {
lua_lock(L);
if (idx >= 0) {
api_check(L, idx <= L.stack_last - L.base_);
while (L.top < L.base_ + idx)
setnilvalue(StkId.inc(ref L.top));
L.top = L.base_ + idx;
}
else {
api_check(L, -(idx+1) <= (L.top - L.base_));
L.top += idx+1; /* `subtract' index (index is negative) */
}
lua_unlock(L);
}
public static void lua_remove (lua_State L, int idx) {
StkId p;
lua_lock(L);
p = index2adr(L, idx);
api_checkvalidindex(L, p);
while ((p=p[1]) < L.top) setobjs2s(L, p-1, p);
StkId.dec(ref L.top);
lua_unlock(L);
}
public static void lua_insert (lua_State L, int idx) {
StkId p;
StkId q;
lua_lock(L);
p = index2adr(L, idx);
api_checkvalidindex(L, p);
for (q = L.top; q>p; StkId.dec(ref q)) setobjs2s(L, q, q-1);
setobjs2s(L, p, L.top);
lua_unlock(L);
}
public static void lua_replace (lua_State L, int idx) {
StkId o;
lua_lock(L);
/* explicit test for incompatible code */
if (idx == LUA_ENVIRONINDEX && L.ci == L.base_ci[0])
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);
}
StkId.dec(ref L.top);
lua_unlock(L);
}
public static void lua_pushvalue (lua_State L, int idx) {
lua_lock(L);
setobj2s(L, L.top, index2adr(L, idx));
api_incr_top(L);
lua_unlock(L);
}
/*
** access functions (stack . C)
*/
public static int lua_type (lua_State L, int idx) {
StkId o = index2adr(L, idx);
return (o == luaO_nilobject) ? LUA_TNONE : ttype(o);
}
public static CharPtr lua_typename (lua_State L, int t) {
//UNUSED(L);
return (t == LUA_TNONE) ? "no value" : luaT_typenames[t];
}
public static bool lua_iscfunction (lua_State L, int idx) {
StkId o = index2adr(L, idx);
return iscfunction(o);
}
public static int lua_isnumber (lua_State L, int idx) {
TValue n = new TValue();
TValue o = index2adr(L, idx);
return tonumber(ref o, n);
}
public static int lua_isstring (lua_State L, int idx) {
int t = lua_type(L, idx);
return (t == LUA_TSTRING || t == LUA_TNUMBER) ? 1 : 0;
}
public static int lua_isuserdata (lua_State L, int idx) {
TValue o = index2adr(L, idx);
return (ttisuserdata(o) || ttislightuserdata(o)) ? 1 : 0;
}
public static 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);
}
public static 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_unlock(L);
return i;
}
public static int lua_lessthan (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
: luaV_lessthan(L, o1, o2);
lua_unlock(L);
return i;
}
public static lua_Number lua_tonumber (lua_State L, int idx) {
TValue n = new TValue();
TValue o = index2adr(L, idx);
if (tonumber(ref o, n) != 0)
return nvalue(o);
else
return 0;
}
public static lua_Integer lua_tointeger (lua_State L, int idx) {
TValue n = new TValue();
TValue o = index2adr(L, idx);
if (tonumber(ref o, n) != 0) {
lua_Integer res;
lua_Number num = nvalue(o);
lua_number2integer(out res, num);
return res;
}
else
return 0;
}
public static int lua_toboolean (lua_State L, int idx) {
TValue o = index2adr(L, idx);
return (l_isfalse(o) == 0) ? 1 : 0;
}
[CLSCompliantAttribute(false)]
public static CharPtr lua_tolstring (lua_State L, int idx, out uint len) {
StkId o = index2adr(L, idx);
if (!ttisstring(o)) {
lua_lock(L); /* `luaV_tostring' may create a new string */
if (luaV_tostring(L, o)==0) { /* conversion failed? */
len = 0;
lua_unlock(L);
return null;
}
luaC_checkGC(L);
o = index2adr(L, idx); /* previous call may reallocate the stack */
lua_unlock(L);
}
len = tsvalue(o).len;
return svalue(o);
}
[CLSCompliantAttribute(false)]
public static uint lua_objlen (lua_State L, int idx) {
StkId o = index2adr(L, idx);
switch (ttype(o)) {
case LUA_TSTRING: return tsvalue(o).len;
case LUA_TUSERDATA: return uvalue(o).len;
case LUA_TTABLE: return (uint)luaH_getn(hvalue(o));
case LUA_TNUMBER: {
uint l;
lua_lock(L); /* `luaV_tostring' may create a new string */
l = (luaV_tostring(L, o) != 0 ? tsvalue(o).len : 0);
lua_unlock(L);
return l;
}
default: return 0;
}
}
public static lua_CFunction lua_tocfunction (lua_State L, int idx) {
StkId o = index2adr(L, idx);
return (!iscfunction(o)) ? null : clvalue(o).c.f;
}
public static object lua_touserdata (lua_State L, int idx) {
StkId o = index2adr(L, idx);
switch (ttype(o)) {
case LUA_TUSERDATA: return (rawuvalue(o).user_data);
case LUA_TLIGHTUSERDATA: return pvalue(o);
default: return null;
}
}
public static lua_State lua_tothread (lua_State L, int idx) {
StkId o = index2adr(L, idx);
return (!ttisthread(o)) ? null : thvalue(o);
}
public static object lua_topointer (lua_State L, int idx) {
StkId o = index2adr(L, idx);
switch (ttype(o)) {
case LUA_TTABLE: return hvalue(o);
case LUA_TFUNCTION: return clvalue(o);
case LUA_TTHREAD: return thvalue(o);
case LUA_TUSERDATA:
case LUA_TLIGHTUSERDATA:
return lua_touserdata(L, idx);
default: return null;
}
}
/*
** push functions (C . stack)
*/
public static void lua_pushnil (lua_State L) {
lua_lock(L);
setnilvalue(L.top);
api_incr_top(L);
lua_unlock(L);
}
public static void lua_pushnumber (lua_State L, lua_Number n) {
lua_lock(L);
setnvalue(L.top, n);
api_incr_top(L);
lua_unlock(L);
}
public static void lua_pushinteger (lua_State L, lua_Integer n) {
lua_lock(L);
setnvalue(L.top, cast_num(n));
api_incr_top(L);
lua_unlock(L);
}
[CLSCompliantAttribute(false)]
public static void lua_pushlstring (lua_State L, CharPtr s, uint len) {
lua_lock(L);
luaC_checkGC(L);
setsvalue2s(L, L.top, luaS_newlstr(L, s, len));
api_incr_top(L);
lua_unlock(L);
}
public static void lua_pushstring (lua_State L, CharPtr s) {
if (s == null)
lua_pushnil(L);
else
lua_pushlstring(L, s, (uint)strlen(s));
}
public static CharPtr lua_pushvfstring (lua_State L, CharPtr fmt,
object[] argp) {
CharPtr ret;
lua_lock(L);
luaC_checkGC(L);
ret = luaO_pushvfstring(L, fmt, argp);
lua_unlock(L);
return ret;
}
public static CharPtr lua_pushfstring (lua_State L, CharPtr fmt) {
CharPtr ret;
lua_lock(L);
luaC_checkGC(L);
ret = luaO_pushvfstring(L, fmt, null);
lua_unlock(L);
return ret;
}
public static CharPtr lua_pushfstring(lua_State L, CharPtr fmt, params object[] p)
{
CharPtr ret;
lua_lock(L);
luaC_checkGC(L);
ret = luaO_pushvfstring(L, fmt, p);
lua_unlock(L);
return ret;
}
public static 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-- != 0)
setobj2n(L, cl.c.upvalue[n], L.top+n);
setclvalue(L, L.top, cl);
lua_assert(iswhite(obj2gco(cl)));
api_incr_top(L);
lua_unlock(L);
}
public static void lua_pushboolean (lua_State L, int b) {
lua_lock(L);
setbvalue(L.top, (b != 0) ? 1 : 0); /* ensure that true is 1 */
api_incr_top(L);
lua_unlock(L);
}
public static void lua_pushlightuserdata (lua_State L, object p) {
lua_lock(L);
setpvalue(L.top, p);
api_incr_top(L);
lua_unlock(L);
}
public static int lua_pushthread (lua_State L) {
lua_lock(L);
setthvalue(L, L.top, L);
api_incr_top(L);
lua_unlock(L);
return (G(L).mainthread == L) ? 1 : 0;
}
/*
** get functions (Lua . stack)
*/
public static void lua_gettable (lua_State L, int idx) {
StkId t;
lua_lock(L);
t = index2adr(L, idx);
api_checkvalidindex(L, t);
luaV_gettable(L, t, L.top - 1, L.top - 1);
lua_unlock(L);
}
public static void lua_getfield (lua_State L, int idx, CharPtr k) {
StkId t;
TValue key = new TValue();
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);
lua_unlock(L);
}
public static void lua_rawget (lua_State L, int idx) {
StkId t;
lua_lock(L);
t = index2adr(L, idx);
api_check(L, ttistable(t));
setobj2s(L, L.top - 1, luaH_get(hvalue(t), L.top - 1));
lua_unlock(L);
}
public static void lua_rawgeti (lua_State L, int idx, int n) {
StkId o;
lua_lock(L);
o = index2adr(L, idx);
api_check(L, ttistable(o));
setobj2s(L, L.top, luaH_getnum(hvalue(o), n));
api_incr_top(L);
lua_unlock(L);
}
public static void lua_createtable (lua_State L, int narray, int nrec) {
lua_lock(L);
luaC_checkGC(L);
sethvalue(L, L.top, luaH_new(L, narray, nrec));
api_incr_top(L);
lua_unlock(L);
}
public static int lua_getmetatable (lua_State L, int objindex) {
TValue obj;
Table mt = null;
int res;
lua_lock(L);
obj = index2adr(L, objindex);
switch (ttype(obj)) {
case LUA_TTABLE:
mt = hvalue(obj).metatable;
break;
case LUA_TUSERDATA:
mt = uvalue(obj).metatable;
break;
default:
mt = G(L).mt[ttype(obj)];
break;
}
if (mt == null)
res = 0;
else {
sethvalue(L, L.top, mt);
api_incr_top(L);
res = 1;
}
lua_unlock(L);
return res;
}
public static void lua_getfenv (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;
}
api_incr_top(L);
lua_unlock(L);
}
/*
** set functions (stack . Lua)
*/
public static 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);
luaV_settable(L, t, L.top - 2, L.top - 1);
L.top -= 2; /* pop index and value */
lua_unlock(L);
}
public static void lua_setfield (lua_State L, int idx, CharPtr k) {
StkId t;
TValue key = new TValue();
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);
StkId.dec(ref L.top); /* pop value */
lua_unlock(L);
}
public static void lua_rawset (lua_State L, int idx) {
StkId t;
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);
L.top -= 2;
lua_unlock(L);
}
public static void lua_rawseti (lua_State L, int idx, int 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);
StkId.dec(ref L.top);
lua_unlock(L);
}
public static int lua_setmetatable (lua_State L, int objindex) {
TValue obj;
Table mt;
lua_lock(L);
api_checknelems(L, 1);
obj = index2adr(L, objindex);
api_checkvalidindex(L, obj);
if (ttisnil(L.top - 1))
mt = null;
else {
api_check(L, ttistable(L.top - 1));
mt = hvalue(L.top - 1);
}
switch (ttype(obj)) {
case LUA_TTABLE: {
hvalue(obj).metatable = mt;
if (mt != null)
luaC_objbarriert(L, hvalue(obj), mt);
break;
}
case LUA_TUSERDATA: {
uvalue(obj).metatable = mt;
if (mt != null)
luaC_objbarrier(L, rawuvalue(obj), mt);
break;
}
default: {
G(L).mt[ttype(obj)] = mt;
break;
}
}
StkId.dec(ref L.top);
lua_unlock(L);
return 1;
}
public static int lua_setfenv (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 != 0) luaC_objbarrier(L, gcvalue(o), hvalue(L.top - 1));
StkId.dec(ref L.top);
lua_unlock(L);
return res;
}
/*
** `load' and `call' functions (run Lua code)
*/
public static void adjustresults(lua_State L, int nres) {
if (nres == LUA_MULTRET && L.top >= L.ci.top)
L.ci.top = L.top;
}
public static void checkresults(lua_State L, int na, int nr) {
api_check(L, (nr) == LUA_MULTRET || (L.ci.top - L.top >= (nr) - (na)));
}
public static void lua_call (lua_State L, int nargs, int nresults) {
StkId func;
lua_lock(L);
api_checknelems(L, nargs+1);
checkresults(L, nargs, nresults);
func = L.top - (nargs+1);
luaD_call(L, func, nresults);
adjustresults(L, nresults);
lua_unlock(L);
}
/*
** Execute a protected call.
*/
public class CallS { /* data to `f_call' */
public StkId func;
public int nresults;
};
static void f_call (lua_State L, object ud) {
CallS c = ud as CallS;
luaD_call(L, c.func, c.nresults);
}
public static int lua_pcall (lua_State L, int nargs, int nresults, int errfunc) {
CallS c = new CallS();
int status;
ptrdiff_t func;
lua_lock(L);
api_checknelems(L, nargs+1);
checkresults(L, nargs, nresults);
if (errfunc == 0)
func = 0;
else {
StkId o = index2adr(L, errfunc);
api_checkvalidindex(L, 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);
adjustresults(L, nresults);
lua_unlock(L);
return status;
}
/*
** Execute a protected C call.
*/
public class CCallS { /* data to `f_Ccall' */
public lua_CFunction func;
public object ud;
};
static void f_Ccall (lua_State L, object ud) {
CCallS c = ud as CCallS;
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);
}
public static int lua_cpcall (lua_State L, lua_CFunction func, object ud) {
CCallS c = new CCallS();
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;
}
[CLSCompliantAttribute(false)]
public static int lua_load (lua_State L, lua_Reader reader, object data,
CharPtr chunkname) {
ZIO z = new ZIO();
int status;
lua_lock(L);
if (chunkname == null) chunkname = "?";
luaZ_init(L, z, reader, data);
status = luaD_protectedparser(L, z, chunkname);
lua_unlock(L);
return status;
}
[CLSCompliantAttribute(false)]
public static int lua_dump (lua_State L, lua_Writer writer, object data) {
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);
else
status = 1;
lua_unlock(L);
return status;
}
public static int lua_status (lua_State L) {
return L.status;
}
/*
** Garbage-collection function
*/
public static int lua_gc (lua_State L, int what, int data) {
int res = 0;
global_State g;
lua_lock(L);
g = G(L);
switch (what) {
case LUA_GCSTOP: {
g.GCthreshold = MAX_LUMEM;
break;
}
case LUA_GCRESTART: {
g.GCthreshold = g.totalbytes;
break;
}
case LUA_GCCOLLECT: {
luaC_fullgc(L);
break;
}
case LUA_GCCOUNT: {
/* GC values are expressed in Kbytes: #bytes/2^10 */
res = cast_int(g.totalbytes >> 10);
break;
}
case LUA_GCCOUNTB: {
res = cast_int(g.totalbytes & 0x3ff);
break;
}
case LUA_GCSTEP: {
lu_mem a = ((lu_mem)data << 10);
if (a <= g.totalbytes)
g.GCthreshold = (uint)(g.totalbytes - a);
else
g.GCthreshold = 0;
while (g.GCthreshold <= g.totalbytes) {
luaC_step(L);
if (g.gcstate == GCSpause) { /* end of cycle? */
res = 1; /* signal it */
break;
}
}
break;
}
case LUA_GCSETPAUSE: {
res = g.gcpause;
g.gcpause = data;
break;
}
case LUA_GCSETSTEPMUL: {
res = g.gcstepmul;
g.gcstepmul = data;
break;
}
default:
res = -1; /* invalid option */
break;
}
lua_unlock(L);
return res;
}
/*
** miscellaneous functions
*/
public static int lua_error (lua_State L) {
lua_lock(L);
api_checknelems(L, 1);
luaG_errormsg(L);
lua_unlock(L);
return 0; /* to avoid warnings */
}
public static int lua_next (lua_State L, int idx) {
StkId t;
int more;
lua_lock(L);
t = index2adr(L, idx);
api_check(L, ttistable(t));
more = luaH_next(L, hvalue(t), L.top - 1);
if (more != 0) {
api_incr_top(L);
}
else /* no more elements */
StkId.dec(ref L.top); /* remove key */
lua_unlock(L);
return more;
}
public static 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);
}
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 */
lua_unlock(L);
}
public static lua_Alloc lua_getallocf (lua_State L, ref object ud) {
lua_Alloc f;
lua_lock(L);
if (ud != null) ud = G(L).ud;
f = G(L).frealloc;
lua_unlock(L);
return f;
}
public static void lua_setallocf (lua_State L, lua_Alloc f, object ud) {
lua_lock(L);
G(L).ud = ud;
G(L).frealloc = f;
lua_unlock(L);
}
[CLSCompliantAttribute(false)]
public static object lua_newuserdata(lua_State L, uint size)
{
Udata u;
lua_lock(L);
luaC_checkGC(L);
u = luaS_newudata(L, size, getcurrenv(L));
setuvalue(L, L.top, u);
api_incr_top(L);
lua_unlock(L);
return u.user_data;
}
// this one is used internally only
internal static object lua_newuserdata(lua_State L, Type t)
{
Udata u;
lua_lock(L);
luaC_checkGC(L);
u = luaS_newudata(L, t, getcurrenv(L));
setuvalue(L, L.top, u);
api_incr_top(L);
lua_unlock(L);
return u.user_data;
}
static CharPtr aux_upvalue (StkId fi, int n, ref TValue val) {
Closure f;
if (!ttisfunction(fi)) return null;
f = clvalue(fi);
if (f.c.isC != 0) {
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]);
}
}
public static CharPtr lua_getupvalue (lua_State L, int funcindex, int n) {
CharPtr name;
TValue val = new TValue();
lua_lock(L);
name = aux_upvalue(index2adr(L, funcindex), n, ref val);
if (name != null) {
setobj2s(L, L.top, val);
api_incr_top(L);
}
lua_unlock(L);
return name;
}
public static CharPtr lua_setupvalue (lua_State L, int funcindex, int n) {
CharPtr name;
TValue val = new TValue();
StkId fi;
lua_lock(L);
fi = index2adr(L, funcindex);
api_checknelems(L, 1);
name = aux_upvalue(fi, n, ref val);
if (name != null) {
StkId.dec(ref L.top);
setobj(L, val, L.top);
luaC_barrier(L, clvalue(fi), L.top);
}
lua_unlock(L);
return name;
}
}
}
/*
** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
#define lauxlib_c
#define LUA_LIB
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace KopiLua
{
using lua_Number = System.Double;
using lua_Integer = System.Int32;
public partial class Lua
{
#if LUA_COMPAT_GETN
public static int luaL_getn(lua_State L, int t);
public static void luaL_setn(lua_State L, int t, int n);
#else
public static int luaL_getn(lua_State L, int i) {return (int)lua_objlen(L, i);}
public static void luaL_setn(lua_State L, int i, int j) {} /* no op! */
#endif
#if LUA_COMPAT_OPENLIB
//#define luaI_openlib luaL_openlib
#endif
/* extra error code for `luaL_load' */
public const int LUA_ERRFILE = (LUA_ERRERR+1);
public class luaL_Reg {
public luaL_Reg(CharPtr name, lua_CFunction func) {
this.name = name;
this.func = func;
}
public CharPtr name;
public lua_CFunction func;
};
/*
** ===============================================================
** some useful macros
** ===============================================================
*/
public static void luaL_argcheck(lua_State L, bool cond, int numarg, string extramsg) {
if (!cond)
luaL_argerror(L, numarg, extramsg);
}
public static CharPtr luaL_checkstring(lua_State L, int n) { return luaL_checklstring(L, n); }
public static CharPtr luaL_optstring(lua_State L, int n, CharPtr d) { uint len; return luaL_optlstring(L, n, d, out len); }
public static int luaL_checkint(lua_State L, int n) {return (int)luaL_checkinteger(L, n);}
public static int luaL_optint(lua_State L, int n, lua_Integer d) {return (int)luaL_optinteger(L, n, d);}
public static long luaL_checklong(lua_State L, int n) {return luaL_checkinteger(L, n);}
public static long luaL_optlong(lua_State L, int n, lua_Integer d) {return luaL_optinteger(L, n, d);}
public static CharPtr luaL_typename(lua_State L, int i) {return lua_typename(L, lua_type(L,i));}
//#define luaL_dofile(L, fn) \
// (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
//#define luaL_dostring(L, s) \
// (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
public static void luaL_getmetatable(lua_State L, CharPtr n) { lua_getfield(L, LUA_REGISTRYINDEX, n); }
public delegate lua_Number luaL_opt_delegate (lua_State L, int narg);
public static lua_Number luaL_opt(lua_State L, luaL_opt_delegate f, int n, lua_Number d) {
return lua_isnoneornil(L, (n != 0) ? d : f(L, n)) ? 1 : 0;}
public delegate lua_Integer luaL_opt_delegate_integer(lua_State L, int narg);
public static lua_Integer luaL_opt_integer(lua_State L, luaL_opt_delegate_integer f, int n, lua_Number d) {
return (lua_Integer)(lua_isnoneornil(L, n) ? d : f(L, (n)));
}
/*
** {======================================================
** Generic Buffer manipulation
** =======================================================
*/
public class luaL_Buffer {
public int p; /* current position in buffer */
public int lvl; /* number of strings in the stack (level) */
public lua_State L;
public CharPtr buffer = new char[LUAL_BUFFERSIZE];
};
public static void luaL_addchar(luaL_Buffer B, char c) {
if (B.p >= LUAL_BUFFERSIZE)
luaL_prepbuffer(B);
B.buffer[B.p++] = c;
}
///* compatibility only */
public static void luaL_putchar(luaL_Buffer B, char c) {luaL_addchar(B,c);}
public static void luaL_addsize(luaL_Buffer B, int n) {B.p += n;}
/* }====================================================== */
/* compatibility with ref system */
/* pre-defined references */
public const int LUA_NOREF = (-2);
public const int LUA_REFNIL = (-1);
//#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \
// (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0))
//#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref))
//#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref))
//#define luaL_reg luaL_Reg
/* 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
public const int FREELIST_REF = 0; /* free list of references */
/* convert a stack index to positive */
public static int abs_index(lua_State L, int i)
{
return ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : lua_gettop(L) + (i) + 1);
}
/*
** {======================================================
** Error-report functions
** =======================================================
*/
public static int luaL_argerror (lua_State L, int narg, CharPtr extramsg) {
lua_Debug ar = new lua_Debug();
if (lua_getstack(L, 0, ar)==0) /* no stack frame? */
return luaL_error(L, "bad argument #%d (%s)", narg, 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 ({1})",
ar.name, extramsg);
}
if (ar.name == null)
ar.name = "?";
return luaL_error(L, "bad argument #%d to " + LUA_QS + " (%s)",
narg, ar.name, extramsg);
}
public static int luaL_typerror (lua_State L, int narg, CharPtr tname) {
CharPtr msg = lua_pushfstring(L, "%s expected, got %s",
tname, luaL_typename(L, narg));
return luaL_argerror(L, narg, msg);
}
private static void tag_error (lua_State L, int narg, int tag) {
luaL_typerror(L, narg, lua_typename(L, tag));
}
public static void luaL_where (lua_State L, int level) {
lua_Debug ar = new lua_Debug();
if (lua_getstack(L, level, ar) != 0) { /* check function at level */
lua_getinfo(L, "Sl", ar); /* get info about it */
if (ar.currentline > 0) { /* is there info? */
lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline);
return;
}
}
lua_pushliteral(L, ""); /* else, no information available... */
}
public static int luaL_error(lua_State L, CharPtr fmt, params object[] p)
{
luaL_where(L, 1);
lua_pushvfstring(L, fmt, p);
lua_concat(L, 2);
return lua_error(L);
}
/* }====================================================== */
public static int luaL_checkoption (lua_State L, int narg, CharPtr def,
CharPtr [] lst) {
CharPtr name = (def != null) ? luaL_optstring(L, narg, def) :
luaL_checkstring(L, narg);
int i;
for (i=0; i<lst.Length; i++)
if (strcmp(lst[i], name)==0)
return i;
return luaL_argerror(L, narg,
lua_pushfstring(L, "invalid option " + LUA_QS, name));
}
public static int luaL_newmetatable (lua_State L, CharPtr 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;
}
public static object luaL_checkudata (lua_State L, int ud, CharPtr tname) {
object p = lua_touserdata(L, ud);
if (p != null) { /* value is a userdata? */
if (lua_getmetatable(L, ud) != 0) { /* does it have a metatable? */
lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
if (lua_rawequal(L, -1, -2) != 0) { /* does it have the correct mt? */
lua_pop(L, 2); /* remove both metatables */
return p;
}
}
}
luaL_typerror(L, ud, tname); /* else error */
return null; /* to avoid warnings */
}
public static void luaL_checkstack (lua_State L, int space, CharPtr mes) {
if (lua_checkstack(L, space) == 0)
luaL_error(L, "stack overflow (%s)", mes);
}
public static void luaL_checktype (lua_State L, int narg, int t) {
if (lua_type(L, narg) != t)
tag_error(L, narg, t);
}
public static void luaL_checkany (lua_State L, int narg) {
if (lua_type(L, narg) == LUA_TNONE)
luaL_argerror(L, narg, "value expected");
}
public static CharPtr luaL_checklstring(lua_State L, int narg) {uint len; return luaL_checklstring(L, narg, out len);}
[CLSCompliantAttribute(false)]
public static CharPtr luaL_checklstring (lua_State L, int narg, out uint len) {
CharPtr s = lua_tolstring(L, narg, out len);
if (s==null) tag_error(L, narg, LUA_TSTRING);
return s;
}
public static CharPtr luaL_optlstring (lua_State L, int narg, CharPtr def) {
uint len; return luaL_optlstring (L, narg, def, out len); }
[CLSCompliantAttribute(false)]
public static CharPtr luaL_optlstring (lua_State L, int narg, CharPtr def, out uint len) {
if (lua_isnoneornil(L, narg)) {
len = (uint)((def != null) ? strlen(def) : 0);
return def;
}
else return luaL_checklstring(L, narg, out len);
}
public static lua_Number luaL_checknumber (lua_State L, int narg) {
lua_Number d = lua_tonumber(L, narg);
if ((d == 0) && (lua_isnumber(L, narg)==0)) /* avoid extra test when d is not 0 */
tag_error(L, narg, LUA_TNUMBER);
return d;
}
public static lua_Number luaL_optnumber (lua_State L, int narg, lua_Number def) {
return luaL_opt(L, luaL_checknumber, narg, def);
}
public static lua_Integer luaL_checkinteger (lua_State L, int narg) {
lua_Integer d = lua_tointeger(L, narg);
if (d == 0 && lua_isnumber(L, narg)==0) /* avoid extra test when d is not 0 */
tag_error(L, narg, LUA_TNUMBER);
return d;
}
public static lua_Integer luaL_optinteger (lua_State L, int narg, lua_Integer def) {
return luaL_opt_integer(L, luaL_checkinteger, narg, def);
}
public static int luaL_getmetafield (lua_State L, int obj, CharPtr event_) {
if (lua_getmetatable(L, obj)==0) /* 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;
}
}
public static int luaL_callmeta (lua_State L, int obj, CharPtr event_) {
obj = abs_index(L, obj);
if (luaL_getmetafield(L, obj, event_)==0) /* no metafield? */
return 0;
lua_pushvalue(L, obj);
lua_call(L, 1, 1);
return 1;
}
public static void luaL_register(lua_State L, CharPtr libname,
luaL_Reg[] l) {
luaI_openlib(L, libname, l, 0);
}
// we could just take the .Length member here, but let's try
// to keep it as close to the C implementation as possible.
private static int libsize (luaL_Reg[] l) {
int size = 0;
for (; l[size].name!=null; size++);
return size;
}
public static void luaI_openlib (lua_State L, CharPtr libname,
luaL_Reg[] l, int nup) {
if (libname!=null) {
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 */
}
int reg_num = 0;
for (; l[reg_num].name!=null; reg_num++) {
int i;
for (i=0; i<nup; i++) /* copy upvalues to the top */
lua_pushvalue(L, -nup);
lua_pushcclosure(L, l[reg_num].func, nup);
lua_setfield(L, -(nup+2), l[reg_num].name);
}
lua_pop(L, nup); /* remove upvalues */
}
/*
** {======================================================
** getn-setn: size for arrays
** =======================================================
*/
#if 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;
}
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 */
}
}
public static 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' */
}
}
public static 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);
}
#endif
/* }====================================================== */
public static CharPtr luaL_gsub (lua_State L, CharPtr s, CharPtr p,
CharPtr r) {
CharPtr wild;
uint l = (uint)strlen(p);
luaL_Buffer b = new luaL_Buffer();
luaL_buffinit(L, b);
while ((wild = strstr(s, p)) != null) {
luaL_addlstring(b, s, (uint)(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);
}
public static CharPtr luaL_findtable (lua_State L, int idx,
CharPtr fname, int szhint) {
CharPtr e;
lua_pushvalue(L, idx);
do {
e = strchr(fname, '.');
if (e == null) e = fname + strlen(fname);
lua_pushlstring(L, fname, (uint)(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, (uint)(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;
}
/*
** {======================================================
** Generic Buffer manipulation
** =======================================================
*/
private static int bufflen(luaL_Buffer B) {return B.p;}
private static int bufffree(luaL_Buffer B) {return LUAL_BUFFERSIZE - bufflen(B);}
public const int LIMIT = LUA_MINSTACK / 2;
private static int emptybuffer (luaL_Buffer B) {
uint l = (uint)bufflen(B);
if (l == 0) return 0; /* put nothing on stack */
else {
lua_pushlstring(B.L, B.buffer, l);
B.p = 0;
B.lvl++;
return 1;
}
}
private static void adjuststack (luaL_Buffer B) {
if (B.lvl > 1) {
lua_State L = B.L;
int toget = 1; /* number of levels to concat */
uint toplen = lua_strlen(L, -1);
do {
uint 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;
}
}
public static CharPtr luaL_prepbuffer (luaL_Buffer B) {
if (emptybuffer(B) != 0)
adjuststack(B);
return new CharPtr(B.buffer, B.p);
}
[CLSCompliantAttribute(false)]
public static void luaL_addlstring (luaL_Buffer B, CharPtr s, uint l) {
while (l-- != 0)
{
char c = s[0];
s = s.next();
luaL_addchar(B, c);
}
}
public static void luaL_addstring (luaL_Buffer B, CharPtr s) {
luaL_addlstring(B, s, (uint)strlen(s));
}
public static void luaL_pushresult (luaL_Buffer B) {
emptybuffer(B);
lua_concat(B.L, B.lvl);
B.lvl = 1;
}
public static void luaL_addvalue (luaL_Buffer B) {
lua_State L = B.L;
uint vl;
CharPtr s = lua_tolstring(L, -1, out vl);
if (vl <= bufffree(B)) { /* fit into buffer? */
CharPtr dst = new CharPtr(B.buffer.chars, B.buffer.index + B.p);
CharPtr src = new CharPtr(s.chars, s.index);
for (uint i = 0; i < vl; i++)
dst[i] = src[i];
B.p += (int)vl;
lua_pop(L, 1); /* remove from stack */
}
else {
if (emptybuffer(B) != 0)
lua_insert(L, -2); /* put buffer before new value */
B.lvl++; /* add new value into B stack */
adjuststack(B);
}
}
public static void luaL_buffinit (lua_State L, luaL_Buffer B) {
B.L = L;
B.p = /*B.buffer*/ 0;
B.lvl = 0;
}
/* }====================================================== */
public static 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 */
}
lua_rawgeti(L, t, FREELIST_REF); /* get first free element */
ref_ = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */
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, ref_);
return ref_;
}
public static 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] */
lua_pushinteger(L, ref_);
lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */
}
}
/*
** {======================================================
** Load functions
** =======================================================
*/
public class LoadF {
public int extraline;
public Stream f;
public CharPtr buff = new char[LUAL_BUFFERSIZE];
};
[CLSCompliantAttribute(false)]
public static CharPtr getF (lua_State L, object ud, out uint size) {
size = 0;
LoadF lf = (LoadF)ud;
//(void)L;
if (lf.extraline != 0) {
lf.extraline = 0;
size = 1;
return "\n";
}
if (feof(lf.f) != 0) return null;
size = (uint)fread(lf.buff, 1, lf.buff.chars.Length, lf.f);
return (size > 0) ? new CharPtr(lf.buff) : null;
}
private static int errfile (lua_State L, CharPtr what, int fnameindex) {
CharPtr serr = strerror(errno());
CharPtr filename = lua_tostring(L, fnameindex) + 1;
lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr);
lua_remove(L, fnameindex);
return LUA_ERRFILE;
}
public static int luaL_loadfile (lua_State L, CharPtr filename) {
LoadF lf = new LoadF();
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;
}
else {
lua_pushfstring(L, "@%s", 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 (c == LUA_SIGNATURE[0] && (filename!=null)) { /* 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;
}
ungetc(c, lf.f);
status = lua_load(L, getF, lf, lua_tostring(L, -1));
readstatus = ferror(lf.f);
if (filename != null) fclose(lf.f); /* close file (even in case of errors) */
if (readstatus != 0) {
lua_settop(L, fnameindex); /* ignore results from `lua_load' */
return errfile(L, "read", fnameindex);
}
lua_remove(L, fnameindex);
return status;
}
public class LoadS {
public CharPtr s;
[CLSCompliantAttribute(false)]
public uint size;
};
static CharPtr getS (lua_State L, object ud, out uint size) {
LoadS ls = (LoadS)ud;
//(void)L;
//if (ls.size == 0) return null;
size = ls.size;
ls.size = 0;
return ls.s;
}
[CLSCompliantAttribute(false)]
public static int luaL_loadbuffer(lua_State L, CharPtr buff, uint size,
CharPtr name) {
LoadS ls = new LoadS();
ls.s = new CharPtr(buff);
ls.size = size;
return lua_load(L, getS, ls, name);
}
public static int luaL_loadstring(lua_State L, CharPtr s) {
return luaL_loadbuffer(L, s, (uint)strlen(s), s);
}
/* }====================================================== */
private static object l_alloc (Type t) {
return System.Activator.CreateInstance(t);
}
private 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;
}
public static lua_State luaL_newstate()
{
lua_State L = lua_newstate(l_alloc, null);
if (L != null) lua_atpanic(L, panic);
return L;
}
}
}
/*
** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $
** Basic library
** See Copyright Notice in lua.h
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace KopiLua
{
using lua_Number = System.Double;
public partial class Lua
{
/*
** 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).
*/
private 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++) {
CharPtr s;
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 */
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);
lua_pop(L, 1); /* pop result */
}
Console.Write("\n", stdout);
return 0;
}
private static int luaB_tonumber (lua_State L) {
int base_ = luaL_optint(L, 2, 10);
if (base_ == 10) { /* standard conversion */
luaL_checkany(L, 1);
if (lua_isnumber(L, 1) != 0) {
lua_pushnumber(L, lua_tonumber(L, 1));
return 1;
}
}
else {
CharPtr s1 = luaL_checkstring(L, 1);
CharPtr s2;
ulong n;
luaL_argcheck(L, 2 <= base_ && base_ <= 36, 2, "base out of range");
n = strtoul(s1, out s2, base_);
if (s1 != s2) { /* at least one valid digit? */
while (isspace((byte)(s2[0]))) s2 = s2.next(); /* skip trailing spaces */
if (s2[0] == '\0') { /* no invalid trailing characters? */
lua_pushnumber(L, (lua_Number)n);
return 1;
}
}
}
lua_pushnil(L); /* else not a number */
return 1;
}
private static int luaB_error (lua_State L) {
int level = luaL_optint(L, 2, 1);
lua_settop(L, 1);
if ((lua_isstring(L, 1)!=0) && (level > 0)) { /* add extra information? */
luaL_where(L, level);
lua_pushvalue(L, 1);
lua_concat(L, 2);
}
return lua_error(L);
}
private static int luaB_getmetatable (lua_State L) {
luaL_checkany(L, 1);
if (lua_getmetatable(L, 1)==0) {
lua_pushnil(L);
return 1; /* no metatable */
}
luaL_getmetafield(L, 1, "__metatable");
return 1; /* returns either __metatable field (if present) or metatable */
}
private static int luaB_setmetatable (lua_State L) {
int t = lua_type(L, 2);
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") != 0)
luaL_error(L, "cannot change a protected metatable");
lua_settop(L, 2);
lua_setmetatable(L, 1);
return 1;
}
private static void getfunc (lua_State L, int opt) {
if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);
else {
lua_Debug ar = new lua_Debug();
int level = (opt != 0) ? 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);
}
}
private 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;
}
private 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)!=0) && (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;
}
private static int luaB_rawequal (lua_State L) {
luaL_checkany(L, 1);
luaL_checkany(L, 2);
lua_pushboolean(L, lua_rawequal(L, 1, 2));
return 1;
}
private static int luaB_rawget (lua_State L) {
luaL_checktype(L, 1, LUA_TTABLE);
luaL_checkany(L, 2);
lua_settop(L, 2);
lua_rawget(L, 1);
return 1;
}
private static int luaB_rawset (lua_State L) {
luaL_checktype(L, 1, LUA_TTABLE);
luaL_checkany(L, 2);
luaL_checkany(L, 3);
lua_settop(L, 3);
lua_rawset(L, 1);
return 1;
}
private static int luaB_gcinfo (lua_State L) {
lua_pushinteger(L, lua_getgccount(L));
return 1;
}
public static readonly CharPtr[] opts = {"stop", "restart", "collect",
"count", "step", "setpause", "setstepmul", null};
public readonly static int[] optsnum = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL};
private static int luaB_collectgarbage (lua_State L) {
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]) {
case LUA_GCCOUNT: {
int b = lua_gc(L, LUA_GCCOUNTB, 0);
lua_pushnumber(L, res + ((lua_Number)b/1024));
return 1;
}
case LUA_GCSTEP: {
lua_pushboolean(L, res);
return 1;
}
default: {
lua_pushnumber(L, res);
return 1;
}
}
}
private static int luaB_type (lua_State L) {
luaL_checkany(L, 1);
lua_pushstring(L, luaL_typename(L, 1));
return 1;
}
private 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 */
if (lua_next(L, 1) != 0)
return 2;
else {
lua_pushnil(L);
return 1;
}
}
private 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;
}
private static int ipairsaux (lua_State L) {
int i = luaL_checkint(L, 2);
luaL_checktype(L, 1, LUA_TTABLE);
i++; /* next value */
lua_pushinteger(L, i);
lua_rawgeti(L, 1, i);
return (lua_isnil(L, -1)) ? 0 : 2;
}
private 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 */
return 3;
}
private static int load_aux (lua_State L, int status) {
if (status == 0) /* OK? */
return 1;
else {
lua_pushnil(L);
lua_insert(L, -2); /* put before error message */
return 2; /* return nil plus error message */
}
}
private static int luaB_loadstring (lua_State L) {
uint l;
CharPtr s = luaL_checklstring(L, 1, out l);
CharPtr chunkname = luaL_optstring(L, 2, s);
return load_aux(L, luaL_loadbuffer(L, s, l, chunkname));
}
private static int luaB_loadfile (lua_State L) {
CharPtr fname = luaL_optstring(L, 1, null);
return load_aux(L, luaL_loadfile(L, fname));
}
/*
** 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.
*/
private static CharPtr generic_reader (lua_State L, object ud, out uint size) {
//(void)ud; /* to avoid warnings */
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)) {
size = 0;
return null;
}
else if (lua_isstring(L, -1) != 0)
{
lua_replace(L, 3); /* save string in a reserved stack slot */
return lua_tolstring(L, 3, out size);
}
else
{
size = 0;
luaL_error(L, "reader function must return a string");
}
return null; /* to avoid warnings */
}
private static int luaB_load (lua_State L) {
int status;
CharPtr 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);
}
private static int luaB_dofile (lua_State L) {
CharPtr 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;
}
private static int luaB_assert (lua_State L) {
luaL_checkany(L, 1);
if (lua_toboolean(L, 1)==0)
return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
return lua_gettop(L);
}
private 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_integer(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)==0)) /* 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;
}
private static int luaB_select (lua_State L) {
int n = lua_gettop(L);
if (lua_type(L, 1) == LUA_TSTRING && lua_tostring(L, 1)[0] == '#') {
lua_pushinteger(L, n-1);
return 1;
}
else {
int i = luaL_checkint(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;
}
}
private 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) ? 1 : 0);
lua_insert(L, 1);
return lua_gettop(L); /* return status + all results */
}
private 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) ? 1 : 0);
lua_replace(L, 1);
return lua_gettop(L); /* return status + all results */
}
private static int luaB_tostring (lua_State L) {
luaL_checkany(L, 1);
if (luaL_callmeta(L, 1, "__tostring") != 0) /* 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) != 0 ? "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;
}
private 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) != 0) {
lua_rawget(L, lua_upvalueindex(1));
validproxy = lua_toboolean(L, -1);
lua_pop(L, 1); /* remove value */
}
luaL_argcheck(L, validproxy!=0, 1, "boolean or proxy expected");
lua_getmetatable(L, 1); /* metatable is valid; get it */
}
lua_setmetatable(L, 2);
return 1;
}
private readonly static luaL_Reg[] base_funcs = {
new luaL_Reg("assert", luaB_assert),
new luaL_Reg("collectgarbage", luaB_collectgarbage),
new luaL_Reg("dofile", luaB_dofile),
new luaL_Reg("error", luaB_error),
new luaL_Reg("gcinfo", luaB_gcinfo),
new luaL_Reg("getfenv", luaB_getfenv),
new luaL_Reg("getmetatable", luaB_getmetatable),
new luaL_Reg("loadfile", luaB_loadfile),
new luaL_Reg("load", luaB_load),
new luaL_Reg("loadstring", luaB_loadstring),
new luaL_Reg("next", luaB_next),
new luaL_Reg("pcall", luaB_pcall),
new luaL_Reg("print", luaB_print),
new luaL_Reg("rawequal", luaB_rawequal),
new luaL_Reg("rawget", luaB_rawget),
new luaL_Reg("rawset", luaB_rawset),
new luaL_Reg("select", luaB_select),
new luaL_Reg("setfenv", luaB_setfenv),
new luaL_Reg("setmetatable", luaB_setmetatable),
new luaL_Reg("tonumber", luaB_tonumber),
new luaL_Reg("tostring", luaB_tostring),
new luaL_Reg("type", luaB_type),
new luaL_Reg("unpack", luaB_unpack),
new luaL_Reg("xpcall", luaB_xpcall),
new luaL_Reg(null, null)
};
/*
** {======================================================
** Coroutine library
** =======================================================
*/
public const int CO_RUN = 0; /* running */
public const int CO_SUS = 1; /* suspended */
public const int CO_NOR = 2; /* 'normal' (it resumed another coroutine) */
public const int CO_DEAD = 3;
private static readonly string[] statnames =
{"running", "suspended", "normal", "dead"};
private 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 = new lua_Debug();
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;
}
}
private static int luaB_costatus (lua_State L) {
lua_State co = lua_tothread(L, 1);
luaL_argcheck(L, co!=null, 1, "coroutine expected");
lua_pushstring(L, statnames[costatus(L, co)]);
return 1;
}
private static int auxresume (lua_State L, lua_State co, int narg) {
int status = costatus(L, co);
if (lua_checkstack(co, narg)==0)
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)==0)
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 */
}
}
private static int luaB_coresume (lua_State L) {
lua_State co = lua_tothread(L, 1);
int r;
luaL_argcheck(L, co!=null, 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 */
}
}
private 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) != 0) { /* 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;
}
private 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;
}
private static int luaB_cowrap (lua_State L) {
luaB_cocreate(L);
lua_pushcclosure(L, luaB_auxwrap, 1);
return 1;
}
private static int luaB_yield (lua_State L) {
return lua_yield(L, lua_gettop(L));
}
private static int luaB_corunning (lua_State L) {
if (lua_pushthread(L) != 0)
lua_pushnil(L); /* main thread is not a coroutine */
return 1;
}
private readonly static luaL_Reg[] co_funcs = {
new luaL_Reg("create", luaB_cocreate),
new luaL_Reg("resume", luaB_coresume),
new luaL_Reg("running", luaB_corunning),
new luaL_Reg("status", luaB_costatus),
new luaL_Reg("wrap", luaB_cowrap),
new luaL_Reg("yield", luaB_yield),
new luaL_Reg(null, null)
};
/* }====================================================== */
private static void auxopen (lua_State L, CharPtr name,
lua_CFunction f, lua_CFunction u) {
lua_pushcfunction(L, u);
lua_pushcclosure(L, f, 1);
lua_setfield(L, -2, name);
}
private static void base_open (lua_State L) {
/* set global _G */
lua_pushvalue(L, LUA_GLOBALSINDEX);
lua_setglobal(L, "_G");
/* open lib into global table */
luaL_register(L, "_G", base_funcs);
lua_pushliteral(L, LUA_VERSION);
lua_setglobal(L, "_VERSION"); /* set global _VERSION */
/* `ipairs' and `pairs' need auxliliary 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' */
}
public static int luaopen_base (lua_State L) {
base_open(L);
luaL_register(L, LUA_COLIBNAME, co_funcs);
return 2;
}
}
}
/*
** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $
** Code generator for Lua
** See Copyright Notice in lua.h
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
namespace KopiLua
{
using TValue = Lua.lua_TValue;
using lua_Number = System.Double;
using Instruction = System.UInt32;
public class InstructionPtr
{
[CLSCompliantAttribute(false)]
public Instruction[] codes;
public int pc;
public InstructionPtr() { this.codes = null; ; this.pc = -1; }
[CLSCompliantAttribute(false)]
public InstructionPtr(Instruction[] codes, int pc) {
this.codes = codes; this.pc = pc; }
public static InstructionPtr Assign(InstructionPtr ptr)
{
if (ptr == null) return null;
return new InstructionPtr(ptr.codes, ptr.pc);
}
[CLSCompliantAttribute(false)]
public Instruction this[int index]
{
get { return this.codes[pc + index]; }
set { this.codes[pc + index] = value; }
}
public static InstructionPtr inc(ref InstructionPtr ptr)
{
InstructionPtr result = new InstructionPtr(ptr.codes, ptr.pc);
ptr.pc++;
return result;
}
public static InstructionPtr dec(ref InstructionPtr ptr)
{
InstructionPtr result = new InstructionPtr(ptr.codes, ptr.pc);
ptr.pc--;
return result;
}
public static bool operator <(InstructionPtr p1, InstructionPtr p2)
{
Debug.Assert(p1.codes == p2.codes);
return p1.pc < p2.pc;
}
public static bool operator >(InstructionPtr p1, InstructionPtr p2)
{
Debug.Assert(p1.codes == p2.codes);
return p1.pc > p2.pc;
}
public static bool operator <=(InstructionPtr p1, InstructionPtr p2)
{
Debug.Assert(p1.codes == p2.codes);
return p1.pc < p2.pc;
}
public static bool operator >=(InstructionPtr p1, InstructionPtr p2)
{
Debug.Assert(p1.codes == p2.codes);
return p1.pc > p2.pc;
}
};
public partial class Lua
{
/*
** Marks the end of a patch list. It is an invalid value both as an absolute
** address, and as a list link (would link an element to itself).
*/
public const int NO_JUMP = (-1);
/*
** grep "ORDER OPR" if you change these enums
*/
public enum BinOpr {
OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW,
OPR_CONCAT,
OPR_NE, OPR_EQ,
OPR_LT, OPR_LE, OPR_GT, OPR_GE,
OPR_AND, OPR_OR,
OPR_NOBINOPR
};
public enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR };
public static InstructionPtr getcode(FuncState fs, expdesc e) {return new InstructionPtr(fs.f.code, e.u.s.info);}
public static int luaK_codeAsBx(FuncState fs, OpCode o, int A, int sBx) {return luaK_codeABx(fs,o,A,sBx+MAXARG_sBx);}
public static void luaK_setmultret(FuncState fs, expdesc e) {luaK_setreturns(fs, e, LUA_MULTRET);}
public static bool hasjumps(expdesc e) {return e.t != e.f;}
private static int isnumeral(expdesc e) {
return (e.k == expkind.VKNUM && e.t == NO_JUMP && e.f == NO_JUMP) ? 1 : 0;
}
public static void luaK_nil (FuncState fs, int from, int n) {
InstructionPtr previous;
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 = new InstructionPtr(fs.f.code, fs.pc-1);
if (GET_OPCODE(previous) == OpCode.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;
}
}
}
}
luaK_codeABC(fs, OpCode.OP_LOADNIL, from, from + n - 1, 0); /* else no optimization */
}
public static int luaK_jump (FuncState fs) {
int jpc = fs.jpc; /* save list of jumps to here */
int j;
fs.jpc = NO_JUMP;
j = luaK_codeAsBx(fs, OpCode.OP_JMP, 0, NO_JUMP);
luaK_concat(fs, ref j, jpc); /* keep them on hold */
return j;
}
public static void luaK_ret (FuncState fs, int first, int nret) {
luaK_codeABC(fs, OpCode.OP_RETURN, first, nret + 1, 0);
}
private static int condjump (FuncState fs, OpCode op, int A, int B, int C) {
luaK_codeABC(fs, op, A, B, C);
return luaK_jump(fs);
}
private static void fixjump (FuncState fs, int pc, int dest) {
InstructionPtr jmp = new InstructionPtr(fs.f.code, pc);
int offset = dest-(pc+1);
lua_assert(dest != NO_JUMP);
if (Math.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
** optimizations with consecutive instructions not in the same basic block).
*/
public static int luaK_getlabel (FuncState fs) {
fs.lasttarget = fs.pc;
return fs.pc;
}
private 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 */
}
private static InstructionPtr getjumpcontrol (FuncState fs, int pc) {
InstructionPtr pi = new InstructionPtr(fs.f.code, pc);
if (pc >= 1 && (testTMode(GET_OPCODE(pi[-1]))!=0))
return new InstructionPtr(pi.codes, pi.pc-1);
else
return new InstructionPtr(pi.codes, pi.pc);
}
/*
** check whether list has any jump that do not produce a value
** (or produce an inverted value)
*/
private static int need_value (FuncState fs, int list) {
for (; list != NO_JUMP; list = getjump(fs, list)) {
InstructionPtr i = getjumpcontrol(fs, list);
if (GET_OPCODE(i[0]) != OpCode.OP_TESTSET) return 1;
}
return 0; /* not found */
}
private static int patchtestreg (FuncState fs, int node, int reg) {
InstructionPtr i = getjumpcontrol(fs, node);
if (GET_OPCODE(i[0]) != OpCode.OP_TESTSET)
return 0; /* cannot patch other instructions */
if (reg != NO_REG && reg != GETARG_B(i[0]))
SETARG_A(i, reg);
else /* no register to put value or register already has the value */
i[0] = (uint)CREATE_ABC(OpCode.OP_TEST, GETARG_B(i[0]), 0, GETARG_C(i[0]));
return 1;
}
private static void removevalues (FuncState fs, int list) {
for (; list != NO_JUMP; list = getjump(fs, list))
patchtestreg(fs, list, NO_REG);
}
private static void patchlistaux (FuncState fs, int list, int vtarget, int reg,
int dtarget) {
while (list != NO_JUMP) {
int next = getjump(fs, list);
if (patchtestreg(fs, list, reg) != 0)
fixjump(fs, list, vtarget);
else
fixjump(fs, list, dtarget); /* jump to default target */
list = next;
}
}
private static void dischargejpc (FuncState fs) {
patchlistaux(fs, fs.jpc, fs.pc, NO_REG, fs.pc);
fs.jpc = NO_JUMP;
}
public static void luaK_patchlist (FuncState fs, int list, int target) {
if (target == fs.pc)
luaK_patchtohere(fs, list);
else {
lua_assert(target < fs.pc);
patchlistaux(fs, list, target, NO_REG, target);
}
}
public static void luaK_patchtohere (FuncState fs, int list) {
luaK_getlabel(fs);
luaK_concat(fs, ref fs.jpc, list);
}
public static void luaK_concat(FuncState fs, ref int l1, int l2)
{
if (l2 == NO_JUMP) return;
else if (l1 == NO_JUMP)
l1 = l2;
else {
int list = l1;
int next;
while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */
list = next;
fixjump(fs, list, l2);
}
}
public static 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");
fs.f.maxstacksize = cast_byte(newstack);
}
}
public static void luaK_reserveregs (FuncState fs, int n) {
luaK_checkstack(fs, n);
fs.freereg += n;
}
private static void freereg (FuncState fs, int reg) {
if ((ISK(reg)==0) && reg >= fs.nactvar) {
fs.freereg--;
lua_assert(reg == fs.freereg);
}
}
private static void freeexp (FuncState fs, expdesc e) {
if (e.k == expkind.VNONRELOC)
freereg(fs, e.u.s.info);
}
private 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));
}
else { /* constant not found; create a new entry */
setnvalue(idx, cast_num(fs.nk));
luaM_growvector(L, ref f.k, fs.nk, ref f.sizek,
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++;
}
}
public static int luaK_stringK (FuncState fs, TString s) {
TValue o = new TValue();
setsvalue(fs.L, o, s);
return addk(fs, o, o);
}
public static int luaK_numberK (FuncState fs, lua_Number r) {
TValue o = new TValue();
setnvalue(o, r);
return addk(fs, o, o);
}
private static int boolK (FuncState fs, int b) {
TValue o = new TValue();
setbvalue(o, b);
return addk(fs, o, o);
}
private static int nilK (FuncState fs) {
TValue k = new TValue(), v = new TValue();
setnilvalue(v);
/* cannot use nil as key; instead use table itself to represent nil */
sethvalue(fs.L, k, fs.h);
return addk(fs, k, v);
}
public static void luaK_setreturns (FuncState fs, expdesc e, int nresults) {
if (e.k == expkind.VCALL) { /* expression is an open function call? */
SETARG_C(getcode(fs, e), nresults+1);
}
else if (e.k == expkind.VVARARG) {
SETARG_B(getcode(fs, e), nresults+1);
SETARG_A(getcode(fs, e), fs.freereg);
luaK_reserveregs(fs, 1);
}
}
public static void luaK_setoneret (FuncState fs, expdesc e) {
if (e.k == expkind.VCALL) { /* expression is an open function call? */
e.k = expkind.VNONRELOC;
e.u.s.info = GETARG_A(getcode(fs, e));
}
else if (e.k == expkind.VVARARG) {
SETARG_B(getcode(fs, e), 2);
e.k = expkind.VRELOCABLE; /* can relocate its simple result */
}
}
public static void luaK_dischargevars (FuncState fs, expdesc e) {
switch (e.k) {
case expkind.VLOCAL: {
e.k = expkind.VNONRELOC;
break;
}
case expkind.VUPVAL: {
e.u.s.info = luaK_codeABC(fs, OpCode.OP_GETUPVAL, 0, e.u.s.info, 0);
e.k = expkind.VRELOCABLE;
break;
}
case expkind.VGLOBAL: {
e.u.s.info = luaK_codeABx(fs, OpCode.OP_GETGLOBAL, 0, e.u.s.info);
e.k = expkind.VRELOCABLE;
break;
}
case expkind.VINDEXED: {
freereg(fs, e.u.s.aux);
freereg(fs, e.u.s.info);
e.u.s.info = luaK_codeABC(fs, OpCode.OP_GETTABLE, 0, e.u.s.info, e.u.s.aux);
e.k = expkind.VRELOCABLE;
break;
}
case expkind.VVARARG:
case expkind.VCALL: {
luaK_setoneret(fs, e);
break;
}
default: break; /* there is one value available (somewhere) */
}
}
private 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, OpCode.OP_LOADBOOL, A, b, jump);
}
private static void discharge2reg (FuncState fs, expdesc e, int reg) {
luaK_dischargevars(fs, e);
switch (e.k) {
case expkind.VNIL: {
luaK_nil(fs, reg, 1);
break;
}
case expkind.VFALSE: case expkind.VTRUE: {
luaK_codeABC(fs, OpCode.OP_LOADBOOL, reg, (e.k == expkind.VTRUE) ? 1 : 0, 0);
break;
}
case expkind.VK: {
luaK_codeABx(fs, OpCode.OP_LOADK, reg, e.u.s.info);
break;
}
case expkind.VKNUM: {
luaK_codeABx(fs, OpCode.OP_LOADK, reg, luaK_numberK(fs, e.u.nval));
break;
}
case expkind.VRELOCABLE: {
InstructionPtr pc = getcode(fs, e);
SETARG_A(pc, reg);
break;
}
case expkind.VNONRELOC: {
if (reg != e.u.s.info)
luaK_codeABC(fs, OpCode.OP_MOVE, reg, e.u.s.info, 0);
break;
}
default: {
lua_assert(e.k == expkind.VVOID || e.k == expkind.VJMP);
return; /* nothing to do... */
}
}
e.u.s.info = reg;
e.k = expkind.VNONRELOC;
}
private static void discharge2anyreg (FuncState fs, expdesc e) {
if (e.k != expkind.VNONRELOC) {
luaK_reserveregs(fs, 1);
discharge2reg(fs, e, fs.freereg-1);
}
}
private static void exp2reg (FuncState fs, expdesc e, int reg) {
discharge2reg(fs, e, reg);
if (e.k == expkind.VJMP)
luaK_concat(fs, ref e.t, e.u.s.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)!=0 || need_value(fs, e.f)!=0) {
int fj = (e.k == expkind.VJMP) ? NO_JUMP : luaK_jump(fs);
p_f = code_label(fs, reg, 0, 1);
p_t = code_label(fs, reg, 1, 0);
luaK_patchtohere(fs, fj);
}
final = luaK_getlabel(fs);
patchlistaux(fs, e.f, final, reg, p_f);
patchlistaux(fs, e.t, final, reg, p_t);
}
e.f = e.t = NO_JUMP;
e.u.s.info = reg;
e.k = expkind.VNONRELOC;
}
public static void luaK_exp2nextreg (FuncState fs, expdesc e) {
luaK_dischargevars(fs, e);
freeexp(fs, e);
luaK_reserveregs(fs, 1);
exp2reg(fs, e, fs.freereg - 1);
}
public static int luaK_exp2anyreg (FuncState fs, expdesc e) {
luaK_dischargevars(fs, e);
if (e.k == expkind.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;
}
}
luaK_exp2nextreg(fs, e); /* default */
return e.u.s.info;
}
public static void luaK_exp2val (FuncState fs, expdesc e) {
if (hasjumps(e))
luaK_exp2anyreg(fs, e);
else
luaK_dischargevars(fs, e);
}
public static int luaK_exp2RK (FuncState fs, expdesc e) {
luaK_exp2val(fs, e);
switch (e.k) {
case expkind.VKNUM:
case expkind.VTRUE:
case expkind.VFALSE:
case expkind.VNIL: {
if (fs.nk <= MAXINDEXRK) { /* constant fit in RK operand? */
e.u.s.info = (e.k == expkind.VNIL) ? nilK(fs) :
(e.k == expkind.VKNUM) ? luaK_numberK(fs, e.u.nval) :
boolK(fs, (e.k == expkind.VTRUE) ? 1 : 0);
e.k = expkind.VK;
return RKASK(e.u.s.info);
}
else break;
}
case expkind.VK: {
if (e.u.s.info <= MAXINDEXRK) /* constant fit in argC? */
return RKASK(e.u.s.info);
else break;
}
default: break;
}
/* not a constant in the right range: put it in a register */
return luaK_exp2anyreg(fs, e);
}
public static void luaK_storevar (FuncState fs, expdesc var, expdesc ex) {
switch (var.k) {
case expkind.VLOCAL: {
freeexp(fs, ex);
exp2reg(fs, ex, var.u.s.info);
return;
}
case expkind.VUPVAL: {
int e = luaK_exp2anyreg(fs, ex);
luaK_codeABC(fs, OpCode.OP_SETUPVAL, e, var.u.s.info, 0);
break;
}
case expkind.VGLOBAL: {
int e = luaK_exp2anyreg(fs, ex);
luaK_codeABx(fs, OpCode.OP_SETGLOBAL, e, var.u.s.info);
break;
}
case expkind.VINDEXED: {
int e = luaK_exp2RK(fs, ex);
luaK_codeABC(fs, OpCode.OP_SETTABLE, var.u.s.info, var.u.s.aux, e);
break;
}
default: {
lua_assert(0); /* invalid var kind to store */
break;
}
}
freeexp(fs, ex);
}
public static void luaK_self (FuncState fs, expdesc e, expdesc key) {
int func;
luaK_exp2anyreg(fs, e);
freeexp(fs, e);
func = fs.freereg;
luaK_reserveregs(fs, 2);
luaK_codeABC(fs, OpCode.OP_SELF, func, e.u.s.info, luaK_exp2RK(fs, key));
freeexp(fs, key);
e.u.s.info = func;
e.k = expkind.VNONRELOC;
}
private static void invertjump (FuncState fs, expdesc e) {
InstructionPtr pc = getjumpcontrol(fs, e.u.s.info);
lua_assert(testTMode(GET_OPCODE(pc[0])) != 0 && GET_OPCODE(pc[0]) != OpCode.OP_TESTSET &&
GET_OPCODE(pc[0]) != OpCode.OP_TEST);
SETARG_A(pc, (GETARG_A(pc[0]) == 0) ? 1 : 0);
}
private static int jumponcond (FuncState fs, expdesc e, int cond) {
if (e.k == expkind.VRELOCABLE) {
InstructionPtr ie = getcode(fs, e);
if (GET_OPCODE(ie) == OpCode.OP_NOT) {
fs.pc--; /* remove previous OpCode.OP_NOT */
return condjump(fs, OpCode.OP_TEST, GETARG_B(ie), 0, (cond==0) ? 1 : 0);
}
/* else go through */
}
discharge2anyreg(fs, e);
freeexp(fs, e);
return condjump(fs, OpCode.OP_TESTSET, NO_REG, e.u.s.info, cond);
}
public static void luaK_goiftrue (FuncState fs, expdesc e) {
int pc; /* pc of last jump */
luaK_dischargevars(fs, e);
switch (e.k) {
case expkind.VK: case expkind.VKNUM: case expkind.VTRUE: {
pc = NO_JUMP; /* always true; do nothing */
break;
}
case expkind.VFALSE: {
pc = luaK_jump(fs); /* always jump */
break;
}
case expkind.VJMP: {
invertjump(fs, e);
pc = e.u.s.info;
break;
}
default: {
pc = jumponcond(fs, e, 0);
break;
}
}
luaK_concat(fs, ref e.f, pc); /* insert last jump in `f' list */
luaK_patchtohere(fs, e.t);
e.t = NO_JUMP;
}
private static void luaK_goiffalse (FuncState fs, expdesc e) {
int pc; /* pc of last jump */
luaK_dischargevars(fs, e);
switch (e.k) {
case expkind.VNIL: case expkind.VFALSE: {
pc = NO_JUMP; /* always false; do nothing */
break;
}
case expkind.VTRUE: {
pc = luaK_jump(fs); /* always jump */
break;
}
case expkind.VJMP: {
pc = e.u.s.info;
break;
}
default: {
pc = jumponcond(fs, e, 1);
break;
}
}
luaK_concat(fs, ref e.t, pc); /* insert last jump in `t' list */
luaK_patchtohere(fs, e.f);
e.f = NO_JUMP;
}
private static void codenot (FuncState fs, expdesc e) {
luaK_dischargevars(fs, e);
switch (e.k) {
case expkind.VNIL: case expkind.VFALSE: {
e.k = expkind.VTRUE;
break;
}
case expkind.VK: case expkind.VKNUM: case expkind.VTRUE: {
e.k = expkind.VFALSE;
break;
}
case expkind.VJMP: {
invertjump(fs, e);
break;
}
case expkind.VRELOCABLE:
case expkind.VNONRELOC: {
discharge2anyreg(fs, e);
freeexp(fs, e);
e.u.s.info = luaK_codeABC(fs, OpCode.OP_NOT, 0, e.u.s.info, 0);
e.k = expkind.VRELOCABLE;
break;
}
default: {
lua_assert(0); /* cannot happen */
break;
}
}
/* interchange true and false lists */
{ int temp = e.f; e.f = e.t; e.t = temp; }
removevalues(fs, e.f);
removevalues(fs, e.t);
}
public static void luaK_indexed (FuncState fs, expdesc t, expdesc k) {
t.u.s.aux = luaK_exp2RK(fs, k);
t.k = expkind.VINDEXED;
}
private static int constfolding (OpCode op, expdesc e1, expdesc e2) {
lua_Number v1, v2, r;
if ((isnumeral(e1)==0) || (isnumeral(e2)==0)) return 0;
v1 = e1.u.nval;
v2 = e2.u.nval;
switch (op) {
case OpCode.OP_ADD: r = luai_numadd(v1, v2); break;
case OpCode.OP_SUB: r = luai_numsub(v1, v2); break;
case OpCode.OP_MUL: r = luai_nummul(v1, v2); break;
case OpCode.OP_DIV:
if (v2 == 0) return 0; /* do not attempt to divide by 0 */
r = luai_numdiv(v1, v2); break;
case OpCode.OP_MOD:
if (v2 == 0) return 0; /* do not attempt to divide by 0 */
r = luai_nummod(v1, v2); break;
case OpCode.OP_POW: r = luai_numpow(v1, v2); break;
case OpCode.OP_UNM: r = luai_numunm(v1); break;
case OpCode.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;
}
private static void codearith (FuncState fs, OpCode op, expdesc e1, expdesc e2) {
if (constfolding(op, e1, e2) != 0)
return;
else {
int o2 = (op != OpCode.OP_UNM && op != OpCode.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 = expkind.VRELOCABLE;
}
}
private 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 != OpCode.OP_EQ) {
int temp; /* exchange args to replace by `<' or `<=' */
temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */
cond = 1;
}
e1.u.s.info = condjump(fs, op, cond, o1, o2);
e1.k = expkind.VJMP;
}
public static void luaK_prefix (FuncState fs, UnOpr op, expdesc e) {
expdesc e2 = new expdesc();
e2.t = e2.f = NO_JUMP; e2.k = expkind.VKNUM; e2.u.nval = 0;
switch (op) {
case UnOpr.OPR_MINUS: {
if (isnumeral(e)==0)
luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */
codearith(fs, OpCode.OP_UNM, e, e2);
break;
}
case UnOpr.OPR_NOT: codenot(fs, e); break;
case UnOpr.OPR_LEN: {
luaK_exp2anyreg(fs, e); /* cannot operate on constants */
codearith(fs, OpCode.OP_LEN, e, e2);
break;
}
default: lua_assert(0); break;
}
}
public static void luaK_infix (FuncState fs, BinOpr op, expdesc v) {
switch (op) {
case BinOpr.OPR_AND: {
luaK_goiftrue(fs, v);
break;
}
case BinOpr.OPR_OR: {
luaK_goiffalse(fs, v);
break;
}
case BinOpr.OPR_CONCAT: {
luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */
break;
}
case BinOpr.OPR_ADD: case BinOpr.OPR_SUB: case BinOpr.OPR_MUL: case BinOpr.OPR_DIV:
case BinOpr.OPR_MOD: case BinOpr.OPR_POW: {
if ((isnumeral(v)==0)) luaK_exp2RK(fs, v);
break;
}
default: {
luaK_exp2RK(fs, v);
break;
}
}
}
public static void luaK_posfix (FuncState fs, BinOpr op, expdesc e1, expdesc e2) {
switch (op) {
case BinOpr.OPR_AND: {
lua_assert(e1.t == NO_JUMP); /* list must be closed */
luaK_dischargevars(fs, e2);
luaK_concat(fs, ref e2.f, e1.f);
e1.Copy(e2);
break;
}
case BinOpr.OPR_OR: {
lua_assert(e1.f == NO_JUMP); /* list must be closed */
luaK_dischargevars(fs, e2);
luaK_concat(fs, ref e2.t, e1.t);
e1.Copy(e2);
break;
}
case BinOpr.OPR_CONCAT: {
luaK_exp2val(fs, e2);
if (e2.k == expkind.VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OpCode.OP_CONCAT) {
lua_assert(e1.u.s.info == GETARG_B(getcode(fs, e2))-1);
freeexp(fs, e1);
SETARG_B(getcode(fs, e2), e1.u.s.info);
e1.k = expkind.VRELOCABLE; e1.u.s.info = e2.u.s.info;
}
else {
luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */
codearith(fs, OpCode.OP_CONCAT, e1, e2);
}
break;
}
case BinOpr.OPR_ADD: codearith(fs, OpCode.OP_ADD, e1, e2); break;
case BinOpr.OPR_SUB: codearith(fs, OpCode.OP_SUB, e1, e2); break;
case BinOpr.OPR_MUL: codearith(fs, OpCode.OP_MUL, e1, e2); break;
case BinOpr.OPR_DIV: codearith(fs, OpCode.OP_DIV, e1, e2); break;
case BinOpr.OPR_MOD: codearith(fs, OpCode.OP_MOD, e1, e2); break;
case BinOpr.OPR_POW: codearith(fs, OpCode.OP_POW, e1, e2); break;
case BinOpr.OPR_EQ: codecomp(fs, OpCode.OP_EQ, 1, e1, e2); break;
case BinOpr.OPR_NE: codecomp(fs, OpCode.OP_EQ, 0, e1, e2); break;
case BinOpr.OPR_LT: codecomp(fs, OpCode.OP_LT, 1, e1, e2); break;
case BinOpr.OPR_LE: codecomp(fs, OpCode.OP_LE, 1, e1, e2); break;
case BinOpr.OPR_GT: codecomp(fs, OpCode.OP_LT, 0, e1, e2); break;
case BinOpr.OPR_GE: codecomp(fs, OpCode.OP_LE, 0, e1, e2); break;
default: lua_assert(0); break;
}
}
public static void luaK_fixline (FuncState fs, int line) {
fs.f.lineinfo[fs.pc - 1] = line;
}
private static int luaK_code (FuncState fs, int i, int line) {
Proto f = fs.f;
dischargejpc(fs); /* `pc' will change */
/* put new instruction in code array */
luaM_growvector(fs.L, ref f.code, fs.pc, ref f.sizecode,
MAX_INT, "code size overflow");
f.code[fs.pc] = (uint)i;
/* save corresponding line information */
luaM_growvector(fs.L, ref f.lineinfo, fs.pc, ref f.sizelineinfo,
MAX_INT, "code size overflow");
f.lineinfo[fs.pc] = line;
return fs.pc++;
}
public static int luaK_codeABC (FuncState fs, OpCode o, int a, int b, int c) {
lua_assert(getOpMode(o) == OpMode.iABC);
lua_assert(getBMode(o) != OpArgMask.OpArgN || b == 0);
lua_assert(getCMode(o) != OpArgMask.OpArgN || c == 0);
return luaK_code(fs, CREATE_ABC(o, a, b, c), fs.ls.lastline);
}
public static int luaK_codeABx (FuncState fs, OpCode o, int a, int bc) {
lua_assert(getOpMode(o) == OpMode.iABx || getOpMode(o) == OpMode.iAsBx);
lua_assert(getCMode(o) == OpArgMask.OpArgN);
return luaK_code(fs, CREATE_ABx(o, a, bc), fs.ls.lastline);
}
public static 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);
if (c <= MAXARG_C)
luaK_codeABC(fs, OpCode.OP_SETLIST, base_, b, c);
else {
luaK_codeABC(fs, OpCode.OP_SETLIST, base_, b, 0);
luaK_code(fs, c, fs.ls.lastline);
}
fs.freereg = base_ + 1; /* free registers with list values */
}
}
}
/*
** $Id: ldblib.c,v 1.104.1.3 2008/01/21 13:11:21 roberto Exp $
** Interface from Lua to its debug API
** See Copyright Notice in lua.h
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace KopiLua
{
public partial class Lua
{
private static int db_getregistry (lua_State L) {
lua_pushvalue(L, LUA_REGISTRYINDEX);
return 1;
}
private static int db_getmetatable (lua_State L) {
luaL_checkany(L, 1);
if (lua_getmetatable(L, 1) == 0) {
lua_pushnil(L); /* no metatable */
}
return 1;
}
private static int db_setmetatable (lua_State L) {
int t = lua_type(L, 2);
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;
}
private static int db_getfenv (lua_State L) {
lua_getfenv(L, 1);
return 1;
}
private static int db_setfenv (lua_State L) {
luaL_checktype(L, 2, LUA_TTABLE);
lua_settop(L, 2);
if (lua_setfenv(L, 1) == 0)
luaL_error(L, LUA_QL("setfenv") +
" cannot change environment of given object");
return 1;
}
private static void settabss (lua_State L, CharPtr i, CharPtr v) {
lua_pushstring(L, v);
lua_setfield(L, -2, i);
}
private static void settabsi (lua_State L, CharPtr i, int v) {
lua_pushinteger(L, v);
lua_setfield(L, -2, i);
}
private static lua_State getthread (lua_State L, out int arg) {
if (lua_isthread(L, 1)) {
arg = 1;
return lua_tothread(L, 1);
}
else {
arg = 0;
return L;
}
}
private static void treatstackoption (lua_State L, lua_State L1, CharPtr fname) {
if (L == L1) {
lua_pushvalue(L, -2);
lua_remove(L, -3);
}
else
lua_xmove(L1, L, 1);
lua_setfield(L, -2, fname);
}
private static int db_getinfo (lua_State L) {
lua_Debug ar = new lua_Debug();
int arg;
lua_State L1 = getthread(L, out arg);
CharPtr options = luaL_optstring(L, arg+2, "flnSu");
if (lua_isnumber(L, arg+1) != 0) {
if (lua_getstack(L1, (int)lua_tointeger(L, arg+1), ar)==0) {
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)==0)
return luaL_argerror(L, arg+2, "invalid option");
lua_createtable(L, 0, 2);
if (strchr(options, 'S') != null) {
settabss(L, "source", ar.source);
settabss(L, "short_src", ar.short_src);
settabsi(L, "linedefined", ar.linedefined);
settabsi(L, "lastlinedefined", ar.lastlinedefined);
settabss(L, "what", ar.what);
}
if (strchr(options, 'l') != null)
settabsi(L, "currentline", ar.currentline);
if (strchr(options, 'u') != null)
settabsi(L, "nups", ar.nups);
if (strchr(options, 'n') != null) {
settabss(L, "name", ar.name);
settabss(L, "namewhat", ar.namewhat);
}
if (strchr(options, 'L') != null)
treatstackoption(L, L1, "activelines");
if (strchr(options, 'f') != null)
treatstackoption(L, L1, "func");
return 1; /* return table */
}
private static int db_getlocal (lua_State L) {
int arg;
lua_State L1 = getthread(L, out arg);
lua_Debug ar = new lua_Debug();
CharPtr name;
if (lua_getstack(L1, luaL_checkint(L, arg+1), ar)==0) /* 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 != null) {
lua_xmove(L1, L, 1);
lua_pushstring(L, name);
lua_pushvalue(L, -2);
return 2;
}
else {
lua_pushnil(L);
return 1;
}
}
private static int db_setlocal (lua_State L) {
int arg;
lua_State L1 = getthread(L, out arg);
lua_Debug ar = new lua_Debug();
if (lua_getstack(L1, luaL_checkint(L, arg+1), ar)==0) /* out of range? */
return luaL_argerror(L, arg+1, "level out of range");
luaL_checkany(L, arg+3);
lua_settop(L, arg+3);
lua_xmove(L, L1, 1);
lua_pushstring(L, lua_setlocal(L1, ar, luaL_checkint(L, arg+2)));
return 1;
}
private static int auxupvalue (lua_State L, int get) {
CharPtr 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 */
name = (get!=0) ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
if (name == null) return 0;
lua_pushstring(L, name);
lua_insert(L, -(get+1));
return get + 1;
}
private static int db_getupvalue (lua_State L) {
return auxupvalue(L, 1);
}
private static int db_setupvalue (lua_State L) {
luaL_checkany(L, 3);
return auxupvalue(L, 0);
}
private const string KEY_HOOK = "h";
private static readonly string[] hooknames =
{"call", "return", "line", "count", "tail return"};
private static void hookf (lua_State L, lua_Debug ar) {
lua_pushlightuserdata(L, 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_]);
if (ar.currentline >= 0)
lua_pushinteger(L, ar.currentline);
else lua_pushnil(L);
lua_assert(lua_getinfo(L, "lS", ar));
lua_call(L, 2, 0);
}
}
private static int makemask (CharPtr smask, int count) {
int mask = 0;
if (strchr(smask, 'c') != null) mask |= LUA_MASKCALL;
if (strchr(smask, 'r') != null) mask |= LUA_MASKRET;
if (strchr(smask, 'l') != null) mask |= LUA_MASKLINE;
if (count > 0) mask |= LUA_MASKCOUNT;
return mask;
}
private static CharPtr unmakemask (int mask, CharPtr smask) {
int i = 0;
if ((mask & LUA_MASKCALL) != 0) smask[i++] = 'c';
if ((mask & LUA_MASKRET) != 0) smask[i++] = 'r';
if ((mask & LUA_MASKLINE) != 0) smask[i++] = 'l';
smask[i] = '\0';
return smask;
}
private static void gethooktable (lua_State L) {
lua_pushlightuserdata(L, KEY_HOOK);
lua_rawget(L, LUA_REGISTRYINDEX);
if (!lua_istable(L, -1)) {
lua_pop(L, 1);
lua_createtable(L, 0, 1);
lua_pushlightuserdata(L, KEY_HOOK);
lua_pushvalue(L, -2);
lua_rawset(L, LUA_REGISTRYINDEX);
}
}
private static int db_sethook (lua_State L) {
int arg, mask, count;
lua_Hook func;
lua_State L1 = getthread(L, out arg);
if (lua_isnoneornil(L, arg+1)) {
lua_settop(L, arg+1);
func = null; mask = 0; count = 0; /* turn off hooks */
}
else {
CharPtr smask = luaL_checkstring(L, arg+2);
luaL_checktype(L, arg+1, LUA_TFUNCTION);
count = luaL_optint(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 */
return 0;
}
private static int db_gethook (lua_State L) {
int arg;
lua_State L1 = getthread(L, out arg);
CharPtr buff = new char[5];
int mask = lua_gethookmask(L1);
lua_Hook hook = lua_gethook(L1);
if (hook != null && hook != hookf) /* external hook? */
lua_pushliteral(L, "external hook");
else {
gethooktable(L);
lua_pushlightuserdata(L, L1);
lua_rawget(L, -2); /* get hook */
lua_remove(L, -2); /* remove hook table */
}
lua_pushstring(L, unmakemask(mask, buff));
lua_pushinteger(L, lua_gethookcount(L1));
return 3;
}
private static int db_debug (lua_State L) {
for (;;) {
CharPtr buffer = new char[250];
fputs("lua_debug> ", stderr);
if (fgets(buffer, stdin) == null ||
strcmp(buffer, "cont\n") == 0)
return 0;
if (luaL_loadbuffer(L, buffer, (uint)strlen(buffer), "=(debug command)")!=0 ||
lua_pcall(L, 0, 0, 0)!=0) {
fputs(lua_tostring(L, -1), stderr);
fputs("\n", stderr);
}
lua_settop(L, 0); /* remove eventual returns */
}
}
public const int LEVELS1 = 12; /* size of the first part of the stack */
public const int LEVELS2 = 10; /* size of the second part of the stack */
private static int db_errorfb (lua_State L) {
int level;
bool firstpart = true; /* still before eventual `...' */
int arg;
lua_State L1 = getthread(L, out arg);
lua_Debug ar = new lua_Debug();
if (lua_isnumber(L, arg+2) != 0) {
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)==0) return 1; /* message is not a string */
else lua_pushliteral(L, "\n");
lua_pushliteral(L, "stack traceback:");
while (lua_getstack(L1, level++, ar) != 0) {
if (level > LEVELS1 && firstpart) {
/* no more than `LEVELS2' more levels? */
if (lua_getstack(L1, level+LEVELS2, ar)==0)
level--; /* keep going */
else {
lua_pushliteral(L, "\n\t..."); /* too many levels */
while (lua_getstack(L1, level+LEVELS2, ar) != 0) /* find last levels */
level++;
}
firstpart = false;
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);
}
lua_concat(L, lua_gettop(L) - arg);
return 1;
}
private readonly static luaL_Reg[] dblib = {
new luaL_Reg("debug", db_debug),
new luaL_Reg("getfenv", db_getfenv),
new luaL_Reg("gethook", db_gethook),
new luaL_Reg("getinfo", db_getinfo),
new luaL_Reg("getlocal", db_getlocal),
new luaL_Reg("getregistry", db_getregistry),
new luaL_Reg("getmetatable", db_getmetatable),
new luaL_Reg("getupvalue", db_getupvalue),
new luaL_Reg("setfenv", db_setfenv),
new luaL_Reg("sethook", db_sethook),
new luaL_Reg("setlocal", db_setlocal),
new luaL_Reg("setmetatable", db_setmetatable),
new luaL_Reg("setupvalue", db_setupvalue),
new luaL_Reg("traceback", db_errorfb),
new luaL_Reg(null, null)
};
public static int luaopen_debug (lua_State L) {
luaL_register(L, LUA_DBLIBNAME, dblib);
return 1;
}
}
}
/*
** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $
** Debug Interface
** See Copyright Notice in lua.h
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
namespace KopiLua
{
using TValue = Lua.lua_TValue;
using StkId = Lua.lua_TValue;
using Instruction = System.UInt32;
public partial class Lua
{
public static int pcRel(InstructionPtr pc, Proto p)
{
Debug.Assert(pc.codes == p.code);
return pc.pc - 1;
}
public static int getline(Proto f, int pc) { return (f.lineinfo != null) ? f.lineinfo[pc] : 0; }
public static void resethookcount(lua_State L) { L.hookcount = L.basehookcount; }
private 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 = InstructionPtr.Assign(L.savedpc);
return pcRel(ci.savedpc, ci_func(ci).l.p);
}
private 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);
}
/*
** this function can be called asynchronous (e.g. during a signal)
*/
public static int lua_sethook (lua_State L, lua_Hook func, int mask, int count) {
if (func == null || mask == 0) { /* turn off hooks? */
mask = 0;
func = null;
}
L.hook = func;
L.basehookcount = count;
resethookcount(L);
L.hookmask = cast_byte(mask);
return 1;
}
public static lua_Hook lua_gethook (lua_State L) {
return L.hook;
}
public static int lua_gethookmask (lua_State L) {
return L.hookmask;
}
public static int lua_gethookcount (lua_State L) {
return L.basehookcount;
}
public static int lua_getstack (lua_State L, int level, lua_Debug ar) {
int status;
CallInfo ci;
lua_lock(L);
for (ci = L.ci; level > 0 && ci > L.base_ci[0]; CallInfo.dec(ref ci)) {
level--;
if (f_isLua(ci)) /* Lua function? */
level -= ci.tailcalls; /* skip lost tail calls */
}
if (level == 0 && ci > L.base_ci[0]) { /* level found? */
status = 1;
ar.i_ci = ci - L.base_ci[0];
}
else if (level < 0) { /* level is of a lost tail call? */
status = 1;
ar.i_ci = 0;
}
else status = 0; /* no such level */
lua_unlock(L);
return status;
}
private static Proto getluaproto (CallInfo ci) {
return (isLua(ci) ? ci_func(ci).l.p : null);
}
private static CharPtr findlocal (lua_State L, CallInfo ci, int n) {
CharPtr name;
Proto fp = getluaproto(ci);
if ((fp!=null) && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != null)
return name; /* is a local variable in a Lua function */
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)";
else
return null;
}
}
public static CharPtr lua_getlocal (lua_State L, lua_Debug ar, int n) {
CallInfo ci = L.base_ci[ar.i_ci];
CharPtr name = findlocal(L, ci, n);
lua_lock(L);
if (name != null)
luaA_pushobject(L, ci.base_[n - 1]);
lua_unlock(L);
return name;
}
public static CharPtr lua_setlocal (lua_State L, lua_Debug ar, int n) {
CallInfo ci = L.base_ci[ar.i_ci];
CharPtr name = findlocal(L, ci, n);
lua_lock(L);
if (name != null)
setobjs2s(L, ci.base_[n - 1], L.top-1);
StkId.dec(ref L.top); /* pop value */
lua_unlock(L);
return name;
}
private static void funcinfo (lua_Debug ar, Closure cl) {
if (cl.c.isC != 0) {
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;
ar.what = (ar.linedefined == 0) ? "main" : "Lua";
}
luaO_chunkid(ar.short_src, ar.source, LUA_IDSIZE);
}
private 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;
}
private static void collectvalidlines (lua_State L, Closure f) {
if (f == null || (f.c.isC!=0)) {
setnilvalue(L.top);
}
else {
Table t = luaH_new(L, 0, 0);
int[] lineinfo = f.l.p.lineinfo;
int i;
for (i=0; i<f.l.p.sizelineinfo; i++)
setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);
sethvalue(L, L.top, t);
}
incr_top(L);
}
private static int auxgetinfo (lua_State L, CharPtr what, lua_Debug ar,
Closure f, CallInfo ci) {
int status = 1;
if (f == null) {
info_tailcall(ar);
return status;
}
for (; what[0] != 0; what = what.next()) {
switch (what[0]) {
case 'S': {
funcinfo(ar, f);
break;
}
case 'l': {
ar.currentline = (ci != null) ? currentline(L, ci) : -1;
break;
}
case 'u': {
ar.nups = f.c.nupvalues;
break;
}
case 'n': {
ar.namewhat = (ci!=null) ? getfuncname(L, ci, ref ar.name) : null;
if (ar.namewhat == null) {
ar.namewhat = ""; /* not found */
ar.name = null;
}
break;
}
case 'L':
case 'f': /* handled by lua_getinfo */
break;
default: status = 0; break;/* invalid option */
}
}
return status;
}
public static int lua_getinfo (lua_State L, CharPtr what, lua_Debug ar) {
int status;
Closure f = null;
CallInfo ci = null;
lua_lock(L);
if (what == '>') {
StkId func = L.top - 1;
luai_apicheck(L, ttisfunction(func));
what = what.next(); /* skip the '>' */
f = clvalue(func);
StkId.dec(ref L.top); /* pop function */
}
else if (ar.i_ci != 0) { /* no tail call? */
ci = L.base_ci[ar.i_ci];
lua_assert(ttisfunction(ci.func));
f = clvalue(ci.func);
}
status = auxgetinfo(L, what, ar, f, ci);
if (strchr(what, 'f') != null) {
if (f == null) setnilvalue(L.top);
else setclvalue(L, L.top, f);
incr_top(L);
}
if (strchr(what, 'L') != null)
collectvalidlines(L, f);
lua_unlock(L);
return status;
}
/*
** {======================================================
** Symbolic Execution and code checker
** =======================================================
*/
private static int checkjump(Proto pt, int pc) { if (!(0 <= pc && pc < pt.sizecode)) return 0; return 1; }
private static int checkreg(Proto pt, int reg) { if (!((reg) < (pt).maxstacksize)) return 0; return 1; }
private static int precheck (Proto pt) {
if (!(pt.maxstacksize <= MAXSTACK)) return 0;
if (!(pt.numparams+(pt.is_vararg & VARARG_HASARG) <= pt.maxstacksize)) return 0;
if (!(((pt.is_vararg & VARARG_NEEDSARG)==0) ||
((pt.is_vararg & VARARG_HASARG)!=0))) return 0;
if (!(pt.sizeupvalues <= pt.nups)) return 0;
if (!(pt.sizelineinfo == pt.sizecode || pt.sizelineinfo == 0)) return 0;
if (!(pt.sizecode > 0 && GET_OPCODE(pt.code[pt.sizecode - 1]) == OpCode.OP_RETURN)) return 0;
return 1;
}
public static int checkopenop(Proto pt, int pc) { return luaG_checkopenop(pt.code[pc + 1]); }
[CLSCompliantAttribute(false)]
public static int luaG_checkopenop (Instruction i) {
switch (GET_OPCODE(i)) {
case OpCode.OP_CALL:
case OpCode.OP_TAILCALL:
case OpCode.OP_RETURN:
case OpCode.OP_SETLIST: {
if (!(GETARG_B(i) == 0)) return 0;
return 1;
}
default: return 0; /* invalid instruction after an open call */
}
}
private static int checkArgMode (Proto pt, int r, OpArgMask mode) {
switch (mode) {
case OpArgMask.OpArgN: if (r!=0) return 0; break;
case OpArgMask.OpArgU: break;
case OpArgMask.OpArgR: checkreg(pt, r); break;
case OpArgMask.OpArgK:
if (!( (ISK(r) != 0) ? INDEXK(r) < pt.sizek : r < pt.maxstacksize)) return 0;
break;
}
return 1;
}
private static Instruction symbexec (Proto pt, int lastpc, int reg) {
int pc;
int last; /* stores position of last instruction that changed `reg' */
int dest;
last = pt.sizecode-1; /* points to final return (a `neutral' instruction) */
if (precheck(pt)==0) return 0;
for (pc = 0; pc < lastpc; pc++) {
Instruction i = pt.code[pc];
OpCode op = GET_OPCODE(i);
int a = GETARG_A(i);
int b = 0;
int c = 0;
if (!((int)op < NUM_OPCODES)) return 0;
checkreg(pt, a);
switch (getOpMode(op)) {
case OpMode.iABC: {
b = GETARG_B(i);
c = GETARG_C(i);
if (checkArgMode(pt, b, getBMode(op))==0) return 0;
if (checkArgMode(pt, c, getCMode(op))==0) return 0;
break;
}
case OpMode.iABx: {
b = GETARG_Bx(i);
if (getBMode(op) == OpArgMask.OpArgK) if (!(b < pt.sizek)) return 0;
break;
}
case OpMode.iAsBx: {
b = GETARG_sBx(i);
if (getBMode(op) == OpArgMask.OpArgR) {
dest = pc+1+b;
if (!((0 <= dest && dest < pt.sizecode))) return 0;
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) == OpCode.OP_SETLIST && GETARG_C(d) == 0)) break;
}
/* if 'j' is even, previous value is not a setlist (even if
it looks like one) */
if ((j&1)!=0) return 0;
}
}
break;
}
}
if (testAMode(op) != 0) {
if (a == reg) last = pc; /* change register `a' */
}
if (testTMode(op) != 0) {
if (!(pc+2 < pt.sizecode)) return 0; /* check skip */
if (!(GET_OPCODE(pt.code[pc + 1]) == OpCode.OP_JMP)) return 0;
}
switch (op) {
case OpCode.OP_LOADBOOL: {
if (c == 1) { /* does it jump? */
if (!(pc+2 < pt.sizecode)) return 0; /* check its jump */
if (!(GET_OPCODE(pt.code[pc + 1]) != OpCode.OP_SETLIST ||
GETARG_C(pt.code[pc + 1]) != 0)) return 0;
}
break;
}
case OpCode.OP_LOADNIL: {
if (a <= reg && reg <= b)
last = pc; /* set registers from `a' to `b' */
break;
}
case OpCode.OP_GETUPVAL:
case OpCode.OP_SETUPVAL: {
if (!(b < pt.nups)) return 0;
break;
}
case OpCode.OP_GETGLOBAL:
case OpCode.OP_SETGLOBAL: {
if (!(ttisstring(pt.k[b]))) return 0;
break;
}
case OpCode.OP_SELF: {
checkreg(pt, a+1);
if (reg == a+1) last = pc;
break;
}
case OpCode.OP_CONCAT: {
if (!(b < c)) return 0; /* at least two operands */
break;
}
case OpCode.OP_TFORLOOP: {
if (!(c >= 1)) return 0; /* 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 OpCode.OP_FORLOOP:
case OpCode.OP_FORPREP:
checkreg(pt, a+3);
/* go through ...no, on second thoughts don't, because this is C# */
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 */
break;
case OpCode.OP_JMP: {
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 */
break;
}
case OpCode.OP_CALL:
case OpCode.OP_TAILCALL: {
if (b != 0) {
checkreg(pt, a+b-1);
}
c--; /* c = num. returns */
if (c == LUA_MULTRET) {
if (checkopenop(pt, pc)==0) return 0;
}
else if (c != 0)
checkreg(pt, a+c-1);
if (reg >= a) last = pc; /* affect all registers above base */
break;
}
case OpCode.OP_RETURN: {
b--; /* b = num. returns */
if (b > 0) checkreg(pt, a+b-1);
break;
}
case OpCode.OP_SETLIST: {
if (b > 0) checkreg(pt, a + b);
if (c == 0) {
pc++;
if (!(pc < pt.sizecode - 1)) return 0;
}
break;
}
case OpCode.OP_CLOSURE: {
int nup, j;
if (!(b < pt.sizep)) return 0;
nup = pt.p[b].nups;
if (!(pc + nup < pt.sizecode)) return 0;
for (j = 1; j <= nup; j++) {
OpCode op1 = GET_OPCODE(pt.code[pc + j]);
if (!(op1 == OpCode.OP_GETUPVAL || op1 == OpCode.OP_MOVE)) return 0;
}
if (reg != NO_REG) /* tracing? */
pc += nup; /* do not 'execute' these pseudo-instructions */
break;
}
case OpCode.OP_VARARG: {
if (!( (pt.is_vararg & VARARG_ISVARARG)!=0 &&
(pt.is_vararg & VARARG_NEEDSARG)==0 )) return 0;
b--;
if (b == LUA_MULTRET) if (checkopenop(pt, pc)==0) return 0;
checkreg(pt, a+b-1);
break;
}
default:
break;
}
}
return pt.code[last];
}
//#undef check
//#undef checkjump
//#undef checkreg
/* }====================================================== */
public static int luaG_checkcode (Proto pt) {
return (symbexec(pt, pt.sizecode, NO_REG) != 0) ? 1 : 0;
}
private static CharPtr kname (Proto p, int c) {
if (ISK(c)!=0 && ttisstring(p.k[INDEXK(c)]))
return svalue(p.k[INDEXK(c)]);
else
return "?";
}
private static CharPtr getobjname (lua_State L, CallInfo ci, int stackpos,
ref CharPtr 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!=null) /* is a local? */
return "local";
i = symbexec(p, pc, stackpos); /* try symbolic execution */
lua_assert(pc != -1);
switch (GET_OPCODE(i)) {
case OpCode.OP_GETGLOBAL: {
int g = GETARG_Bx(i); /* global index */
lua_assert(ttisstring(p.k[g]));
name = svalue(p.k[g]);
return "global";
}
case OpCode.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, ref name); /* get name for `b' */
break;
}
case OpCode.OP_GETTABLE: {
int k = GETARG_C(i); /* key index */
name = kname(p, k);
return "field";
}
case OpCode.OP_GETUPVAL: {
int u = GETARG_B(i); /* upvalue index */
name = (p.upvalues!=null) ? getstr(p.upvalues[u]) : "?";
return "upvalue";
}
case OpCode.OP_SELF: {
int k = GETARG_C(i); /* key index */
name = kname(p, k);
return "method";
}
default: break;
}
}
return null; /* no useful name found */
}
private static CharPtr getfuncname (lua_State L, CallInfo ci, ref CharPtr name) {
Instruction i;
if ((isLua(ci) && ci.tailcalls > 0) || !isLua(ci - 1))
return null; /* calling function is not Lua (or is unknown) */
CallInfo.dec(ref ci); /* calling function */
i = ci_func(ci).l.p.code[currentpc(L, ci)];
if (GET_OPCODE(i) == OpCode.OP_CALL || GET_OPCODE(i) == OpCode.OP_TAILCALL ||
GET_OPCODE(i) == OpCode.OP_TFORLOOP)
return getobjname(L, ci, GETARG_A(i), ref name);
else
return null; /* no useful name can be found */
}
/* only ANSI way to check whether a pointer points to an array */
private static int isinstack (CallInfo ci, TValue o) {
StkId p;
for (p = ci.base_; p < ci.top; StkId.inc(ref p))
if (o == p) return 1;
return 0;
}
public static void luaG_typeerror (lua_State L, TValue o, CharPtr op) {
CharPtr name = null;
CharPtr t = luaT_typenames[ttype(o)];
CharPtr kind = (isinstack(L.ci, o)) != 0 ?
getobjname(L, L.ci, cast_int(o - L.base_), ref name) :
null;
if (kind != null)
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);
}
public static void luaG_concaterror (lua_State L, StkId p1, StkId p2) {
if (ttisstring(p1) || ttisnumber(p1)) p1 = p2;
lua_assert(!ttisstring(p1) && !ttisnumber(p1));
luaG_typeerror(L, p1, "concatenate");
}
public static void luaG_aritherror (lua_State L, TValue p1, TValue p2) {
TValue temp = new TValue();
if (luaV_tonumber(p1, temp) == null)
p2 = p1; /* first operand is wrong */
luaG_typeerror(L, p2, "perform arithmetic on");
}
public static int luaG_ordererror (lua_State L, TValue p1, TValue p2) {
CharPtr t1 = luaT_typenames[ttype(p1)];
CharPtr t2 = luaT_typenames[ttype(p2)];
if (t1[2] == t2[2])
luaG_runerror(L, "attempt to compare two %s values", t1);
else
luaG_runerror(L, "attempt to compare %s with %s", t1, t2);
return 0;
}
private static void addinfo (lua_State L, CharPtr msg) {
CallInfo ci = L.ci;
if (isLua(ci)) { /* is Lua code? */
CharPtr buff = new CharPtr(new char[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);
}
}
public static void 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 */
}
luaD_throw(L, LUA_ERRRUN);
}
public static void luaG_runerror(lua_State L, CharPtr fmt, params object[] argp)
{
addinfo(L, luaO_pushvfstring(L, fmt, argp));
luaG_errormsg(L);
}
}
}
/*
** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 roberto Exp $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Threading;
#if XBOX
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
#endif
namespace KopiLua
{
using lua_Integer = System.Int32;
using ptrdiff_t = System.Int32;
using TValue = Lua.lua_TValue;
using StkId = Lua.lua_TValue;
using lu_byte = System.Byte;
using ZIO = Lua.Zio;
public partial class Lua
{
public static void luaD_checkstack(lua_State L, int n) {
if ((L.stack_last - L.top) <= n)
luaD_growstack(L, n);
else
{
#if HARDSTACKTESTS
luaD_reallocstack(L, L.stacksize - EXTRA_STACK - 1);
#endif
}
}
public static void incr_top(lua_State L)
{
luaD_checkstack(L, 1);
StkId.inc(ref L.top);
}
// in the original C code these values save and restore the stack by number of bytes. marshalling sizeof
// isn't that straightforward in managed languages, so i implement these by index instead.
public static int savestack(lua_State L, StkId p) {return p;}
public static StkId restorestack(lua_State L, int n) {return L.stack[n];}
public static int saveci(lua_State L, CallInfo p) {return p - L.base_ci;}
public static CallInfo restoreci(lua_State L, int n) { return L.base_ci[n]; }
/* results from luaD_precall */
public const int PCRLUA = 0; /* initiated a call to a Lua function */
public const int PCRC = 1; /* did a call to a C function */
public const int PCRYIELD = 2; /* C funtion yielded */
/* type of protected functions, to be ran by `runprotected' */
public delegate void Pfunc(lua_State L, object ud);
/*
** {======================================================
** Error-recovery functions
** =======================================================
*/
public delegate void luai_jmpbuf(lua_Integer b);
/* chain list of long jump buffers */
public class lua_longjmp {
public lua_longjmp previous;
public luai_jmpbuf b;
[CLSCompliantAttribute(false)]
public volatile int status; /* error code */
};
public static void luaD_seterrorobj (lua_State L, int errcode, StkId oldtop) {
switch (errcode) {
case LUA_ERRMEM: {
setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG));
break;
}
case LUA_ERRERR: {
setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
break;
}
case LUA_ERRSYNTAX:
case LUA_ERRRUN: {
setobjs2s(L, oldtop, L.top-1); /* error message on current top */
break;
}
}
L.top = oldtop + 1;
}
private static void restore_stack_limit (lua_State L) {
lua_assert(L.stack_last == L.stacksize - EXTRA_STACK - 1);
if (L.size_ci > LUAI_MAXCALLS) { /* there was an overflow? */
int inuse = L.ci - L.base_ci;
if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */
luaD_reallocCI(L, LUAI_MAXCALLS);
}
}
private static void resetstack (lua_State L, int status) {
L.ci = L.base_ci[0];
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;
}
public static void luaD_throw (lua_State L, int errcode) {
if (L.errorJmp != null) {
L.errorJmp.status = errcode;
LUAI_THROW(L, L.errorJmp);
}
else {
L.status = cast_byte(errcode);
if (G(L).panic != null) {
resetstack(L, errcode);
lua_unlock(L);
G(L).panic(L);
}
#if XBOX
throw new ApplicationException();
#else
#if SILVERLIGHT
throw new SystemException();
#else
Environment.Exit(EXIT_FAILURE);
#endif
#endif
}
}
public static int luaD_rawrunprotected (lua_State L, Pfunc f, object ud) {
lua_longjmp lj = new lua_longjmp();
lj.status = 0;
lj.previous = L.errorJmp; /* chain new error handler */
L.errorJmp = lj;
/*
LUAI_TRY(L, lj,
f(L, ud)
);
* */
#if CATCH_EXCEPTIONS
try
#endif
{
f(L, ud);
}
#if CATCH_EXCEPTIONS
catch
{
if (lj.status == 0)
lj.status = -1;
}
#endif
L.errorJmp = lj.previous; /* restore old error handler */
return lj.status;
}
/* }====================================================== */
private static void correctstack (lua_State L, TValue[] oldstack) {
/* don't need to do this
CallInfo ci;
GCObject up;
L.top = L.stack[L.top - oldstack];
for (up = L.openupval; up != null; up = up.gch.next)
gco2uv(up).v = L.stack[gco2uv(up).v - oldstack];
for (ci = L.base_ci[0]; ci <= L.ci; CallInfo.inc(ref ci)) {
ci.top = L.stack[ci.top - oldstack];
ci.base_ = L.stack[ci.base_ - oldstack];
ci.func = L.stack[ci.func - oldstack];
}
L.base_ = L.stack[L.base_ - oldstack];
* */
}
public static void luaD_reallocstack (lua_State L, int newsize) {
TValue[] oldstack = L.stack;
int realsize = newsize + 1 + EXTRA_STACK;
lua_assert(L.stack_last == L.stacksize - EXTRA_STACK - 1);
luaM_reallocvector(L, ref L.stack, L.stacksize, realsize/*, TValue*/);
L.stacksize = realsize;
L.stack_last = L.stack[newsize];
correctstack(L, oldstack);
}
public static void luaD_reallocCI (lua_State L, int newsize) {
CallInfo oldci = L.base_ci[0];
luaM_reallocvector(L, ref L.base_ci, L.size_ci, newsize/*, CallInfo*/);
L.size_ci = newsize;
L.ci = L.base_ci[L.ci - oldci];
L.end_ci = L.base_ci[L.size_ci - 1];
}
public static void luaD_growstack (lua_State L, int n) {
if (n <= L.stacksize) /* double size is enough? */
luaD_reallocstack(L, 2*L.stacksize);
else
luaD_reallocstack(L, L.stacksize + n);
}
private 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");
}
CallInfo.inc(ref L.ci);
return L.ci;
}
public static void luaD_callhook (lua_State L, int event_, int line) {
lua_Hook hook = L.hook;
if ((hook!=null) && (L.allowhook!=0)) {
ptrdiff_t top = savestack(L, L.top);
ptrdiff_t ci_top = savestack(L, L.ci.top);
lua_Debug ar = new lua_Debug();
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 = L.ci - L.base_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);
L.allowhook = 0; /* cannot call hooks inside a hook */
lua_unlock(L);
hook(L, ar);
lua_lock(L);
lua_assert(L.allowhook==0);
L.allowhook = 1;
L.ci.top = restorestack(L, ci_top);
L.top = restorestack(L, top);
}
}
private 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(StkId.inc(ref L.top));
#if LUA_COMPAT_VARARG
if ((p.is_vararg & VARARG_NEEDSARG) != 0) { /* compat. with old-style vararg? */
int nvar = actual - nfixargs; /* number of extra arguments */
lua_assert(p.is_vararg & VARARG_HASARG);
luaC_checkGC(L);
htab = luaH_new(L, nvar, 1); /* create `arg' table */
for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */
setobj2n(L, luaH_setnum(L, htab, i+1), L.top - 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; i<nfixargs; i++) {
setobjs2s(L, StkId.inc(ref L.top), fixed_ + i);
setnilvalue(fixed_ + i);
}
/* add `arg' parameter */
if (htab!=null) {
StkId top = L.top;
StkId.inc(ref L.top);
sethvalue(L, top, htab);
lua_assert(iswhite(obj2gco(htab)));
}
return base_;
}
static StkId tryfuncTM (lua_State L, StkId func) {
/*const*/ TValue tm = luaT_gettmbyobj(L, func, TMS.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; StkId.dec(ref p)) setobjs2s(L, p, p - 1);
incr_top(L);
func = restorestack(L, funcr); /* previous call may change stack */
setobj2s(L, func, tm); /* tag method is the new function to be called */
return func;
}
public static CallInfo inc_ci(lua_State L)
{
if (L.ci == L.end_ci) return growCI(L);
// (condhardstacktests(luaD_reallocCI(L, L.size_ci)), ++L.ci))
CallInfo.inc(ref L.ci);
return L.ci;
}
public static 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 = InstructionPtr.Assign(L.savedpc);
if (cl.isC==0) { /* 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 == 0) { /* no varargs? */
base_ = L.stack[func + 1];
if (L.top > base_ + p.numparams)
L.top = base_ + p.numparams;
}
else { /* vararg function */
int nargs = L.top - func - 1;
base_ = adjust_varargs(L, p, nargs);
func = restorestack(L, funcr); /* previous call may change the stack */
}
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 = new InstructionPtr(p.code, 0); /* starting point */
ci.tailcalls = 0;
ci.nresults = nresults;
for (st = L.top; st < ci.top; StkId.inc(ref st))
setnilvalue(st);
L.top = ci.top;
if ((L.hookmask & LUA_MASKCALL) != 0) {
InstructionPtr.inc(ref L.savedpc); /* hooks assume 'pc' is already incremented */
luaD_callhook(L, LUA_HOOKCALL, -1);
InstructionPtr.dec(ref L.savedpc); /* correct 'pc' */
}
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) != 0)
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;
}
}
}
private 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)!=0) && (L.ci.tailcalls-- != 0)) /* tail calls */
luaD_callhook(L, LUA_HOOKTAILRET, -1);
}
return restorestack(L, fr);
}
public static int luaD_poscall (lua_State L, StkId firstResult) {
StkId res;
int wanted, i;
CallInfo ci;
if ((L.hookmask & LUA_MASKRET) != 0)
firstResult = callrethooks(L, firstResult);
ci = CallInfo.dec(ref L.ci);
res = ci.func; /* res == final position of 1st result */
wanted = ci.nresults;
L.base_ = (ci - 1).base_; /* restore base */
L.savedpc = InstructionPtr.Assign((ci - 1).savedpc); /* restore savedpc */
/* move results to correct place */
for (i = wanted; i != 0 && firstResult < L.top; i--)
{
setobjs2s(L, res, firstResult);
res = res + 1;
firstResult = firstResult + 1;
}
while (i-- > 0)
setnilvalue(StkId.inc(ref res));
L.top = res;
return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */
}
/*
** Call a function (C or Lua). The function to be called is at *func.
** 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.
*/
private static 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 */
L.nCcalls--;
luaC_checkGC(L);
}
private static void resume (lua_State L, object ud) {
StkId firstArg = (StkId)ud;
CallInfo ci = L.ci;
if (L.status == 0) { /* start coroutine? */
lua_assert(ci == L.base_ci[0] && firstArg > L.base_);
if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA)
return;
}
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]) == OpCode.OP_CALL ||
GET_OPCODE((ci-1).savedpc[-1]) == OpCode.OP_TAILCALL);
if (luaD_poscall(L, firstArg) != 0) /* complete it... */
L.top = L.ci.top; /* and correct top if not multiple results */
}
else /* yielded inside a hook: just continue its execution */
L.base_ = L.ci.base_;
}
luaV_execute(L, L.ci - L.base_ci);
}
private static int resume_error (lua_State L, CharPtr msg) {
L.top = L.ci.base_;
setsvalue2s(L, L.top, luaS_new(L, msg));
incr_top(L);
lua_unlock(L);
return LUA_ERRRUN;
}
public static int lua_resume (lua_State L, int nargs) {
int status;
lua_lock(L);
if (L.status != LUA_YIELD && (L.status != 0 || (L.ci != L.base_ci[0])))
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;
lua_unlock(L);
return status;
}
[CLSCompliantAttribute(false)]
public static int lua_yield (lua_State L, int nresults) {
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 */
L.status = LUA_YIELD;
lua_unlock(L);
return -1;
}
public static int luaD_pcall (lua_State L, Pfunc func, object u,
ptrdiff_t old_top, ptrdiff_t ef) {
int status;
ushort oldnCcalls = L.nCcalls;
ptrdiff_t old_ci = saveci(L, L.ci);
lu_byte old_allowhooks = L.allowhook;
ptrdiff_t old_errfunc = L.errfunc;
L.errfunc = ef;
status = luaD_rawrunprotected(L, func, u);
if (status != 0) { /* 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 = InstructionPtr.Assign(L.ci.savedpc);
L.allowhook = old_allowhooks;
restore_stack_limit(L);
}
L.errfunc = old_errfunc;
return status;
}
/*
** Execute a protected parser.
*/
public class SParser { /* data to `f_parser' */
public ZIO z;
public Mbuffer buff = new Mbuffer(); /* buffer to be used by the scanner */
public CharPtr name;
};
private static void f_parser (lua_State L, object ud) {
int i;
Proto tf;
Closure cl;
SParser p = (SParser)ud;
int c = luaZ_lookahead(p.z);
luaC_checkGC(L);
tf = (c == LUA_SIGNATURE[0]) ?
luaU_undump(L, p.z, p.buff, p.name) :
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);
}
public static int luaD_protectedparser (lua_State L, ZIO z, CharPtr name) {
SParser p = new SParser();
int status;
p.z = z; p.name = new CharPtr(name);
luaZ_initbuffer(L, p.buff);
status = luaD_pcall(L, f_parser, p, savestack(L, L.top), L.errfunc);
luaZ_freebuffer(L, p.buff);
return status;
}
}
}
/*
** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $
** save precompiled Lua chunks
** See Copyright Notice in lua.h
*/
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Runtime.Serialization;
namespace KopiLua
{
using lua_Number = System.Double;
using TValue = Lua.lua_TValue;
public partial class Lua
{
public class DumpState {
public lua_State L;
[CLSCompliantAttribute(false)]
public lua_Writer writer;
public object data;
public int strip;
public int status;
};
public static void DumpMem(object b, DumpState D)
{
#if XBOX || SILVERLIGHT
// todo: implement this - mjf
Debug.Assert(false);
#else
int size = Marshal.SizeOf(b);
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(b, ptr, false);
byte[] bytes = new byte[size];
Marshal.Copy(ptr, bytes, 0, size);
char[] ch = new char[bytes.Length];
for (int i = 0; i < bytes.Length; i++)
ch[i] = (char)bytes[i];
CharPtr str = ch;
DumpBlock(str, (uint)str.chars.Length, D);
Marshal.Release(ptr);
#endif
}
public static void DumpMem(object b, int n, DumpState D)
{
Array array = b as Array;
Debug.Assert(array.Length == n);
for (int i = 0; i < n; i++)
DumpMem(array.GetValue(i), D);
}
public static void DumpVar(object x, DumpState D)
{
DumpMem(x, D);
}
private static void DumpBlock(CharPtr b, uint 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);
}
}
private static void DumpChar(int y, DumpState D)
{
char x=(char)y;
DumpVar(x,D);
}
private static void DumpInt(int x, DumpState D)
{
DumpVar(x,D);
}
private static void DumpNumber(lua_Number x, DumpState D)
{
DumpVar(x,D);
}
static void DumpVector(object b, int n, DumpState D)
{
DumpInt(n,D);
DumpMem(b, n, D);
}
private static void DumpString(TString s, DumpState D)
{
if (s==null || getstr(s)==null)
{
uint size=0;
DumpVar(size,D);
}
else
{
uint size=s.tsv.len+1; /* include trailing '\0' */
DumpVar(size,D);
DumpBlock(getstr(s),size,D);
}
}
private static void DumpCode(Proto f,DumpState D)
{
DumpVector(f.code, f.sizecode, D);
}
private static void DumpConstants(Proto f, DumpState D)
{
int i,n=f.sizek;
DumpInt(n,D);
for (i=0; i<n; i++)
{
/*const*/ TValue o=f.k[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;
}
}
n=f.sizep;
DumpInt(n,D);
for (i=0; i<n; i++) DumpFunction(f.p[i],f.source,D);
}
private static void DumpDebug(Proto f, DumpState D)
{
int i,n;
n= (D.strip != 0) ? 0 : f.sizelineinfo;
DumpVector(f.lineinfo, n, D);
n= (D.strip != 0) ? 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) ? 0 : f.sizeupvalues;
DumpInt(n,D);
for (i=0; i<n; i++) DumpString(f.upvalues[i],D);
}
private static void DumpFunction(Proto f, TString p, DumpState D)
{
DumpString( ((f.source==p) || (D.strip!=0)) ? 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);
}
private static void DumpHeader(DumpState D)
{
CharPtr h = new char[LUAC_HEADERSIZE];
luaU_header(h);
DumpBlock(h,LUAC_HEADERSIZE,D);
}
/*
** dump Lua function as precompiled chunk
*/
[CLSCompliantAttribute(false)]
public static int luaU_dump (lua_State L, Proto f, lua_Writer w, object data, int strip)
{
DumpState D = new DumpState();
D.L=L;
D.writer=w;
D.data=data;
D.strip=strip;
D.status=0;
DumpHeader(D);
DumpFunction(f,null,D);
return D.status;
}
}
}
/*
** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace KopiLua
{
using TValue = Lua.lua_TValue;
using StkId = Lua.lua_TValue;
using Instruction = System.UInt32;
public partial class Lua
{
public static int sizeCclosure(int n) {
return GetUnmanagedSize(typeof(CClosure)) + GetUnmanagedSize(typeof(TValue)) * (n - 1);
}
public static int sizeLclosure(int n) {
return GetUnmanagedSize(typeof(LClosure)) + GetUnmanagedSize(typeof(TValue)) * (n - 1);
}
public static Closure luaF_newCclosure (lua_State L, int nelems, Table e) {
//Closure c = (Closure)luaM_malloc(L, sizeCclosure(nelems));
Closure c = luaM_new<Closure>(L);
AddTotalBytes(L, sizeCclosure(nelems));
luaC_link(L, obj2gco(c), LUA_TFUNCTION);
c.c.isC = 1;
c.c.env = e;
c.c.nupvalues = cast_byte(nelems);
c.c.upvalue = new TValue[nelems];
for (int i = 0; i < nelems; i++)
c.c.upvalue[i] = new lua_TValue();
return c;
}
public static Closure luaF_newLclosure (lua_State L, int nelems, Table e) {
//Closure c = (Closure)luaM_malloc(L, sizeLclosure(nelems));
Closure c = luaM_new<Closure>(L);
AddTotalBytes(L, sizeLclosure(nelems));
luaC_link(L, obj2gco(c), LUA_TFUNCTION);
c.l.isC = 0;
c.l.env = e;
c.l.nupvalues = cast_byte(nelems);
c.l.upvals = new UpVal[nelems];
for (int i = 0; i < nelems; i++)
c.l.upvals[i] = new UpVal();
while (nelems-- > 0) c.l.upvals[nelems] = null;
return c;
}
public static UpVal luaF_newupval (lua_State L) {
UpVal uv = luaM_new<UpVal>(L);
luaC_link(L, obj2gco(uv), LUA_TUPVAL);
uv.v = uv.u.value;
setnilvalue(uv.v);
return uv;
}
public static UpVal luaF_findupval (lua_State L, StkId level) {
global_State g = G(L);
GCObjectRef pp = new OpenValRef(L);
UpVal p;
UpVal uv;
while (pp.get() != null && (p = ngcotouv(pp.get())).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 = new NextRef(p);
}
uv = luaM_new<UpVal>(L); /* not found: create a new one */
uv.tt = LUA_TUPVAL;
uv.marked = luaC_white(g);
uv.v = level; /* current value lives in the stack */
uv.next = pp.get(); /* chain it in the proper position */
pp.set( 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);
return uv;
}
private 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;
}
public static 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 */
}
public static 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 */
else {
unlinkupval(uv);
setobj(L, uv.u.value, uv.v);
uv.v = uv.u.value; /* now current value lives here */
luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */
}
}
}
public static Proto luaF_newproto (lua_State L) {
Proto f = luaM_new<Proto>(L);
luaC_link(L, obj2gco(f), LUA_TPROTO);
f.k = null;
f.sizek = 0;
f.p = null;
f.sizep = 0;
f.code = null;
f.sizecode = 0;
f.sizelineinfo = 0;
f.sizeupvalues = 0;
f.nups = 0;
f.upvalues = null;
f.numparams = 0;
f.is_vararg = 0;
f.maxstacksize = 0;
f.lineinfo = null;
f.sizelocvars = 0;
f.locvars = null;
f.linedefined = 0;
f.lastlinedefined = 0;
f.source = null;
return f;
}
public static void luaF_freeproto (lua_State L, Proto f) {
luaM_freearray<Instruction>(L, f.code);
luaM_freearray<Proto>(L, f.p);
luaM_freearray<TValue>(L, f.k);
luaM_freearray<Int32>(L, f.lineinfo);
luaM_freearray<LocVar>(L, f.locvars);
luaM_freearray<TString>(L, f.upvalues);
luaM_free(L, f);
}
// we have a gc, so nothing to do
public static void luaF_freeclosure (lua_State L, Closure c) {
int size = (c.c.isC != 0) ? sizeCclosure(c.c.nupvalues) :
sizeLclosure(c.l.nupvalues);
//luaM_freemem(L, c, size);
SubtractTotalBytes(L, size);
}
/*
** Look for n-th local variable at line `line' in function `func'.
** Returns null if not found.
*/
public static CharPtr luaF_getlocalname (Proto f, int local_number, int pc) {
int i;
for (i = 0; i<f.sizelocvars && f.locvars[i].startpc <= pc; i++) {
if (pc < f.locvars[i].endpc) { /* is variable active? */
local_number--;
if (local_number == 0)
return getstr(f.locvars[i].varname);
}
}
return null; /* not found */
}
}
}
/*
** $Id: lgc.c,v 2.38.1.1 2007/12/27 13:02:25 roberto Exp $
** Garbage Collector
** See Copyright Notice in lua.h
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace KopiLua
{
using lu_int32 = System.UInt32;
using l_mem = System.Int32;
using lu_mem = System.UInt32;
using TValue = Lua.lua_TValue;
using StkId = Lua.lua_TValue;
using lu_byte = System.Byte;
using Instruction = System.UInt32;
public partial class Lua
{
/*
** Possible states of the Garbage Collector
*/
public const int GCSpause = 0;
public const int GCSpropagate = 1;
public const int GCSsweepstring = 2;
public const int GCSsweep = 3;
public const int GCSfinalize = 4;
/*
** some userful bit tricks
*/
public static int resetbits(ref lu_byte x, int m) { x &= (lu_byte)~m; return x; }
public static int setbits(ref lu_byte x, int m) { x |= (lu_byte)m; return x; }
public static bool testbits(lu_byte x, int m) { return (x & (lu_byte)m) != 0; }
public static int bitmask(int b) {return 1<<b;}
public static int bit2mask(int b1, int b2) {return (bitmask(b1) | bitmask(b2));}
public static int l_setbit(ref lu_byte x, int b) { return setbits(ref x, bitmask(b)); }
public static int resetbit(ref lu_byte x, int b) { return resetbits(ref x, bitmask(b)); }
public static bool testbit(lu_byte x, int b) { return testbits(x, bitmask(b)); }
public static int set2bits(ref lu_byte x, int b1, int b2) { return setbits(ref x, (bit2mask(b1, b2))); }
public static int reset2bits(ref lu_byte x, int b1, int b2) { return resetbits(ref x, (bit2mask(b1, b2))); }
public static bool test2bits(lu_byte x, int b1, int b2) { return testbits(x, (bit2mask(b1, b2))); }
/*
** 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)
*/
public const int WHITE0BIT = 0;
public const int WHITE1BIT = 1;
public const int BLACKBIT = 2;
public const int FINALIZEDBIT = 3;
public const int KEYWEAKBIT = 3;
public const int VALUEWEAKBIT = 4;
public const int FIXEDBIT = 5;
public const int SFIXEDBIT = 6;
public readonly static int WHITEBITS = bit2mask(WHITE0BIT, WHITE1BIT);
public static bool iswhite(GCObject x) { return test2bits(x.gch.marked, WHITE0BIT, WHITE1BIT); }
public static bool isblack(GCObject x) { return testbit(x.gch.marked, BLACKBIT); }
public static bool isgray(GCObject x) { return (!isblack(x) && !iswhite(x)); }
public static int otherwhite(global_State g) { return g.currentwhite ^ WHITEBITS; }
public static bool isdead(global_State g, GCObject v) { return (v.gch.marked & otherwhite(g) & WHITEBITS) != 0; }
public static void changewhite(GCObject x) { x.gch.marked ^= (byte)WHITEBITS; }
public static void gray2black(GCObject x) { l_setbit(ref x.gch.marked, BLACKBIT); }
public static bool valiswhite(TValue x) { return (iscollectable(x) && iswhite(gcvalue(x))); }
public static byte luaC_white(global_State g) { return (byte)(g.currentwhite & WHITEBITS); }
public static void luaC_checkGC(lua_State L)
{
//condhardstacktests(luaD_reallocstack(L, L.stacksize - EXTRA_STACK - 1));
//luaD_reallocstack(L, L.stacksize - EXTRA_STACK - 1);
if (G(L).totalbytes >= G(L).GCthreshold)
luaC_step(L);
}
public static void luaC_barrier(lua_State L, object p, TValue v) { if (valiswhite(v) && isblack(obj2gco(p)))
luaC_barrierf(L,obj2gco(p),gcvalue(v)); }
public static void luaC_barriert(lua_State L, Table t, TValue v) { if (valiswhite(v) && isblack(obj2gco(t)))
luaC_barrierback(L,t); }
public static void luaC_objbarrier(lua_State L, object p, object o)
{ if (iswhite(obj2gco(o)) && isblack(obj2gco(p)))
luaC_barrierf(L,obj2gco(p),obj2gco(o)); }
public static void luaC_objbarriert(lua_State L, Table t, object o)
{ if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); }
[CLSCompliantAttribute(false)]
public const uint GCSTEPSIZE = 1024;
public const int GCSWEEPMAX = 40;
public const int GCSWEEPCOST = 10;
public const int GCFINALIZECOST = 100;
public static byte maskmarks = (byte)(~(bitmask(BLACKBIT)|WHITEBITS));
public static void makewhite(global_State g, GCObject x)
{
x.gch.marked = (byte)(x.gch.marked & maskmarks | luaC_white(g));
}
public static void white2gray(GCObject x) { reset2bits(ref x.gch.marked, WHITE0BIT, WHITE1BIT); }
public static void black2gray(GCObject x) { resetbit(ref x.gch.marked, BLACKBIT); }
public static void stringmark(TString s) {reset2bits(ref s.tsv.marked, WHITE0BIT, WHITE1BIT);}
public static bool isfinalized(Udata_uv u) { return testbit(u.marked, FINALIZEDBIT); }
public static void markfinalized(Udata_uv u)
{
lu_byte marked = u.marked; // can't pass properties in as ref
l_setbit(ref marked, FINALIZEDBIT);
u.marked = marked;
}
public static int KEYWEAK = bitmask(KEYWEAKBIT);
public static int VALUEWEAK = bitmask(VALUEWEAKBIT);
public static void markvalue(global_State g, TValue o)
{
checkconsistency(o);
if (iscollectable(o) && iswhite(gcvalue(o)))
reallymarkobject(g,gcvalue(o));
}
public static void markobject(global_State g, object t)
{
if (iswhite(obj2gco(t)))
reallymarkobject(g, obj2gco(t));
}
public static void setthreshold(global_State g)
{
g.GCthreshold = (uint)((g.estimate / 100) * g.gcpause);
}
private static void removeentry (Node n) {
lua_assert(ttisnil(gval(n)));
if (iscollectable(gkey(n)))
setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */
}
private static void reallymarkobject (global_State g, GCObject o) {
lua_assert(iswhite(o) && !isdead(g, o));
white2gray(o);
switch (o.gch.tt) {
case LUA_TSTRING: {
return;
}
case LUA_TUSERDATA: {
Table mt = gco2u(o).metatable;
gray2black(o); /* udata are never gray */
if (mt != null) 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;
break;
}
case LUA_TTABLE: {
gco2h(o).gclist = g.gray;
g.gray = o;
break;
}
case LUA_TTHREAD: {
gco2th(o).gclist = g.gray;
g.gray = o;
break;
}
case LUA_TPROTO: {
gco2p(o).gclist = g.gray;
g.gray = o;
break;
}
default: lua_assert(0); break;
}
}
private static void marktmu (global_State g) {
GCObject u = g.tmudata;
if (u != null) {
do {
u = u.gch.next;
makewhite(g, u); /* may be marked, if left from previous GC */
reallymarkobject(g, u);
} while (u != g.tmudata);
}
}
/* move `dead' udata that need finalization to list `tmudata' */
[CLSCompliantAttribute(false)]
public static uint luaC_separateudata (lua_State L, int all) {
global_State g = G(L);
uint deadmem = 0;
GCObjectRef p = new NextRef(g.mainthread);
GCObject curr;
while ((curr = p.get()) != null) {
if (!(iswhite(curr) || (all!=0)) || isfinalized(gco2u(curr)))
p = new NextRef(curr.gch); /* don't bother with them */
else if (fasttm(L, gco2u(curr).metatable, TMS.TM_GC) == null) {
markfinalized(gco2u(curr)); /* don't need finalization */
p = new NextRef(curr.gch);
}
else { /* must call its gc method */
deadmem += (uint)sizeudata(gco2u(curr));
markfinalized(gco2u(curr));
p.set( 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;
}
}
}
return deadmem;
}
private static int traversetable (global_State g, Table h) {
int i;
int weakkey = 0;
int weakvalue = 0;
/*const*/ TValue mode;
if (h.metatable != null)
markobject(g, h.metatable);
mode = gfasttm(g, h.metatable, TMS.TM_MODE);
if ((mode != null) && ttisstring(mode)) { /* is there a weak mode? */
weakkey = (strchr(svalue(mode), 'k') != null) ? 1 : 0 ;
weakvalue = (strchr(svalue(mode), 'v') != null) ? 1 : 0;
if ((weakkey!=0) || (weakvalue!=0)) { /* is really weak? */
h.marked &= (byte)~(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!=0) && (weakvalue!=0)) return 1;
if (weakvalue==0) {
i = h.sizearray;
while ((i--) != 0)
markvalue(g, h.array[i]);
}
i = sizenode(h);
while ((i--) != 0) {
Node n = gnode(h, i);
lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n)));
if (ttisnil(gval(n)))
removeentry(n); /* remove empty entries */
else {
lua_assert(!ttisnil(gkey(n)));
if (weakkey==0) markvalue(g, gkey(n));
if (weakvalue==0) markvalue(g, gval(n));
}
}
return ((weakkey != 0) || (weakvalue != 0)) ? 1 : 0;
}
/*
** All marks are conditional because a GC may happen while the
** prototype is still being created
*/
private static void traverseproto (global_State g, Proto f) {
int i;
if (f.source != null) stringmark(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 */
if (f.upvalues[i] != null)
stringmark(f.upvalues[i]);
}
for (i=0; i<f.sizep; i++) { /* mark nested protos */
if (f.p[i] != null)
markobject(g, f.p[i]);
}
for (i=0; i<f.sizelocvars; i++) { /* mark local-variable names */
if (f.locvars[i].varname != null)
stringmark(f.locvars[i].varname);
}
}
private static void traverseclosure (global_State g, Closure cl) {
markobject(g, cl.c.env);
if (cl.c.isC != 0) {
int i;
for (i=0; i<cl.c.nupvalues; i++) /* mark its upvalues */
markvalue(g, cl.c.upvalue[i]);
}
else {
int i;
lua_assert(cl.l.nupvalues == cl.l.p.nups);
markobject(g, cl.l.p);
for (i=0; i<cl.l.nupvalues; i++) /* mark its upvalues */
markobject(g, cl.l.upvals[i]);
}
}
private static void checkstacksizes (lua_State L, StkId max) {
int ci_used = cast_int(L.ci - L.base_ci[0]); /* 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));
}
private 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[0]; ci <= l.ci; CallInfo.inc(ref ci)) {
lua_assert(ci.top <= l.stack_last);
if (lim < ci.top) lim = ci.top;
}
for (o = l.stack[0]; o < l.top; StkId.inc(ref o))
markvalue(g, o);
for (; o <= lim; StkId.inc(ref o))
setnilvalue(o);
checkstacksizes(l, lim);
}
/*
** traverse one gray object, turning it to black.
** Returns `quantity' traversed.
*/
private static l_mem propagatemark (global_State g) {
GCObject o = g.gray;
lua_assert(isgray(o));
gray2black(o);
switch (o.gch.tt) {
case LUA_TTABLE: {
Table h = gco2h(o);
g.gray = h.gclist;
if (traversetable(g, h) != 0) /* table is weak? */
black2gray(o); /* keep it gray */
return GetUnmanagedSize(typeof(Table)) +
GetUnmanagedSize(typeof(TValue)) * h.sizearray +
GetUnmanagedSize(typeof(Node)) * sizenode(h);
}
case LUA_TFUNCTION: {
Closure cl = gco2cl(o);
g.gray = cl.c.gclist;
traverseclosure(g, cl);
return (cl.c.isC != 0) ? sizeCclosure(cl.c.nupvalues) :
sizeLclosure(cl.l.nupvalues);
}
case LUA_TTHREAD: {
lua_State th = gco2th(o);
g.gray = th.gclist;
th.gclist = g.grayagain;
g.grayagain = o;
black2gray(o);
traversestack(g, th);
return GetUnmanagedSize(typeof(lua_State)) +
GetUnmanagedSize(typeof(TValue)) * th.stacksize +
GetUnmanagedSize(typeof(CallInfo)) * th.size_ci;
}
case LUA_TPROTO: {
Proto p = gco2p(o);
g.gray = p.gclist;
traverseproto(g, p);
return GetUnmanagedSize(typeof(Proto)) +
GetUnmanagedSize(typeof(Instruction)) * p.sizecode +
GetUnmanagedSize(typeof(Proto)) * p.sizep +
GetUnmanagedSize(typeof(TValue)) * p.sizek +
GetUnmanagedSize(typeof(int)) * p.sizelineinfo +
GetUnmanagedSize(typeof(LocVar)) * p.sizelocvars +
GetUnmanagedSize(typeof(TString)) * p.sizeupvalues;
}
default: lua_assert(0); return 0;
}
}
private static uint propagateall (global_State g) {
uint m = 0;
while (g.gray != null) m += (uint)propagatemark(g);
return m;
}
/*
** 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
*/
private static bool iscleared (TValue o, bool iskey) {
if (!iscollectable(o)) return false;
if (ttisstring(o)) {
stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */
return false;
}
return iswhite(gcvalue(o)) ||
(ttisuserdata(o) && (!iskey && isfinalized(uvalue(o))));
}
/*
** clear collected entries from weaktables
*/
private static void cleartable (GCObject l) {
while (l != null) {
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--!= 0) {
TValue o = h.array[i];
if (iscleared(o, false)) /* value was collected? */
setnilvalue(o); /* remove value */
}
}
i = sizenode(h);
while (i-- != 0) {
Node n = gnode(h, i);
if (!ttisnil(gval(n)) && /* non-empty entry? */
(iscleared(key2tval(n), true) || iscleared(gval(n), false))) {
setnilvalue(gval(n)); /* remove value ... */
removeentry(n); /* remove entry from Table */
}
}
l = h.gclist;
}
}
private static void freeobj (lua_State L, GCObject o) {
switch (o.gch.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));
break;
}
case LUA_TSTRING: {
G(L).strt.nuse--;
SubtractTotalBytes(L, sizestring(gco2ts(o)));
luaM_freemem(L, gco2ts(o));
break;
}
case LUA_TUSERDATA: {
SubtractTotalBytes(L, sizeudata(gco2u(o)));
luaM_freemem(L, gco2u(o));
break;
}
default: lua_assert(0); break;
}
}
public static void sweepwholelist(lua_State L, GCObjectRef p) { sweeplist(L, p, MAX_LUMEM); }
private static GCObjectRef sweeplist (lua_State L, GCObjectRef p, lu_mem count) {
GCObject curr;
global_State g = G(L);
int deadmask = otherwhite(g);
while ((curr = p.get()) != null && count-- > 0) {
if (curr.gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */
sweepwholelist(L, new OpenValRef( gco2th(curr) ));
if (((curr.gch.marked ^ WHITEBITS) & deadmask) != 0) { /* not dead? */
lua_assert(!isdead(g, curr) || testbit(curr.gch.marked, FIXEDBIT));
makewhite(g, curr); /* make it white (for next cycle) */
p = new NextRef(curr.gch);
}
else { /* must erase `curr' */
lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT));
p.set( curr.gch.next );
if (curr == g.rootgc) /* is the first element of the list? */
g.rootgc = curr.gch.next; /* adjust first */
freeobj(L, curr);
}
}
return p;
}
private static void checkSizes (lua_State L) {
global_State g = G(L);
/* check size of string hash */
if (g.strt.nuse < (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? */
uint newsize = luaZ_sizebuffer(g.buff) / 2;
luaZ_resizebuffer(L, g.buff, (int)newsize);
}
}
private static void GCTM (lua_State L) {
global_State g = G(L);
GCObject o = g.tmudata.gch.next; /* get first element */
Udata udata = rawgco2u(o);
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, TMS.TM_GC);
if (tm != null) {
lu_byte oldah = L.allowhook;
lu_mem oldt = (lu_mem)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);
L.allowhook = oldah; /* restore hooks */
g.GCthreshold = (uint)oldt; /* restore threshold */
}
}
/*
** Call all GC tag methods
*/
public static void luaC_callGCTM (lua_State L) {
while (G(L).tmudata != null)
GCTM(L);
}
public static void luaC_freeall (lua_State L) {
global_State g = G(L);
int i;
g.currentwhite = (byte)(WHITEBITS | bitmask(SFIXEDBIT)); /* mask to collect all elements */
sweepwholelist(L, new RootGCRef(g));
for (i = 0; i < g.strt.size; i++) /* free all string lists */
sweepwholelist(L, new ArrayRef(g.strt.hash, i));
}
private static void markmt (global_State g) {
int i;
for (i=0; i<NUM_TAGS; i++)
if (g.mt[i] != null) markobject(g, g.mt[i]);
}
/* mark root set */
private 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;
}
private 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);
}
}
private static void atomic (lua_State L) {
global_State g = G(L);
uint udsize; /* total size of userdata to be finalized */
/* 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 = new RootGCRef(g);
g.gcstate = GCSsweepstring;
g.estimate = g.totalbytes - udsize; /* first estimate */
}
private static l_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;
}
case GCSpropagate: {
if (g.gray != null)
return propagatemark(g);
else { /* no more `gray' objects */
atomic(L); /* finish mark phase */
return 0;
}
}
case GCSsweepstring: {
lu_mem old = (lu_mem)g.totalbytes;
sweepwholelist(L, new ArrayRef(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 -= (uint)(old - g.totalbytes);
return GCSWEEPCOST;
}
case GCSsweep: {
lu_mem old = (lu_mem)g.totalbytes;
g.sweepgc = sweeplist(L, g.sweepgc, GCSWEEPMAX);
if (g.sweepgc.get() == null) { /* nothing more to sweep? */
checkSizes(L);
g.gcstate = GCSfinalize; /* end sweep phase */
}
lua_assert(old >= g.totalbytes);
g.estimate -= (uint)(old - g.totalbytes);
return GCSWEEPMAX*GCSWEEPCOST;
}
case GCSfinalize: {
if (g.tmudata != null) {
GCTM(L);
if (g.estimate > GCFINALIZECOST)
g.estimate -= GCFINALIZECOST;
return GCFINALIZECOST;
}
else {
g.gcstate = GCSpause; /* end collection */
g.gcdept = 0;
return 0;
}
}
default: lua_assert(0); return 0;
}
}
public static void luaC_step (lua_State L) {
global_State g = G(L);
l_mem lim = (l_mem)((GCSTEPSIZE / 100) * g.gcstepmul);
if (lim == 0)
lim = (l_mem)((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 {
lua_assert(g.totalbytes >= g.estimate);
setthreshold(g);
}
}
public static void luaC_fullgc (lua_State L) {
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 = new RootGCRef(g);
/* 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);
singlestep(L);
}
markroot(L);
while (g.gcstate != GCSpause) {
singlestep(L);
}
setthreshold(g);
}
public static 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 */
}
public static void luaC_barrierback(lua_State L, Table t)
{
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;
}
public static void luaC_link (lua_State L, GCObject o, lu_byte tt) {
global_State g = G(L);
o.gch.next = g.rootgc;
g.rootgc = o;
o.gch.marked = luaC_white(g);
o.gch.tt = tt;
}
public static 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);
}
}
}
}
}
/*
** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $
** Initialization of libraries for lua.c
** See Copyright Notice in lua.h
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace KopiLua
{
public partial class Lua
{
private readonly static luaL_Reg[] lualibs = {
new luaL_Reg("", luaopen_base),
new luaL_Reg(LUA_LOADLIBNAME, luaopen_package),
new luaL_Reg(LUA_TABLIBNAME, luaopen_table),
new luaL_Reg(LUA_IOLIBNAME, luaopen_io),
new luaL_Reg(LUA_OSLIBNAME, luaopen_os),
new luaL_Reg(LUA_STRLIBNAME, luaopen_string),
new luaL_Reg(LUA_MATHLIBNAME, luaopen_math),
new luaL_Reg(LUA_DBLIBNAME, luaopen_debug),
new luaL_Reg(null, null)
};
public static void luaL_openlibs (lua_State L) {
for (int i=0; i<lualibs.Length-1; i++)
{
luaL_Reg lib = lualibs[i];
lua_pushcfunction(L, lib.func);
lua_pushstring(L, lib.name);
lua_call(L, 1, 0);
}
}
}
}
/*
** $Id: liolib.c,v 2.73.1.3 2008/01/18 17:47:43 roberto Exp $
** Standard I/O (and system) library
** See Copyright Notice in lua.h
*/
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace KopiLua
{
using lua_Number = System.Double;
using lua_Integer = System.Int32;
public class FilePtr
{
public Stream file;
}
public partial class Lua
{
public const int IO_INPUT = 1;
public const int IO_OUTPUT = 2;
private static readonly string[] fnames = { "input", "output" };
private static int pushresult (lua_State L, int i, CharPtr filename) {
int en = errno(); /* calls to Lua API may change this value */
if (i != 0) {
lua_pushboolean(L, 1);
return 1;
}
else {
lua_pushnil(L);
if (filename != null)
lua_pushfstring(L, "%s: %s", filename, strerror(en));
else
lua_pushfstring(L, "%s", strerror(en));
lua_pushinteger(L, en);
return 3;
}
}
private static void fileerror (lua_State L, int arg, CharPtr filename) {
lua_pushfstring(L, "%s: %s", filename, strerror(errno()));
luaL_argerror(L, arg, lua_tostring(L, -1));
}
public static FilePtr tofilep(lua_State L) { return (FilePtr)luaL_checkudata(L, 1, LUA_FILEHANDLE); }
private static int io_type (lua_State L) {
object ud;
luaL_checkany(L, 1);
ud = lua_touserdata(L, 1);
lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
if (ud == null || (lua_getmetatable(L, 1)==0) || (lua_rawequal(L, -2, -1)==0))
lua_pushnil(L); /* not a file */
else if ( (ud as FilePtr).file == null)
lua_pushliteral(L, "closed file");
else
lua_pushliteral(L, "file");
return 1;
}
private static Stream tofile (lua_State L) {
FilePtr f = tofilep(L);
if (f.file == null)
luaL_error(L, "attempt to use a closed file");
return f.file;
}
/*
** When creating file files, always creates a `closed' file file
** before opening the actual file; so, if there is a memory error, the
** file is not left opened.
*/
private static FilePtr newfile (lua_State L) {
FilePtr pf = (FilePtr)lua_newuserdata(L, typeof(FilePtr));
pf.file = null; /* file file is currently `closed' */
luaL_getmetatable(L, LUA_FILEHANDLE);
lua_setmetatable(L, -2);
return pf;
}
/*
** function to (not) close the standard files stdin, stdout, and stderr
*/
private static int io_noclose (lua_State L) {
lua_pushnil(L);
lua_pushliteral(L, "cannot close standard file");
return 2;
}
/*
** function to close 'popen' files
*/
private static int io_pclose (lua_State L) {
FilePtr p = tofilep(L);
int ok = (lua_pclose(L, p.file) == 0) ? 1 : 0;
p.file = null;
return pushresult(L, ok, null);
}
/*
** function to close regular files
*/
private static int io_fclose (lua_State L) {
FilePtr p = tofilep(L);
int ok = (fclose(p.file) == 0) ? 1 : 0;
p.file = null;
return pushresult(L, ok, null);
}
private static int aux_close (lua_State L) {
lua_getfenv(L, 1);
lua_getfield(L, -1, "__close");
return (lua_tocfunction(L, -1))(L);
}
private 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);
}
private static int io_gc (lua_State L) {
Stream f = tofilep(L).file;
/* ignore closed files */
if (f != null)
aux_close(L);
return 0;
}
private static int io_tostring (lua_State L) {
Stream f = tofilep(L).file;
if (f == null)
lua_pushliteral(L, "file (closed)");
else
lua_pushfstring(L, "file (%p)", f);
return 1;
}
private static int io_open (lua_State L) {
CharPtr filename = luaL_checkstring(L, 1);
CharPtr mode = luaL_optstring(L, 2, "r");
FilePtr pf = newfile(L);
pf.file = fopen(filename, mode);
return (pf.file == null) ? pushresult(L, 0, filename) : 1;
}
/*
** this function has a separated environment, which defines the
** correct __close for 'popen' files
*/
private static int io_popen (lua_State L) {
CharPtr filename = luaL_checkstring(L, 1);
CharPtr mode = luaL_optstring(L, 2, "r");
FilePtr pf = newfile(L);
pf.file = lua_popen(L, filename, mode);
return (pf.file == null) ? pushresult(L, 0, filename) : 1;
}
private static int io_tmpfile (lua_State L) {
FilePtr pf = newfile(L);
#if XBOX
luaL_error(L, "io_tmpfile not supported on Xbox360");
#else
pf.file = tmpfile();
#endif
return (pf.file == null) ? pushresult(L, 0, null) : 1;
}
private static Stream getiofile (lua_State L, int findex) {
Stream f;
lua_rawgeti(L, LUA_ENVIRONINDEX, findex);
f = (lua_touserdata(L, -1) as FilePtr).file;
if (f == null)
luaL_error(L, "standard %s file is closed", fnames[findex - 1]);
return f;
}
private static int g_iofile (lua_State L, int f, CharPtr mode) {
if (!lua_isnoneornil(L, 1)) {
CharPtr filename = lua_tostring(L, 1);
if (filename != null) {
FilePtr pf = newfile(L);
pf.file = fopen(filename, mode);
if (pf.file == null)
fileerror(L, 1, filename);
}
else {
tofile(L); /* check that it's a valid file file */
lua_pushvalue(L, 1);
}
lua_rawseti(L, LUA_ENVIRONINDEX, f);
}
/* return current value */
lua_rawgeti(L, LUA_ENVIRONINDEX, f);
return 1;
}
private static int io_input (lua_State L) {
return g_iofile(L, IO_INPUT, "r");
}
private static int io_output (lua_State L) {
return g_iofile(L, IO_OUTPUT, "w");
}
private static void aux_lines (lua_State L, int idx, int toclose) {
lua_pushvalue(L, idx);
lua_pushboolean(L, toclose); /* close/not close file when finished */
lua_pushcclosure(L, io_readline, 2);
}
private static int f_lines (lua_State L) {
tofile(L); /* check that it's a valid file file */
aux_lines(L, 1, 0);
return 1;
}
private 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);
}
else {
CharPtr filename = luaL_checkstring(L, 1);
FilePtr pf = newfile(L);
pf.file = fopen(filename, "r");
if (pf.file == null)
fileerror(L, 1, filename);
aux_lines(L, lua_gettop(L), 1);
return 1;
}
}
/*
** {======================================================
** READ
** =======================================================
*/
private static int read_number (lua_State L, Stream f) {
//lua_Number d;
object[] parms = { (object)(double)0.0 };
if (fscanf(f, LUA_NUMBER_SCAN, parms) == 1)
{
lua_pushnumber(L, (double)parms[0]);
return 1;
}
else return 0; /* read fails */
}
private static int test_eof (lua_State L, Stream f) {
int c = getc(f);
ungetc(c, f);
lua_pushlstring(L, null, 0);
return (c != EOF) ? 1 : 0;
}
private static int read_line (lua_State L, Stream f) {
luaL_Buffer b = new luaL_Buffer();
luaL_buffinit(L, b);
for (;;) {
uint l;
CharPtr p = luaL_prepbuffer(b);
if (fgets(p, f) == null) { /* eof? */
luaL_pushresult(b); /* close buffer */
return (lua_objlen(L, -1) > 0) ? 1 : 0; /* check whether read something */
}
l = (uint)strlen(p);
if (l == 0 || p[l-1] != '\n')
luaL_addsize(b, (int)l);
else {
luaL_addsize(b, (int)(l - 1)); /* do not include `eol' */
luaL_pushresult(b); /* close buffer */
return 1; /* read at least an `eol' */
}
}
}
private static int read_chars (lua_State L, Stream f, uint n) {
uint rlen; /* how much to read */
uint nr; /* number of chars actually read */
luaL_Buffer b = new luaL_Buffer();
luaL_buffinit(L, b);
rlen = LUAL_BUFFERSIZE; /* try to read that much each time */
do {
CharPtr p = luaL_prepbuffer(b);
if (rlen > n) rlen = n; /* cannot read more than asked */
nr = (uint)fread(p, GetUnmanagedSize(typeof(char)), (int)rlen, f);
luaL_addsize(b, (int)nr);
n -= nr; /* still have to read `n' chars */
} while (n > 0 && nr == rlen); /* until end of count or eof */
luaL_pushresult(b); /* close buffer */
return (n == 0 || lua_objlen(L, -1) > 0) ? 1 : 0;
}
private static int g_read (lua_State L, Stream f, int first) {
int nargs = lua_gettop(L) - 1;
int success;
int n;
clearerr(f);
if (nargs == 0) { /* no arguments? */
success = read_line(L, f);
n = first+1; /* to return 1 result */
}
else { /* ensure stack space for all results and for auxlib's buffer */
luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
success = 1;
for (n = first; (nargs-- != 0) && (success!=0); n++) {
if (lua_type(L, n) == LUA_TNUMBER) {
uint l = (uint)lua_tointeger(L, n);
success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
}
else {
CharPtr p = lua_tostring(L, n);
luaL_argcheck(L, (p!=null) && (p[0] == '*'), n, "invalid option");
switch (p[1]) {
case 'n': /* number */
success = read_number(L, f);
break;
case 'l': /* line */
success = read_line(L, f);
break;
case 'a': /* file */
read_chars(L, f, ~((uint)0)); /* read MAX_uint chars */
success = 1; /* always success */
break;
default:
return luaL_argerror(L, n, "invalid format");
}
}
}
}
if (ferror(f)!=0)
return pushresult(L, 0, null);
if (success==0) {
lua_pop(L, 1); /* remove last result */
lua_pushnil(L); /* push nil instead */
}
return n - first;
}
private static int io_read (lua_State L) {
return g_read(L, getiofile(L, IO_INPUT), 1);
}
private static int f_read (lua_State L) {
return g_read(L, tofile(L), 2);
}
private static int io_readline (lua_State L) {
Stream f = (lua_touserdata(L, lua_upvalueindex(1)) as FilePtr).file;
int sucess;
if (f == null) /* file is already closed? */
luaL_error(L, "file is already closed");
sucess = read_line(L, f);
if (ferror(f)!=0)
return luaL_error(L, "%s", strerror(errno()));
if (sucess != 0) return 1;
else { /* EOF */
if (lua_toboolean(L, lua_upvalueindex(2)) != 0) { /* generator created file? */
lua_settop(L, 0);
lua_pushvalue(L, lua_upvalueindex(1));
aux_close(L); /* close it */
}
return 0;
}
}
/* }====================================================== */
private static int g_write (lua_State L, Stream f, int arg) {
int nargs = lua_gettop(L) - 1;
int status = 1;
for (; (nargs--) != 0; arg++) {
if (lua_type(L, arg) == LUA_TNUMBER) {
/* optimization: could be done exactly as for strings */
status = ((status!=0) &&
(fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0)) ? 1 : 0;
}
else {
uint l;
CharPtr s = luaL_checklstring(L, arg, out l);
status = ((status!=0) && (fwrite(s, GetUnmanagedSize(typeof(char)), (int)l, f) == l)) ? 1 : 0;
}
}
return pushresult(L, status, null);
}
private static int io_write (lua_State L) {
return g_write(L, getiofile(L, IO_OUTPUT), 1);
}
private static int f_write (lua_State L) {
return g_write(L, tofile(L), 2);
}
private static int f_seek (lua_State L) {
int[] mode = { SEEK_SET, SEEK_CUR, SEEK_END };
CharPtr[] modenames = { "set", "cur", "end", null };
Stream f = tofile(L);
int op = luaL_checkoption(L, 2, "cur", modenames);
long offset = luaL_optlong(L, 3, 0);
op = fseek(f, offset, mode[op]);
if (op != 0)
return pushresult(L, 0, null); /* error */
else {
lua_pushinteger(L, ftell(f));
return 1;
}
}
private static int f_setvbuf (lua_State L) {
CharPtr[] modenames = { "no", "full", "line", null };
int[] mode = { _IONBF, _IOFBF, _IOLBF };
Stream 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], (uint)sz);
return pushresult(L, (res == 0) ? 1 : 0, null);
}
private static int io_flush (lua_State L) {
int result = 1;
try {getiofile(L, IO_OUTPUT).Flush();} catch {result = 0;}
return pushresult(L, result, null);
}
private static int f_flush (lua_State L) {
int result = 1;
try {tofile(L).Flush();} catch {result = 0;}
return pushresult(L, result, null);
}
private readonly static luaL_Reg[] iolib = {
new luaL_Reg("close", io_close),
new luaL_Reg("flush", io_flush),
new luaL_Reg("input", io_input),
new luaL_Reg("lines", io_lines),
new luaL_Reg("open", io_open),
new luaL_Reg("output", io_output),
new luaL_Reg("popen", io_popen),
new luaL_Reg("read", io_read),
new luaL_Reg("tmpfile", io_tmpfile),
new luaL_Reg("type", io_type),
new luaL_Reg("write", io_write),
new luaL_Reg(null, null)
};
private readonly static luaL_Reg[] flib = {
new luaL_Reg("close", io_close),
new luaL_Reg("flush", f_flush),
new luaL_Reg("lines", f_lines),
new luaL_Reg("read", f_read),
new luaL_Reg("seek", f_seek),
new luaL_Reg("setvbuf", f_setvbuf),
new luaL_Reg("write", f_write),
new luaL_Reg("__gc", io_gc),
new luaL_Reg("__tostring", io_tostring),
new luaL_Reg(null, null)
};
private static void createmeta (lua_State L) {
luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file files */
lua_pushvalue(L, -1); /* push metatable */
lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
luaL_register(L, null, flib); /* file methods */
}
private static void createstdfile (lua_State L, Stream f, int k, CharPtr fname) {
newfile(L).file = 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);
}
private static void newfenv (lua_State L, lua_CFunction cls) {
lua_createtable(L, 0, 1);
lua_pushcfunction(L, cls);
lua_setfield(L, -2, "__close");
}
public static int luaopen_io (lua_State L) {
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' */
return 1;
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment