commit 19cfac06227f1f700dd4f282f90a8ea530c82958 Author: mykola2312 <49044616+mykola2312@users.noreply.github.com> Date: Tue Feb 25 05:09:07 2020 +0200 Initial commit diff --git a/addons/lua502.dll b/addons/lua502.dll new file mode 100644 index 0000000..9edd850 Binary files /dev/null and b/addons/lua502.dll differ diff --git a/addons/lua502.exp b/addons/lua502.exp new file mode 100644 index 0000000..8bb5ef1 Binary files /dev/null and b/addons/lua502.exp differ diff --git a/addons/lua502.lib b/addons/lua502.lib new file mode 100644 index 0000000..91ce6db Binary files /dev/null and b/addons/lua502.lib differ diff --git a/addons/lua502.pdb b/addons/lua502.pdb new file mode 100644 index 0000000..953ce1b Binary files /dev/null and b/addons/lua502.pdb differ diff --git a/addons/lua502.vdf b/addons/lua502.vdf new file mode 100644 index 0000000..748ae2d --- /dev/null +++ b/addons/lua502.vdf @@ -0,0 +1,5 @@ +"Plugin" +{ + "file" "gmod9/addons/lua502.dll" +} + diff --git a/build b/build new file mode 100644 index 0000000..6faed37 --- /dev/null +++ b/build @@ -0,0 +1,33 @@ +# If you don't want to use make, run this script. +# But make sure you read config to see what can be customized. + + +# Easiest way to build bin/lua: +# cc -O2 -o bin/lua -Iinclude -Isrc src/*.c src/lib/*.c src/lua/*.c -lm -ldl + + +# Easiest way to build Lua libraries and executables: +echo -n 'building core library... ' +cd src +cc -O2 -c -I../include *.c +ar rc ../lib/liblua.a *.o +rm -f *.o + +echo -n 'standard library... ' +cd lib +cc -O2 -c -I../../include *.c +ar rc ../../lib/liblualib.a *.o +rm -f *.o + +echo -n 'lua... ' +cd ../lua +cc -O2 -o ../../bin/lua -I../../include *.c ../../lib/*.a -lm -ldl + +echo -n 'luac... ' +cd ../luac +cc -O2 -o ../../bin/luac -I../../include -I.. *.c -DLUA_OPNAMES ../lopcodes.c ../../lib/*.a + +echo 'done' + +cd ../.. +bin/lua test/hello.lua diff --git a/config b/config new file mode 100644 index 0000000..34c77ea --- /dev/null +++ b/config @@ -0,0 +1,178 @@ +# configuration file for making Lua 5.0 +# see INSTALL for installation instructions + +# These are default values. Skip this section and see the explanations below. + +LOADLIB= +DLLIB= +NUMBER= +POPEN= +TMPNAM= +DEGREES= +USERCONF= + +# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= + +# --------------------------------------------------------------- Lua libraries + +# Support for dynamically loading C libraries for Lua is a very important +# feature, which we strongly recommend be enabled. By default, this support is +# enabled on Windows systems (see below) but disabled on other systems because +# it relies on system-dependent code that is not part of ANSI C. For more +# information on dynamic loading, read the comments in src/lib/liolib.c . +# +# To enable support for dynamic loading on Unix systems that support the dlfcn +# interface (e.g., Linux, Solaris, IRIX, BSD, AIX, HPUX, and probably others), +# uncomment the next two lines. +# +#LOADLIB= -DUSE_DLOPEN=1 +#DLLIB= -ldl +# +# In Linux with gcc, you should also uncomment the next definition for +# MYLDFLAGS, which passes -E (= -export-dynamic) to the linker. This option +# allows dynamic libraries to link back to the `lua' program, so that they do +# not need the Lua libraries. (Other systems may have an equivalent facility.) +# +#MYLDFLAGS= -Wl,-E +# +# On Windows systems. support for dynamic loading is enabled by default. +# To disable this support, uncomment the next line. +# +#LOADLIB= -DUSE_DLL=0 + +# The Lua IO library (src/lib/liolib.c) has support for pipes using popen and +# pclose. This support is enabled by default on POSIX systems. +# If your system is not POSIX but has popen and pclose, define USE_POPEN=1. +# If you don't want to support pipes, define USE_POPEN=0. +# +#POPEN= -DUSE_POPEN=1 +#POPEN= -DUSE_POPEN=0 +# +# The form below will probably work in (some) Windows systems. +# +#POPEN= -DUSE_POPEN=1 -Dpopen=_popen -Dpclose=_pclose + +# The Lua OS library (src/lib/liolib.c) exports an interface to the C function +# tmpnam, which gcc now thinks is `dangerous'. So, support for tmpnam is +# disabled by default when compiling with gcc. +# If you still want to use tmpnam, define USE_TMPNAME=1. If you don't want to +# use tmpnam even if you're not compiling with gcc, define USE_TMPNAME=0. +# +#TMPNAM= -DUSE_TMPNAME=1 +#TMPNAM= -DUSE_TMPNAME=0 + +# The Lua math library (src/lib/lmathlib.c) now operates in radians, unlike +# previous versions of Lua, which used degrees. To use degrees instead of +# radians, define USE_DEGREES. +# +#DEGREES= -DUSE_DEGREES + +# ------------------------------------------------------------------ Lua core + +# Lua uses double for numbers. To change this, uncomment and edit the following +# line, changing USE_XXX to one of USE_DOUBLE, USE_FLOAT, USE_LONG, USE_INT. +# +#NUMBER= -DLUA_USER_H='"../etc/luser_number.h"' -DUSE_XXX + +# When compiling Lua with gcc on a Pentium machine, using a fast rounding +# method for the conversion of doubles to ints can give around 20% speed +# improvement. To use this rounding method, uncomment the following line. +#NUMBER= -DLUA_USER_H='"../etc/luser_number.h"' -DUSE_FASTROUND + +# For partial compatibility with old upvalue syntax, define LUA_COMPATUPSYNTAX. +# For partial compatibility with old upvalue behavior in C functions, define +# LUA_COMPATUPVALUES. Add these definitions to MYCFLAGS. +# +# -DLUA_COMPATUPSYNTAX -DLUA_COMPATUPVALUES + +# ------------------------------------------------------------- Lua interpreter + +# The stand-alone Lua interpreter needs the math functions, which are usually +# in libm.a (-lm). If your C library already includes the math functions, +# or if you are using a modified interpreter that does not need them, +# then comment the following line or add the appropriates libraries. +# +EXTRA_LIBS= -lm + +# If you want to customize the stand-alone Lua interpreter, uncomment and +# edit the following two lines; also edit etc/saconfig.c to suit your needs. +# -DUSE_READLINE adds line editing and history to the interpreter. You need +# to add -lreadline (and perhaps also -lhistory and -lcurses or -lncurses) +# to EXTRA_LIBS. +# +#USERCONF=-DLUA_USERCONFIG='"$(LUA)/etc/saconfig.c"' -DUSE_READLINE +#EXTRA_LIBS= -lm -ldl -lreadline # -lhistory -lcurses -lncurses + +# ------------------------------------------------------------------ C compiler + +# You need an ANSI C compiler. gcc is a popular one. We do not use -ansi in +# WARN because it disables POSIX features used in the libraries. +# +CC= gcc +WARN= -Wall + +# ------------------------------------------------------------------ C options + +# Write here any options you may need for your C compiler. +# If you are using gcc, -O3 will get you a faster but larger code. You can +# also add -fomit-frame-pointer to get even faster code at the cost of losing +# debug information. If you only want the shared libraries, you may want to +# add -fPIC to MYCFLAGS. +# +MYCFLAGS= -O2 +#MYCFLAGS= -O3 -fomit-frame-pointer # -fPIC + +# Write here any options you may need for your C linker. +#MYLDFLAGS= + +# ------------------------------------------------------------------ librarian + +# This should work in all Unix systems. +# +AR= ar rcu + +# If your system doesn't have (or need) ranlib, use RANLIB=true. +# On some systems, "ar s" does what ranlib would do. +# +RANLIB= ranlib +#RANLIB= ar s +#RANLIB= true + +# ------------------------------------------------------------------ stripper + +# This should work in all Unix systems, but you may want to add options. +# +STRIP= strip + +# ------------------------------------------------------------------ install + +# Locations for "make install". You may need to be root do "make install". +# +INSTALL_ROOT= /usr/local +INSTALL_BIN= $(INSTALL_ROOT)/bin +INSTALL_INC= $(INSTALL_ROOT)/include +INSTALL_LIB= $(INSTALL_ROOT)/lib +INSTALL_MAN= $(INSTALL_ROOT)/man/man1 + +# You may prefer to use "install" instead of "cp" if you have it. +# If you use "install", you may also want to change the permissions after -m. +# +INSTALL_EXEC= cp +INSTALL_DATA= cp +#INSTALL_EXEC= install -m 0755 +#INSTALL_DATA= install -m 0644 + +# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE ========= + +V=5.0 + +BIN= $(LUA)/bin +INC= $(LUA)/include +LIB= $(LUA)/lib + +INCS= -I$(INC) $(EXTRA_INCS) +DEFS= $(NUMBER) $(EXTRA_DEFS) + +CFLAGS= $(MYCFLAGS) $(WARN) $(INCS) $(DEFS) + +# (end of config) diff --git a/configure b/configure new file mode 100644 index 0000000..0aa8971 --- /dev/null +++ b/configure @@ -0,0 +1,9 @@ +#!/bin/sh + +# Lua does not use GNU autoconf; just edit ./config if needed to suit your +# platform and then run make. + +# This shows the parameters currently set in ./config: +make echo + +# If you want config as a Lua program, run "make lecho". diff --git a/doc/contents.html b/doc/contents.html new file mode 100644 index 0000000..06bd6fb --- /dev/null +++ b/doc/contents.html @@ -0,0 +1,123 @@ + + +Lua: 5.0 reference manual - contents + + + + +
+

+Lua +Reference manual for Lua 5.0 +

+ +Lua 5.0 Reference Manual +[ +top +| +ps +| +pdf +] +

+ + +Copyright +© 2003 Tecgraf, PUC-Rio. All rights reserved. +


+ + + +
+ +Last update: +Wed May 7 18:34:34 EST 2003 + + + + diff --git a/doc/logo.gif b/doc/logo.gif new file mode 100644 index 0000000..2f5e4ac Binary files /dev/null and b/doc/logo.gif differ diff --git a/doc/lua.1 b/doc/lua.1 new file mode 100644 index 0000000..c9bba7d --- /dev/null +++ b/doc/lua.1 @@ -0,0 +1,167 @@ +.\" lua.man,v 1.8 2003/04/02 00:05:20 lhf Exp +.TH LUA 1 "2003/04/02 00:05:20" +.SH NAME +lua \- Lua interpreter +.SH SYNOPSIS +.B lua +[ +.I options +] +[ +.I script +[ +.I args +] +] +.SH DESCRIPTION +.B lua +is the stand-alone Lua interpreter. +It loads and executes Lua programs, +either in textual source form or +in precompiled binary form. +(Precompiled binaries are output by +.BR luac , +the Lua compiler.) +.B lua +can be used as a batch interpreter and also interactively. +.LP +The given +.I options +(see below) +are executed and then +the Lua program in file +.I script +is loaded and executed. +The given +.I args +are available to +.I script +as strings in a global table named +.BR arg . +If these arguments contain spaces or other characters special to the shell, +then they should be quoted +(but note that the quotes will be removed by the shell). +The arguments in +.B arg +start at 0, +which contains the string +.RI ` script '. +The index of the last argument is stored in +.BR "arg.n" . +The arguments given in the command line before +.IR script , +including the name of the interpreter, +are available in negative indices in +.BR arg . +.LP +At the very start, +before even handling the command line, +.B lua +executes the contents of the environment variable +.BR LUA_INIT , +if it is defined. +If the value of +.B LUA_INIT +is of the form +.RI `@ filename ', +then +.I filename +is executed. +Otherwise, the string is assumed to be a Lua statement and is executed. +.LP +Options start with +.B \- +and are described below. +You can use +.B "\--" +to signal the end of options. +.LP +If no arguments are given, +then +.B "\-v \-i" +is assumed when the standard input is a terminal; +otherwise, +.B "\-" +is assumed. +.LP +In interactive mode, +.B lua +prompts the user, +reads lines from the standard input, +and executes them as they are read. +If a line does not contain a complete statement, +then a secondary prompt is displayed and +lines are read until a complete statement is formed or +a syntax error is found. +So, one way to interrupt the reading of an incomplete statement is +to force a syntax error: +adding a +.B `;' +in the middle of a statement is a sure way of forcing a syntax error +(except inside multiline strings and comments; these must be closed explicitly). +If a line starts with +.BR `=' , +then +.B lua +displays the values of all the expressions in the remainder of the +line. The expressions must be separated by commas. +The primary prompt is the value of the global variable +.BR _PROMPT , +if this value is a string; +otherwise, the default prompt is used. +Similarly, the secondary prompt is the value of the global variable +.BR _PROMPT2 . +So, +to change the prompts, +set the corresponding variable to a string of your choice. +You can do that after calling the interpreter +or on the command line with +.BR "_PROMPT" "=\'lua: \'" , +for example. +(Note the need for quotes, because the string contains a space.) +The default prompts are ``> '' and ``>> ''. +.SH OPTIONS +.TP +.B \- +load and execute the standard input as a file, +that is, +not interactively, +even when the standard input is a terminal. +.TP +.BI \-e " stat" +execute statement +.IR stat . +You need to quote +.I stat +if it contains spaces, quotes, +or other characters special to the shell. +.TP +.B \-i +enter interactive mode after +.I script +is executed. +.TP +.BI \-l " file" +call +.BI require( file ) +before executing +.IR script. +Typically used to load libraries +(hence the letter +.IR l ). +.TP +.B \-v +show version information. +.SH "SEE ALSO" +.BR luac (1) +.br +http://www.lua.org/ +.SH DIAGNOSTICS +Error messages should be self explanatory. +.SH AUTHORS +R. Ierusalimschy, +L. H. de Figueiredo, +and +W. Celes +(lua@tecgraf.puc-rio.br) +.\" EOF diff --git a/doc/lua.html b/doc/lua.html new file mode 100644 index 0000000..073d4b5 --- /dev/null +++ b/doc/lua.html @@ -0,0 +1,175 @@ + + + +LUA man page + + + + +

NAME

+lua - Lua interpreter +

SYNOPSIS

+lua +[ +options +] +[ +script +[ +args +] +] +

DESCRIPTION

+lua +is the stand-alone Lua interpreter. +It loads and executes Lua programs, +either in textual source form or +in precompiled binary form. +(Precompiled binaries are output by +luac, +the Lua compiler.) +lua +can be used as a batch interpreter and also interactively. +

+The given +options +(see below) +are executed and then +the Lua program in file +script +is loaded and executed. +The given +args +are available to +script +as strings in a global table named +arg. +If these arguments contain spaces or other characters special to the shell, +then they should be quoted +(but note that the quotes will be removed by the shell). +The arguments in +arg +start at 0, +which contains the string +`script'. +The index of the last argument is stored in +"arg.n". +The arguments given in the command line before +script, +including the name of the interpreter, +are available in negative indices in +arg. +

+At the very start, +before even handling the command line, +lua +executes the contents of the environment variable +LUA_INIT, +if it is defined. +If the value of +LUA_INIT +is of the form +`@filename', +then +filename +is executed. +Otherwise, the string is assumed to be a Lua statement and is executed. +

+Options start with +- +and are described below. +You can use +"--" +to signal the end of options. +

+If no arguments are given, +then +"-v -i" +is assumed when the standard input is a terminal; +otherwise, +"-" +is assumed. +

+In interactive mode, +lua +prompts the user, +reads lines from the standard input, +and executes them as they are read. +If a line does not contain a complete statement, +then a secondary prompt is displayed and +lines are read until a complete statement is formed or +a syntax error is found. +So, one way to interrupt the reading of an incomplete statement is +to force a syntax error: +adding a +`;' +in the middle of a statement is a sure way of forcing a syntax error +(except inside multiline strings and comments; these must be closed explicitly). +If a line starts with +`=', +then +lua +displays the values of all the expressions in the remainder of the +line. The expressions must be separated by commas. +The primary prompt is the value of the global variable +_PROMPT, +if this value is a string; +otherwise, the default prompt is used. +Similarly, the secondary prompt is the value of the global variable +_PROMPT2. +So, +to change the prompts, +set the corresponding variable to a string of your choice. +You can do that after calling the interpreter +or on the command line with +"_PROMPT" "=\'lua: \'", +for example. +(Note the need for quotes, because the string contains a space.) +The default prompts are ``> '' and ``>> ''. +

OPTIONS

+

+- +load and execute the standard input as a file, +that is, +not interactively, +even when the standard input is a terminal. +

+-e "stat" +execute statement +stat. +You need to quote +stat +if it contains spaces, quotes, +or other characters special to the shell. +

+-i +enter interactive mode after +script +is executed. +

+-l "file" +call +require( file) +before executing +script. +Typically used to load libraries +(hence the letter +l). +

+-v +show version information. +

SEE ALSO

+luac(1) +
+http://www.lua.org/ +

DIAGNOSTICS

+Error messages should be self explanatory. +

AUTHORS

+R. Ierusalimschy, +L. H. de Figueiredo, +and +W. Celes +(lua AT tecgraf.puc-rio.br) + + + diff --git a/doc/luac.1 b/doc/luac.1 new file mode 100644 index 0000000..c652306 --- /dev/null +++ b/doc/luac.1 @@ -0,0 +1,136 @@ +.\" luac.man,v 1.25 2002/12/13 11:45:12 lhf Exp +.TH LUAC 1 "2002/12/13 11:45:12" +.SH NAME +luac \- Lua compiler +.SH SYNOPSIS +.B luac +[ +.I options +] [ +.I filenames +] +.SH DESCRIPTION +.B luac +is the Lua compiler. +It translates programs written in the Lua programming language +into binary files that can be latter loaded and executed. +.LP +The main advantages of precompiling chunks are: +faster loading, +protecting source code from user changes, +and +off-line syntax checking. +.LP +Pre-compiling does not imply faster execution +because in Lua chunks are always compiled into bytecodes before being executed. +.B luac +simply allows those bytecodes to be saved in a file for later execution. +.LP +.B luac +produces a single output file containing the bytecodes +for all source files given. +By default, +the output file is named +.BR luac.out , +but you can change this with the +.B \-o +option. +.LP +The binary files created by +.B luac +are portable to all architectures with the same word size. +This means that +binary files created on a 32-bit platform (such as Intel) +can be read without change in another 32-bit platform (such as Sparc), +even if the byte order (``endianness'') is different. +On the other hand, +binary files created on a 16-bit platform cannot be read in a 32-bit platform, +nor vice-versa. +.LP +In the command line, +you can mix +text files containing Lua source and +binary files containing precompiled chunks. +This is useful to combine several precompiled chunks, +even from different (but compatible) platforms, +into a single precompiled chunk. +.LP +You can use +.B "\-" +to indicate the standard input as a source file +and +.B "\--" +to signal the end of options +(that is, +all remaining arguments will be treated as files even if they start with +.BR "\-" ). +.LP +The internal format of the binary files produced by +.B luac +is likely to change when a new version of Lua is released. +So, +save the source files of all Lua programs that you precompile. +.LP +.SH OPTIONS +Options must be separate. +.TP +.B \-l +produce a listing of the compiled bytecode for Lua's virtual machine. +Listing bytecodes is useful to learn about Lua's virtual machine. +If no files are given, then +.B luac +loads +.B luac.out +and lists its contents. +.TP +.BI \-o " file" +output to +.IR file , +instead of the default +.BR luac.out . +The output file may be a source file because +all files are loaded before the output file is written. +Be careful not to overwrite precious files. +.TP +.B \-p +load files but do not generate any output file. +Used mainly for syntax checking and for testing precompiled chunks: +corrupted files will probably generate errors when loaded. +Lua always performs a thorough integrity test on precompiled chunks. +Bytecode that passes this test is completely safe, +in the sense that it will not break the interpreter. +However, +there is no guarantee that such code does anything sensible. +(None can be given, because the halting problem is unsolvable.) +If no files are given, then +.B luac +loads +.B luac.out +and tests its contents. +No messages are displayed if the file passes the integrity test. +.TP +.B \-s +strip debug information before writing the output file. +This saves some space in very large chunks, +but if errors occur when running these chunks, +then the error messages may not contain the full information they usually do +(line numbers and names of locals are lost). +.TP +.B \-v +show version information. +.SH FILES +.TP 15 +.B luac.out +default output file +.SH "SEE ALSO" +.BR lua (1) +.br +http://www.lua.org/ +.SH DIAGNOSTICS +Error messages should be self explanatory. +.SH AUTHORS +L. H. de Figueiredo, +R. Ierusalimschy and +W. Celes +(lua@tecgraf.puc-rio.br) +.\" EOF diff --git a/doc/luac.html b/doc/luac.html new file mode 100644 index 0000000..3a71622 --- /dev/null +++ b/doc/luac.html @@ -0,0 +1,144 @@ + + + +LUAC man page + + + + +

NAME

+luac - Lua compiler +

SYNOPSIS

+luac +[ +options +] [ +filenames +] +

DESCRIPTION

+luac +is the Lua compiler. +It translates programs written in the Lua programming language +into binary files that can be latter loaded and executed. +

+The main advantages of precompiling chunks are: +faster loading, +protecting source code from user changes, +and +off-line syntax checking. +

+Pre-compiling does not imply faster execution +because in Lua chunks are always compiled into bytecodes before being executed. +luac +simply allows those bytecodes to be saved in a file for later execution. +

+luac +produces a single output file containing the bytecodes +for all source files given. +By default, +the output file is named +luac.out, +but you can change this with the +-o +option. +

+The binary files created by +luac +are portable to all architectures with the same word size. +This means that +binary files created on a 32-bit platform (such as Intel) +can be read without change in another 32-bit platform (such as Sparc), +even if the byte order (``endianness'') is different. +On the other hand, +binary files created on a 16-bit platform cannot be read in a 32-bit platform, +nor vice-versa. +

+In the command line, +you can mix +text files containing Lua source and +binary files containing precompiled chunks. +This is useful to combine several precompiled chunks, +even from different (but compatible) platforms, +into a single precompiled chunk. +

+You can use +"-" +to indicate the standard input as a source file +and +"--" +to signal the end of options +(that is, +all remaining arguments will be treated as files even if they start with +"-"). +

+The internal format of the binary files produced by +luac +is likely to change when a new version of Lua is released. +So, +save the source files of all Lua programs that you precompile. +

+

OPTIONS

+Options must be separate. +

+-l +produce a listing of the compiled bytecode for Lua's virtual machine. +Listing bytecodes is useful to learn about Lua's virtual machine. +If no files are given, then +luac +loads +luac.out +and lists its contents. +

+-o "file" +output to +file, +instead of the default +luac.out. +The output file may be a source file because +all files are loaded before the output file is written. +Be careful not to overwrite precious files. +

+-p +load files but do not generate any output file. +Used mainly for syntax checking and for testing precompiled chunks: +corrupted files will probably generate errors when loaded. +Lua always performs a thorough integrity test on precompiled chunks. +Bytecode that passes this test is completely safe, +in the sense that it will not break the interpreter. +However, +there is no guarantee that such code does anything sensible. +(None can be given, because the halting problem is unsolvable.) +If no files are given, then +luac +loads +luac.out +and tests its contents. +No messages are displayed if the file passes the integrity test. +

+-s +strip debug information before writing the output file. +This saves some space in very large chunks, +but if errors occur when running these chunks, +then the error messages may not contain the full information they usually do +(line numbers and names of locals are lost). +

+-v +show version information. +

FILES

+

+luac.out +default output file +

SEE ALSO

+lua(1) +
+http://www.lua.org/ +

DIAGNOSTICS

+Error messages should be self explanatory. +

AUTHORS

+L. H. de Figueiredo, +R. Ierusalimschy and +W. Celes +(lua AT tecgraf.puc-rio.br) + + + diff --git a/doc/manual.html b/doc/manual.html new file mode 100644 index 0000000..2a92d2a --- /dev/null +++ b/doc/manual.html @@ -0,0 +1,4612 @@ + + + + +Lua: 5.0 reference manual + + + + +
+

+Lua +Lua 5.0 Reference Manual +

+ +by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes +

+ +Copyright +© 2003 Tecgraf, PUC-Rio. All rights reserved. + +


+ +

+

+ + + + +

1 - Introduction

+ +

Lua is an extension programming language designed to support +general procedural programming with data description +facilities. +It also offers good support for object-oriented programming, +functional programming, and data-driven programming. +Lua is intended to be used as a powerful, light-weight +configuration language for any program that needs one. +Lua is implemented as a library, written in clean C +(that is, in the common subset of ANSI C and C++). + +

Being an extension language, Lua has no notion of a "main" program: +it only works embedded in a host client, +called the embedding program or simply the host. +This host program can invoke functions to execute a piece of Lua code, +can write and read Lua variables, +and can register C functions to be called by Lua code. +Through the use of C functions, Lua can be augmented to cope with +a wide range of different domains, +thus creating customized programming languages sharing a syntactical framework. + +

The Lua distribution includes a stand-alone embedding program, +lua, that uses the Lua library to offer a complete Lua interpreter. + +

Lua is free software, +and is provided as usual with no guarantees, +as stated in its copyright notice. +The implementation described in this manual is available +at Lua's official web site, www.lua.org. + +

Like any other reference manual, +this document is dry in places. +For a discussion of the decisions behind the design of Lua, +see the papers below, +which are available at Lua's web site. +

+ +

Lua means "moon" in Portuguese and is pronounced LOO-ah. + +

+

2 - The Language

+ +

This section describes the lexis, the syntax, and the semantics of Lua. +In other words, +this section describes +which tokens are valid, +how they can be combined, +and what their combinations mean. + +

The language constructs will be explained using the usual extended BNF, +in which +{a} means 0 or more a's, and +[a] means an optional a. +Non-terminals are shown in italics, +keywords are shown in bold, +and other terminal symbols are shown in typewriter font, +enclosed in single quotes. + +

2.1 - Lexical Conventions

+ +

Identifiers in Lua can be any string of letters, +digits, and underscores, +not beginning with a digit. +This coincides with the definition of identifiers in most languages. +(The definition of letter depends on the current locale: +any character considered alphabetic by the current locale +can be used in an identifier.) + +

The following keywords are reserved +and cannot be used as identifiers: + +

+       and       break     do        else      elseif
+       end       false     for       function  if
+       in        local     nil       not       or
+       repeat    return    then      true      until     while
+
+ +

Lua is a case-sensitive language: +and is a reserved word, but And and AND +are two different, valid identifiers. +As a convention, identifiers starting with an underscore followed by +uppercase letters (such as _VERSION) +are reserved for internal variables used by Lua. + +

The following strings denote other tokens: +

+       +     -     *     /     ^     =
+       ~=    <=    >=    <     >     ==
+       (     )     {     }     [     ]
+       ;     :     ,     .     ..    ...
+
+ +

Literal strings +can be delimited by matching single or double quotes, +and can contain the following C-like escape sequences: +

+Moreover, a `\newline´ +(that is, a backslash followed by a real newline) +results in a newline in the string. +A character in a string may also be specified by its numerical value +using the escape sequence `\ddd´, +where ddd is a sequence of up to three decimal digits. +Strings in Lua may contain any 8-bit value, including embedded zeros, +which can be specified as `\0´. + +

Literal strings can also be delimited by matching double square brackets +[[ · · · ]]. +Literals in this bracketed form may run for several lines, +may contain nested [[ · · · ]] pairs, +and do not interpret any escape sequences. +For convenience, +when the opening `[[´ is immediately followed by a newline, +the newline is not included in the string. +As an example, in a system using ASCII +(in which `a´ is coded as 97, +newline is coded as 10, and `1´ is coded as 49), +the four literals below denote the same string: +

+      (1)   "alo\n123\""
+      (2)   '\97lo\10\04923"'
+      (3)   [[alo
+            123"]]
+      (4)   [[
+            alo
+            123"]]
+
+ +

Numerical constants may be written with an optional decimal part +and an optional decimal exponent. +Examples of valid numerical constants are +

+       3     3.0     3.1416  314.16e-2   0.31416E1
+
+ +

Comments start anywhere outside a string with a +double hyphen (--). +If the text immediately after -- is different from [[, +the comment is a short comment, +which runs until the end of the line. +Otherwise, it is a long comment, +which runs until the corresponding ]]. +Long comments may run for several lines +and may contain nested [[ · · · ]] pairs. + +

For convenience, +the first line of a chunk is skipped if it starts with #. +This facility allows the use of Lua as a script interpreter +in Unix systems (see 6). + +

2.2 - Values and Types

+ +

Lua is a dynamically typed language. +That means that +variables do not have types; only values do. +There are no type definitions in the language. +All values carry their own type. + +

There are eight basic types in Lua: +nil, boolean, number, +string, function, userdata, thread, and table. +Nil is the type of the value nil, +whose main property is to be different from any other value; +usually it represents the absence of a useful value. +Boolean is the type of the values false and true. +In Lua, both nil and false make a condition false; +any other value makes it true. +Number represents real (double-precision floating-point) numbers. +(It is easy to build Lua interpreters that use other +internal representations for numbers, +such as single-precision float or long integers.) +String represents arrays of characters. + +Lua is 8-bit clean: +Strings may contain any 8-bit character, +including embedded zeros ('\0') (see 2.1). + +

Functions are first-class values in Lua. +That means that functions can be stored in variables, +passed as arguments to other functions, and returned as results. +Lua can call (and manipulate) functions written in Lua and +functions written in C +(see 2.5.7). + +

The type userdata is provided to allow arbitrary C data to +be stored in Lua variables. +This type corresponds to a block of raw memory +and has no pre-defined operations in Lua, +except assignment and identity test. +However, by using metatables, +the programmer can define operations for userdata values +(see 2.8). +Userdata values cannot be created or modified in Lua, +only through the C API. +This guarantees the integrity of data owned by the host program. + +

The type thread represents independent threads of execution +and it is used to implement coroutines. + +

The type table implements associative arrays, +that is, arrays that can be indexed not only with numbers, +but with any value (except nil). +Moreover, +tables can be heterogeneous, +that is, they can contain values of all types (except nil). +Tables are the sole data structuring mechanism in Lua; +they may be used to represent ordinary arrays, +symbol tables, sets, records, graphs, trees, etc. +To represent records, Lua uses the field name as an index. +The language supports this representation by +providing a.name as syntactic sugar for a["name"]. +There are several convenient ways to create tables in Lua +(see 2.5.6). + +

Like indices, +the value of a table field can be of any type (except nil). +In particular, +because functions are first class values, +table fields may contain functions. +Thus tables may also carry methods (see 2.5.8). + +

Tables, functions, and userdata values are objects: +variables do not actually contain these values, +only references to them. +Assignment, parameter passing, and function returns +always manipulate references to such values; +these operations do not imply any kind of copy. + +

The library function type returns a string describing the type +of a given value (see 5.1). + +

2.2.1 - Coercion

+ +

Lua provides automatic conversion between +string and number values at run time. +Any arithmetic operation applied to a string tries to convert +that string to a number, following the usual rules. +Conversely, whenever a number is used where a string is expected, +the number is converted to a string, in a reasonable format. +For complete control of how numbers are converted to strings, +use the format function from the string library (see 5.3). + +

2.3 - Variables

+ +

Variables are places that store values. + +There are three kinds of variables in Lua: +global variables, local variables, and table fields. + +

A single name can denote a global variable or a local variable +(or a formal parameter of a function, +which is a particular form of local variable): +

+	var ::= Name
+
+Variables are assumed to be global unless explicitly declared local +(see 2.4.7). +Local variables are lexically scoped: +Local variables can be freely accessed by functions +defined inside their scope (see 2.6). + +

Before the first assignment to a variable, its value is nil. + +

Square brackets are used to index a table: +

+	var ::= prefixexp `[´ exp `]´
+
+The first expression (prefixexp)should result in a table value; +the second expression (exp) +identifies a specific entry inside that table. +The expression denoting the table to be indexed has a restricted syntax; +see 2.5 for details. + +

The syntax var.NAME is just syntactic sugar for +var["NAME"]: +

+	var ::= prefixexp `.´ Name
+
+ +

The meaning of accesses to global variables +and table fields can be changed via metatables. +An access to an indexed variable t[i] is equivalent to +a call gettable_event(t,i). +(See 2.8 for a complete description of the +gettable_event function. +This function is not defined or callable in Lua. +We use it here only for explanatory purposes.) + +

All global variables live as fields in ordinary Lua tables, +called environment tables or simply environments. +Functions written in C and exported to Lua (C functions) +all share a common global environment. +Each function written in Lua (a Lua function) +has its own reference to an environment, +so that all global variables in that function +will refer to that environment table. +When a function is created, +it inherits the environment from the function that created it. +To change or get the environment table of a Lua function, +you call setfenv or getfenv (see 5.1). + +

An access to a global variable x +is equivalent to _env.x, +which in turn is equivalent to +

+       gettable_event(_env, "x")
+
+where _env is the environment of the running function. +(The _env variable is not defined in Lua. +We use it here only for explanatory purposes.) + +

2.4 - Statements

+ +

Lua supports an almost conventional set of statements, +similar to those in Pascal or C. +This set includes +assignment, control structures, procedure calls, +table constructors, and variable declarations. + +

2.4.1 - Chunks

+ +

The unit of execution of Lua is called a chunk. +A chunk is simply a sequence of statements, +which are executed sequentially. +Each statement can be optionally followed by a semicolon: +

+	chunk ::= {stat [`;´]}
+
+ +

Lua handles a chunk as the body of an anonymous function (see 2.5.8). +As such, chunks can define local variables and return values. + +

A chunk may be stored in a file or in a string inside the host program. +When a chunk is executed, first it is pre-compiled into opcodes for +a virtual machine, +and then the compiled code is executed +by an interpreter for the virtual machine. + +

Chunks may also be pre-compiled into binary form; +see program luac for details. +Programs in source and compiled forms are interchangeable; +Lua automatically detects the file type and acts accordingly. + + +

2.4.2 - Blocks

+A block is a list of statements; +syntactically, a block is equal to a chunk: +
+	block ::= chunk
+
+ +

A block may be explicitly delimited to produce a single statement: +

+	stat ::= do block end
+
+Explicit blocks are useful +to control the scope of variable declarations. +Explicit blocks are also sometimes used to +add a return or break statement in the middle +of another block (see 2.4.4). + + +

2.4.3 - Assignment

+ +

Lua allows multiple assignment. +Therefore, the syntax for assignment +defines a list of variables on the left side +and a list of expressions on the right side. +The elements in both lists are separated by commas: +

+	stat ::= varlist1 `=´ explist1
+	varlist1 ::= var {`,´ var}
+	explist1 ::= exp {`,´ exp}
+
+Expressions are discussed in 2.5. + +

Before the assignment, +the list of values is adjusted to the length of +the list of variables. +If there are more values than needed, +the excess values are thrown away. +If there are fewer values than needed, +the list is extended with as many nil's as needed. +If the list of expressions ends with a function call, +then all values returned by that function call enter in the list of values, +before the adjustment +(except when the call is enclosed in parentheses; see 2.5). + +

The assignment statement first evaluates all its expressions +and only then are the assignments performed. +Thus the code +

+       i = 3
+       i, a[i] = i+1, 20
+
+sets a[3] to 20, without affecting a[4] +because the i in a[i] is evaluated (to 3) +before it is assigned 4. +Similarly, the line +
+       x, y = y, x
+
+exchanges the values of x and y. + +

The meaning of assignments to global variables +and table fields can be changed via metatables. +An assignment to an indexed variable t[i] = val is equivalent to +settable_event(t,i,val). +(See 2.8 for a complete description of the +settable_event function. +This function is not defined or callable in Lua. +We use it here only for explanatory purposes.) + +

An assignment to a global variable x = val +is equivalent to the assignment +_env.x = val, +which in turn is equivalent to +

+       settable_event(_env, "x", val)
+
+where _env is the environment of the running function. +(The _env variable is not defined in Lua. +We use it here only for explanatory purposes.) + +

2.4.4 - Control Structures

+The control structures +if, while, and repeat have the usual meaning and +familiar syntax: + + + +
+	stat ::= while exp do block end
+	stat ::= repeat block until exp
+	stat ::= if exp then block {elseif exp then block} [else block] end
+
+Lua also has a for statement, in two flavors (see 2.4.5). + +

The condition expression exp of a +control structure may return any value. +Both false and nil are considered false. +All values different from nil and false are considered true +(in particular, the number 0 and the empty string are also true). + +

The return statement is used to return values +from a function or from a chunk. + +Functions and chunks may return more than one value, +so the syntax for the return statement is +

+	stat ::= return [explist1]
+
+ +

The break statement can be used to terminate the execution of a +while, repeat, or for loop, +skipping to the next statement after the loop: + +

+	stat ::= break
+
+A break ends the innermost enclosing loop. + +

For syntactic reasons, return and break +statements can only be written as the last statement of a block. +If it is really necessary to return or break in the +middle of a block, +then an explicit inner block can be used, +as in the idioms +`do return end´ and +`do break end´, +because now return and break are the last statements in +their (inner) blocks. +In practice, +those idioms are only used during debugging. + +

2.4.5 - For Statement

+ +

The for statement has two forms: +one numeric and one generic. + + +

The numeric for loop repeats a block of code while a +control variable runs through an arithmetic progression. +It has the following syntax: +

+	stat ::= for Name `=´ exp `,´ exp [`,´ exp] do block end
+
+The block is repeated for name starting at the value of +the first exp, until it passes the second exp by steps of the +third exp. +More precisely, a for statement like +
+       for var = e1, e2, e3 do block end
+
+is equivalent to the code: +
+       do
+         local var, _limit, _step = tonumber(e1), tonumber(e2), tonumber(e3)
+         if not (var and _limit and _step) then error() end
+         while (_step>0 and var<=_limit) or (_step<=0 and var>=_limit) do
+           block
+           var = var + _step
+         end
+       end
+
+Note the following: + + +

The generic for statement works over functions, +called iterators. +For each iteration, it calls its iterator function to produce a new value, +stopping when the new value is nil. +The generic for loop has the following syntax: +

+	stat ::= for Name {`,´ Name} in explist1 do block end
+
+A for statement like +
+       for var_1, ..., var_n in explist do block end
+
+is equivalent to the code: +
+       do
+         local _f, _s, var_1 = explist
+         local var_2, ... , var_n
+         while true do
+           var_1, ..., var_n = _f(_s, var_1)
+           if var_1 == nil then break end
+           block
+         end
+       end
+
+Note the following: + + +

2.4.6 - Function Calls as Statements

+To allow possible side-effects, +function calls can be executed as statements: +
+	stat ::= functioncall
+
+In this case, all returned values are thrown away. +Function calls are explained in 2.5.7. + +

2.4.7 - Local Declarations

+Local variables may be declared anywhere inside a block. +The declaration may include an initial assignment: +
+	stat ::= local namelist [`=´ explist1]
+	namelist ::= Name {`,´ Name}
+
+If present, an initial assignment has the same semantics +of a multiple assignment (see 2.4.3). +Otherwise, all variables are initialized with nil. + +

A chunk is also a block (see 2.4.1), +so local variables can be declared in a chunk outside any explicit block. +Such local variables die when the chunk ends. + +

The visibility rules for local variables are explained in 2.6. + +

2.5 - Expressions

+ +

+The basic expressions in Lua are the following: +

+	exp ::= prefixexp
+	exp ::= nil | false | true
+	exp ::= Number
+	exp ::= Literal
+	exp ::= function
+	exp ::= tableconstructor
+	prefixexp ::= var | functioncall | `(´ exp `)´
+
+ +

Numbers and literal strings are explained in 2.1; +variables are explained in 2.3; +function definitions are explained in 2.5.8; +function calls are explained in 2.5.7; +table constructors are explained in 2.5.6. + + +

An expression enclosed in parentheses always results in only one value. +Thus, +(f(x,y,z)) is always a single value, +even if f returns several values. +(The value of (f(x,y,z)) is the first value returned by f +or nil if f does not return any values.) + +

Expressions can also be built with arithmetic operators, relational operators, +and logical operators, all of which are explained below. + +

2.5.1 - Arithmetic Operators

+Lua supports the usual arithmetic operators: +the binary + (addition), +- (subtraction), * (multiplication), +/ (division), and ^ (exponentiation); +and unary - (negation). +If the operands are numbers, or strings that can be converted to +numbers (see 2.2.1), +then all operations except exponentiation have the usual meaning. +Exponentiation calls a global function __pow; +otherwise, an appropriate metamethod is called (see 2.8). +The standard mathematical library defines function __pow, +giving the expected meaning to exponentiation +(see 5.5). + +

2.5.2 - Relational Operators

+The relational operators in Lua are +
+       ==    ~=    <     >     <=    >=
+
+These operators always result in false or true. + +

Equality (==) first compares the type of its operands. +If the types are different, then the result is false. +Otherwise, the values of the operands are compared. +Numbers and strings are compared in the usual way. +Objects (tables, userdata, threads, and functions) +are compared by reference: +Two objects are considered equal only if they are the same object. +Every time you create a new object (a table, userdata, or function), +this new object is different from any previously existing object. + +

You can change the way that Lua compares tables and userdata +using the "eq" metamethod (see 2.8). + +

The conversion rules of 2.2.1 +do not apply to equality comparisons. +Thus, "0"==0 evaluates to false, +and t[0] and t["0"] denote different +entries in a table. + + +

The operator ~= is exactly the negation of equality (==). + +

The order operators work as follows. +If both arguments are numbers, then they are compared as such. +Otherwise, if both arguments are strings, +then their values are compared according to the current locale. +Otherwise, Lua tries to call the "lt" or the "le" +metamethod (see 2.8). + +

2.5.3 - Logical Operators

+The logical operators in Lua are + +
+       and   or    not
+
+Like the control structures (see 2.4.4), +all logical operators consider both false and nil as false +and anything else as true. + + +

The operator not always return false or true. + +

The conjunction operator and returns its first argument +if this value is false or nil; +otherwise, and returns its second argument. +The disjunction operator or returns its first argument +if this value is different from nil and false; +otherwise, or returns its second argument. +Both and and or use short-cut evaluation, +that is, +the second operand is evaluated only if necessary. +For example, +

+       10 or error()       -> 10
+       nil or "a"          -> "a"
+       nil and 10          -> nil
+       false and error()   -> false
+       false and nil       -> false
+       false or nil        -> nil
+       10 and 20           -> 20
+
+ +

2.5.4 - Concatenation

+The string concatenation operator in Lua is +denoted by two dots (`..´). +If both operands are strings or numbers, then they are converted to +strings according to the rules mentioned in 2.2.1. +Otherwise, the "concat" metamethod is called (see 2.8). + +

2.5.5 - Precedence

+Operator precedence in Lua follows the table below, +from lower to higher priority: +
+       or
+       and
+       <     >     <=    >=    ~=    ==
+       ..
+       +     -
+       *     /
+       not   - (unary)
+       ^
+
+You can use parentheses to change the precedences in an expression. +The concatenation (`..´) and exponentiation (`^´) +operators are right associative. +All other binary operators are left associative. + +

2.5.6 - Table Constructors

+Table constructors are expressions that create tables. +Every time a constructor is evaluated, a new table is created. +Constructors can be used to create empty tables, +or to create a table and initialize some of its fields. +The general syntax for constructors is +
+	tableconstructor ::= `{´ [fieldlist] `}´
+	fieldlist ::= field {fieldsep field} [fieldsep]
+	field ::= `[´ exp `]´ `=´ exp | Name `=´ exp | exp
+	fieldsep ::= `,´ | `;´
+
+ +

Each field of the form [exp1] = exp2 adds to the new table an entry +with key exp1 and value exp2. +A field of the form name = exp is equivalent to +["name"] = exp. +Finally, fields of the form exp are equivalent to +[i] = exp, where i are consecutive numerical integers, +starting with 1. +Fields in the other formats do not affect this counting. +For example, +

+       a = {[f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45}
+
+is equivalent to +
+       do
+         local temp = {}
+         temp[f(1)] = g
+         temp[1] = "x"         -- 1st exp
+         temp[2] = "y"         -- 2nd exp
+         temp.x = 1            -- temp["x"] = 1
+         temp[3] = f(x)        -- 3rd exp
+         temp[30] = 23
+         temp[4] = 45          -- 4th exp
+         a = temp
+       end
+
+ +

If the last field in the list has the form exp +and the expression is a function call, +then all values returned by the call enter the list consecutively +(see 2.5.7). +To avoid this, +enclose the function call in parentheses (see 2.5). + +

The field list may have an optional trailing separator, +as a convenience for machine-generated code. + +

2.5.7 - Function Calls

+A function call in Lua has the following syntax: +
+	functioncall ::= prefixexp args
+
+In a function call, +first prefixexp and args are evaluated. +If the value of prefixexp has type function, +then that function is called +with the given arguments. +Otherwise, its "call" metamethod is called, +having as first parameter the value of prefixexp, +followed by the original call arguments +(see 2.8). + +

The form +

+	functioncall ::= prefixexp `:´ Name args
+
+can be used to call "methods". +A call v:name(...) +is syntactic sugar for v.name(v,...), +except that v is evaluated only once. + +

Arguments have the following syntax: +

+	args ::= `(´ [explist1] `)´
+	args ::= tableconstructor
+	args ::= Literal
+
+All argument expressions are evaluated before the call. +A call of the form f{...} is syntactic sugar for +f({...}), that is, +the argument list is a single new table. +A call of the form f'...' +(or f"..." or f[[...]]) is syntactic sugar for +f('...'), that is, +the argument list is a single literal string. + +

Because a function can return any number of results +(see 2.4.4), +the number of results must be adjusted before they are used. +If the function is called as a statement (see 2.4.6), +then its return list is adjusted to zero elements, +thus discarding all returned values. +If the function is called inside another expression +or in the middle of a list of expressions, +then its return list is adjusted to one element, +thus discarding all returned values except the first one. +If the function is called as the last element of a list of expressions, +then no adjustment is made +(unless the call is enclosed in parentheses). + +

Here are some examples: +

+       f()                -- adjusted to 0 results
+       g(f(), x)          -- f() is adjusted to 1 result
+       g(x, f())          -- g gets x plus all values returned by f()
+       a,b,c = f(), x     -- f() is adjusted to 1 result (and c gets nil)
+       a,b,c = x, f()     -- f() is adjusted to 2 results
+       a,b,c = f()        -- f() is adjusted to 3 results
+       return f()         -- returns all values returned by f()
+       return x,y,f()     -- returns x, y, and all values returned by f()
+       {f()}              -- creates a list with all values returned by f()
+       {f(), nil}         -- f() is adjusted to 1 result
+
+ +

If you enclose a function call in parentheses, +then it is adjusted to return exactly one value: +

+       return x,y,(f())   -- returns x, y, and the first value from f()
+       {(f())}            -- creates a table with exactly one element
+
+ +

As an exception to the free-format syntax of Lua, +you cannot put a line break before the `(´ in a function call. +That restriction avoids some ambiguities in the language. +If you write +

+       a = f
+       (g).x(a)
+
+Lua would read that as a = f(g).x(a). +So, if you want two statements, you must add a semi-colon between them. +If you actually want to call f, +you must remove the line break before (g). + +

A call of the form return functioncall is called +a tail call. +Lua implements proper tail calls +(or proper tail recursion): +In a tail call, +the called function reuses the stack entry of the calling function. +Therefore, there is no limit on the number of nested tail calls that +a program can execute. +However, a tail call erases any debug information about the +calling function. +Note that a tail call only happens with a particular syntax, +where the return has one single function call as argument; +this syntax makes the calling function returns exactly +the returns of the called function. +So, all the following examples are not tails calls: +

+  return (f(x))        -- results adjusted to 1
+  return 2 * f(x)
+  return x, f(x)       -- additional results
+  f(x); return         -- results discarded
+  return x or f(x)     -- results adjusted to 1
+
+ +

2.5.8 - Function Definitions

+ +

The syntax for function definition is +

+	function ::= function funcbody
+	funcbody ::= `(´ [parlist1] `)´ block end
+
+ +

The following syntactic sugar simplifies function definitions: +

+	stat ::= function funcname funcbody
+	stat ::= local function Name funcbody
+	funcname ::= Name {`.´ Name} [`:´ Name]
+
+The statement +
+       function f () ... end
+
+translates to +
+       f = function () ... end
+
+The statement +
+       function t.a.b.c.f () ... end
+
+translates to +
+       t.a.b.c.f = function () ... end
+
+The statement +
+       local function f () ... end
+
+translates to +
+       local f; f = function () ... end
+
+ +

A function definition is an executable expression, +whose value has type function. +When Lua pre-compiles a chunk, +all its function bodies are pre-compiled too. +Then, whenever Lua executes the function definition, +the function is instantiated (or closed). +This function instance (or closure) +is the final value of the expression. +Different instances of the same function +may refer to different external local variables +and may have different environment tables. + +

Parameters act as local variables that are +initialized with the argument values: +

+	parlist1 ::= namelist [`,´ `...´]
+	parlist1 ::= `...´
+
+When a function is called, +the list of arguments is adjusted to +the length of the list of parameters, +unless the function is a variadic or vararg function, +which is +indicated by three dots (`...´) at the end of its parameter list. +A vararg function does not adjust its argument list; +instead, it collects all extra arguments into an implicit parameter, +called arg. +The value of arg is a table, +with a field n that holds the number of extra arguments +and with the extra arguments at positions 1, 2, ..., n. + +

As an example, consider the following definitions: +

+       function f(a, b) end
+       function g(a, b, ...) end
+       function r() return 1,2,3 end
+
+Then, we have the following mapping from arguments to parameters: +
+       CALL            PARAMETERS
+
+       f(3)             a=3, b=nil
+       f(3, 4)          a=3, b=4
+       f(3, 4, 5)       a=3, b=4
+       f(r(), 10)       a=1, b=10
+       f(r())           a=1, b=2
+
+       g(3)             a=3, b=nil, arg={n=0}
+       g(3, 4)          a=3, b=4,   arg={n=0}
+       g(3, 4, 5, 8)    a=3, b=4,   arg={5, 8; n=2}
+       g(5, r())        a=5, b=1,   arg={2, 3; n=2}
+
+ +

Results are returned using the return statement (see 2.4.4). +If control reaches the end of a function +without encountering a return statement, +then the function returns with no results. + +

The colon syntax +is used for defining methods, +that is, functions that have an implicit extra parameter self. +Thus, the statement +

+       function t.a.b.c:f (...) ... end
+
+is syntactic sugar for +
+       t.a.b.c.f = function (self, ...) ... end
+
+ +

2.6 - Visibility Rules

+ + +

Lua is a lexically scoped language. +The scope of variables begins at the first statement after +their declaration and lasts until the end of the innermost block that +includes the declaration. +For instance: +

+  x = 10                -- global variable
+  do                    -- new block
+    local x = x         -- new `x', with value 10
+    print(x)            --> 10
+    x = x+1
+    do                  -- another block
+      local x = x+1     -- another `x'
+      print(x)          --> 12
+    end
+    print(x)            --> 11
+  end
+  print(x)              --> 10  (the global one)
+
+Notice that, in a declaration like local x = x, +the new x being declared is not in scope yet, +and so the second x refers to the outside variable. + +

Because of the lexical scoping rules, +local variables can be freely accessed by functions +defined inside their scope. +For instance: +

+  local counter = 0
+  function inc (x)
+    counter = counter + x
+    return counter
+  end
+
+A local variable used by an inner function is called +an upvalue, or external local variable, +inside the inner function. + +

Notice that each execution of a local statement +defines new local variables. +Consider the following example: +

+  a = {}
+  local x = 20
+  for i=1,10 do
+    local y = 0
+    a[i] = function () y=y+1; return x+y end
+  end
+
+The loop creates ten closures +(that is, ten instances of the anonymous function). +Each of these closures uses a different y variable, +while all of them share the same x. + +

2.7 - Error Handling

+ +

Because Lua is an extension language, +all Lua actions start from C code in the host program +calling a function from the Lua library (see 3.15). +Whenever an error occurs during Lua compilation or execution, +control returns to C, +which can take appropriate measures +(such as print an error message). + +

Lua code can explicitly generate an error by calling the +error function (see 5.1). +If you need to catch errors in Lua, +you can use the pcall function (see 5.1). + +

2.8 - Metatables

+ +

Every table and userdata object in Lua may have a metatable. +This metatable is an ordinary Lua table +that defines the behavior of the original table and userdata +under certain special operations. +You can change several aspects of the behavior +of an object by setting specific fields in its metatable. +For instance, when an object is the operand of an addition, +Lua checks for a function in the field "__add" in its metatable. +If it finds one, +Lua calls that function to perform the addition. + +

We call the keys in a metatable events +and the values metamethods. +In the previous example, the event is "add" +and the metamethod is the function that performs the addition. + +

You can query and change the metatable of an object +through the set/getmetatable +functions (see 5.1). + +

A metatable may control how an object behaves in arithmetic operations, +order comparisons, concatenation, and indexing. +A metatable can also define a function to be called when a userdata +is garbage collected. +For each of those operations Lua associates a specific key +called an event. +When Lua performs one of those operations over a table or a userdata, +it checks whether that object has a metatable with the corresponding event. +If so, the value associated with that key (the metamethod) +controls how Lua will perform the operation. + +

Metatables control the operations listed next. +Each operation is identified by its corresponding name. +The key for each operation is a string with its name prefixed by +two underscores; +for instance, the key for operation "add" is the +string "__add". +The semantics of these operations is better explained by a Lua function +describing how the interpreter executes that operation. + +

The code shown here in Lua is only illustrative; +the real behavior is hard coded in the interpreter +and it is much more efficient than this simulation. +All functions used in these descriptions +(rawget, tonumber, etc.) +are described in 5.1. +In particular, to retrieve the metamethod of a given object, +we use the expression +

+  metatable(obj)[event]
+
+This should be read as +
+  rawget(metatable(obj) or {}, event)
+
+That is, the access to a metamethod does not invoke other metamethods, +and the access to objects with no metatables does not fail +(it simply results in nil). + +

+ +

2.9 - Garbage Collection

+ +

Lua does automatic memory management. +That means that +you do not have to worry about allocating memory for new objects +and freeing it when the objects are no longer needed. +Lua manages memory automatically by running +a garbage collector from time to time +to collect all dead objects +(that is, those objects that are no longer accessible from Lua). +All objects in Lua are subject to automatic management: +tables, userdata, functions, threads, and strings. + +

Lua uses two numbers to control its garbage-collection cycles. +One number counts how many bytes of dynamic memory Lua is using; +the other is a threshold. +When the number of bytes crosses the threshold, +Lua runs the garbage collector, +which reclaims the memory of all dead objects. +The byte counter is adjusted, +and then the threshold is reset to twice the new value of the byte counter. + +

Through the C API, you can query those numbers +and change the threshold (see 3.7). +Setting the threshold to zero actually forces an immediate +garbage-collection cycle, +while setting it to a huge number effectively stops the garbage collector. +Using Lua code you have a more limited control over garbage-collection cycles, +through the gcinfo and collectgarbage functions +(see 5.1). + +

2.9.1 - Garbage-Collection Metamethods

+ +

Using the C API, +you can set garbage-collector metamethods for userdata (see 2.8). +These metamethods are also called finalizers. +Finalizers allow you to coordinate Lua's garbage collection +with external resource management +(such as closing files, network or database connections, +or freeing your own memory). + +

Free userdata with a field __gc in their metatables are not +collected immediately by the garbage collector. +Instead, Lua puts them in a list. +After the collection, +Lua does the equivalent of the following function +for each userdata in that list: +

+ function gc_event (udata)
+   local h = metatable(udata).__gc
+   if h then
+     h(udata)
+   end
+ end
+
+ +

At the end of each garbage-collection cycle, +the finalizers for userdata are called in reverse +order of their creation, +among those collected in that cycle. +That is, the first finalizer to be called is the one associated +with the userdata created last in the program. + +

2.9.2 - Weak Tables

+ +

A weak table is a table whose elements are +weak references. +A weak reference is ignored by the garbage collector. +In other words, +if the only references to an object are weak references, +then the garbage collector will collect that object. + +

A weak table can have weak keys, weak values, or both. +A table with weak keys allows the collection of its keys, +but prevents the collection of its values. +A table with both weak keys and weak values allows the collection of +both keys and values. +In any case, if either the key or the value is collected, +the whole pair is removed from the table. +The weakness of a table is controlled by the value of the +__mode field of its metatable. +If the __mode field is a string containing the character `k´, +the keys in the table are weak. +If __mode contains `v´, +the values in the table are weak. + +

After you use a table as a metatable, +you should not change the value of its field __mode. +Otherwise, the weak behavior of the tables controlled by this +metatable is undefined. + +

2.10 - Coroutines

+ +

Lua supports coroutines, +also called semi-coroutines +or collaborative multithreading. +A coroutine in Lua represents an independent thread of execution. +Unlike threads in multithread systems, however, +a coroutine only suspends its execution by explicitly calling +a yield function. + +

You create a coroutine with a call to coroutine.create. +Its sole argument is a function +that is the main function of the coroutine. +The create function only creates a new coroutine and +returns a handle to it (an object of type thread); +it does not start the coroutine execution. + +

When you first call coroutine.resume, +passing as its first argument the thread returned by coroutine.create, +the coroutine starts its execution, +at the first line of its main function. +Extra arguments passed to coroutine.resume are given as +parameters for the coroutine main function. +After the coroutine starts running, +it runs until it terminates or yields. + +

A coroutine can terminate its execution in two ways: +Normally, when its main function returns +(explicitly or implicitly, after the last instruction); +and abnormally, if there is an unprotected error. +In the first case, coroutine.resume returns true, +plus any values returned by the coroutine main function. +In case of errors, coroutine.resume returns false +plus an error message. + +

A coroutine yields by calling coroutine.yield. +When a coroutine yields, +the corresponding coroutine.resume returns immediately, +even if the yield happens inside nested function calls +(that is, not in the main function, +but in a function directly or indirectly called by the main function). +In the case of a yield, coroutine.resume also returns true, +plus any values passed to coroutine.yield. +The next time you resume the same coroutine, +it continues its execution from the point where it yielded, +with the call to coroutine.yield returning any extra +arguments passed to coroutine.resume. + +

The coroutine.wrap function creates a coroutine +like coroutine.create, +but instead of returning the coroutine itself, +it returns a function that, when called, resumes the coroutine. +Any arguments passed to that function +go as extra arguments to resume. +The function returns all the values returned by resume, +except the first one (the boolean error code). +Unlike coroutine.resume, +this function does not catch errors; +any error is propagated to the caller. + +

As an example, +consider the next code: +

+function foo1 (a)
+  print("foo", a)
+  return coroutine.yield(2*a)
+end
+
+co = coroutine.create(function (a,b)
+      print("co-body", a, b)
+      local r = foo1(a+1)
+      print("co-body", r)
+      local r, s = coroutine.yield(a+b, a-b)
+      print("co-body", r, s)
+      return b, "end"
+end)
+       
+a, b = coroutine.resume(co, 1, 10)
+print("main", a, b)
+a, b, c = coroutine.resume(co, "r")
+print("main", a, b, c)
+a, b, c = coroutine.resume(co, "x", "y")
+print("main", a, b, c)
+a, b = coroutine.resume(co, "x", "y")
+print("main", a, b)
+
+When you run it, it produces the following output: +
+co-body 1       10
+foo     2
+main    true    4
+co-body r
+main    true    11      -9
+co-body x       y
+main    true    10      end
+main    false   cannot resume dead coroutine
+
+ +

+

3 - The Application Program Interface

+ + +

This section describes the C API for Lua, that is, +the set of C functions available to the host program to communicate +with Lua. +All API functions and related types and constants +are declared in the header file lua.h. + +

Even when we use the term "function", +any facility in the API may be provided as a macro instead. +All such macros use each of its arguments exactly once +(except for the first argument, which is always a Lua state), +and so do not generate hidden side-effects. + +

3.1 - States

+ +

The Lua library is fully reentrant: +it has no global variables. + +The whole state of the Lua interpreter +(global variables, stack, etc.) +is stored in a dynamically allocated structure of type lua_State. + +A pointer to this state must be passed as the first argument to +every function in the library, except to lua_open, +which creates a Lua state from scratch. + +

Before calling any API function, +you must create a state by calling lua_open: +

+       lua_State *lua_open (void);
+
+ + +

To release a state created with lua_open, call lua_close: +

+       void lua_close (lua_State *L);
+
+ +This function destroys all objects in the given Lua state +(calling the corresponding garbage-collection metamethods, if any) +and frees all dynamic memory used by that state. +On several platforms, you may not need to call this function, +because all resources are naturally released when the host program ends. +On the other hand, +long-running programs, +such as a daemon or a web server, +might need to release states as soon as they are not needed, +to avoid growing too large. + +

3.2 - The Stack and Indices

+ +

Lua uses a virtual stack to pass values to and from C. +Each element in this stack represents a Lua value +(nil, number, string, etc.). + +

Whenever Lua calls C, the called function gets a new stack, +which is independent of previous stacks and of stacks of +C functions that are still active. +That stack initially contains any arguments to the C function, +and it is where the C function pushes its results to be returned to the caller (see 3.16) +to be returned to the caller. + +

For convenience, +most query operations in the API do not follow a strict stack discipline. +Instead, they can refer to any element in the stack by using an index: +A positive index represents an absolute stack position +(starting at 1); +a negative index represents an offset from the top of the stack. +More specifically, if the stack has n elements, +then index 1 represents the first element +(that is, the element that was pushed onto the stack first) +and +index n represents the last element; +index -1 also represents the last element +(that is, the element at the top) +and index -n represents the first element. +We say that an index is valid +if it lies between 1 and the stack top +(that is, if 1 <= abs(index) <= top). + + +

At any time, you can get the index of the top element by calling +lua_gettop: +

+       int lua_gettop (lua_State *L);
+
+Because indices start at 1, +the result of lua_gettop is equal to the number of elements in the stack +(and so 0 means an empty stack). + +

When you interact with Lua API, +you are responsible for controlling stack overflow. +The function +

+       int lua_checkstack (lua_State *L, int extra);
+
+ +grows the stack size to top + extra elements; +it returns false if it cannot grow the stack to that size. +This function never shrinks the stack; +if the stack is already larger than the new size, +it is left unchanged. + +

Whenever Lua calls C, +it ensures that at least LUA_MINSTACK stack positions are available. +LUA_MINSTACK is defined in lua.h as 20, +so that usually you do not have to worry about stack space +unless your code has loops pushing elements onto the stack. + +

Most query functions accept as indices any value inside the +available stack space, that is, indices up to the maximum stack size +you have set through lua_checkstack. +Such indices are called acceptable indices. +More formally, we define an acceptable index +as follows: +

+     (index < 0 && abs(index) <= top) || (index > 0 && index <= stackspace)
+
+Note that 0 is never an acceptable index. + +

Unless otherwise noted, +any function that accepts valid indices can also be called with +pseudo-indices, +which represent some Lua values that are accessible to the C code +but are not in the stack. +Pseudo-indices are used to access the global environment, +the registry, and the upvalues of a C function (see 3.17). + +

3.3 - Stack Manipulation

+The API offers the following functions for basic stack manipulation: +
+       void lua_settop    (lua_State *L, int index);
+       void lua_pushvalue (lua_State *L, int index);
+       void lua_remove    (lua_State *L, int index);
+       void lua_insert    (lua_State *L, int index);
+       void lua_replace   (lua_State *L, int index);
+
+ + + +

lua_settop accepts any acceptable index, +or 0, +and sets the stack top to that index. +If the new top is larger than the old one, +then the new elements are filled with nil. +If index is 0, then all stack elements are removed. +A useful macro defined in the lua.h is +

+       #define lua_pop(L,n)   lua_settop(L, -(n)-1)
+
+ +which pops n elements from the stack. + +

lua_pushvalue pushes onto the stack a copy of the element +at the given index. +lua_remove removes the element at the given position, +shifting down the elements above that position to fill the gap. +lua_insert moves the top element into the given position, +shifting up the elements above that position to open space. +lua_replace moves the top element into the given position, +without shifting any element (therefore replacing the value at +the given position). +All these functions accept only valid indices. +(You cannot call lua_remove or lua_insert with +pseudo-indices, as they do not represent a stack position.) + +

As an example, if the stack starts as 10 20 30 40 50* +(from bottom to top; the `*´ marks the top), +then +

+       lua_pushvalue(L, 3)    --> 10 20 30 40 50 30*
+       lua_pushvalue(L, -1)   --> 10 20 30 40 50 30 30*
+       lua_remove(L, -3)      --> 10 20 30 40 30 30*
+       lua_remove(L,  6)      --> 10 20 30 40 30*
+       lua_insert(L,  1)      --> 30 10 20 30 40*
+       lua_insert(L, -1)      --> 30 10 20 30 40*  (no effect)
+       lua_replace(L, 2)      --> 30 40 20 30*
+       lua_settop(L, -3)      --> 30 40*
+       lua_settop(L,  6)      --> 30 40 nil nil nil nil*
+
+ +

3.4 - Querying the Stack

+ +

To check the type of a stack element, +the following functions are available: +

+       int lua_type            (lua_State *L, int index);
+       int lua_isnil           (lua_State *L, int index);
+       int lua_isboolean       (lua_State *L, int index);
+       int lua_isnumber        (lua_State *L, int index);
+       int lua_isstring        (lua_State *L, int index);
+       int lua_istable         (lua_State *L, int index);
+       int lua_isfunction      (lua_State *L, int index);
+       int lua_iscfunction     (lua_State *L, int index);
+       int lua_isuserdata      (lua_State *L, int index);
+       int lua_islightuserdata (lua_State *L, int index);
+
+ + + + + +These functions can be called with any acceptable index. + +

lua_type returns the type of a value in the stack, +or LUA_TNONE for a non-valid index +(that is, if that stack position is "empty"). +The types returned by lua_type are coded by the following constants +defined in lua.h: +LUA_TNIL, +LUA_TNUMBER, +LUA_TBOOLEAN, +LUA_TSTRING, +LUA_TTABLE, +LUA_TFUNCTION, +LUA_TUSERDATA, +LUA_TTHREAD, +LUA_TLIGHTUSERDATA. +The following function translates these constants to strings: +

+       const char *lua_typename  (lua_State *L, int type);
+
+ + +

The lua_is* functions return 1 if the object is compatible +with the given type, and 0 otherwise. +lua_isboolean is an exception to this rule: +It succeeds only for boolean values +(otherwise it would be useless, +as any value has a boolean value). +They always return 0 for a non-valid index. +lua_isnumber accepts numbers and numerical strings; +lua_isstring accepts strings and numbers (see 2.2.1); +lua_isfunction accepts both Lua functions and C functions; +and lua_isuserdata accepts both full and light userdata. +To distinguish between Lua functions and C functions, +you can use lua_iscfunction. +To distinguish between full and light userdata, +you can use lua_islightuserdata. +To distinguish between numbers and numerical strings, +you can use lua_type. + +

The API also contains functions to compare two values in the stack: +

+       int lua_equal    (lua_State *L, int index1, int index2);
+       int lua_rawequal (lua_State *L, int index1, int index2);
+       int lua_lessthan (lua_State *L, int index1, int index2);
+
+ +lua_equal and lua_lessthan +are equivalent to their counterparts in Lua (see 2.5.2). +lua_rawequal compares the values for primitive equality, +without metamethods. +These functions return 0 (false) if any of the indices are non-valid. + +

3.5 - Getting Values from the Stack

+ +

To translate a value in the stack to a specific C type, +you can use the following conversion functions: +

+       int            lua_toboolean   (lua_State *L, int index);
+       lua_Number     lua_tonumber    (lua_State *L, int index);
+       const char    *lua_tostring    (lua_State *L, int index);
+       size_t         lua_strlen      (lua_State *L, int index);
+       lua_CFunction  lua_tocfunction (lua_State *L, int index);
+       void          *lua_touserdata  (lua_State *L, int index);
+       lua_State     *lua_tothread    (lua_State *L, int index);
+       void          *lua_topointer   (lua_State *L, int index);
+
+ + + +These functions can be called with any acceptable index. +When called with a non-valid index, +they act as if the given value had an incorrect type. + +

lua_toboolean converts the Lua value at the given index +to a C "boolean" value (0 or 1). +Like all tests in Lua, lua_toboolean returns 1 for any Lua value +different from false and nil; +otherwise it returns 0. +It also returns 0 when called with a non-valid index. +(If you want to accept only real boolean values, +use lua_isboolean to test the type of the value.) + +

lua_tonumber converts the Lua value at the given index +to a number (by default, lua_Number is double). + +The Lua value must be a number or a string convertible to number +(see 2.2.1); otherwise, lua_tonumber returns 0. + +

lua_tostring converts the Lua value at the given index to a string +(const char*). +The Lua value must be a string or a number; +otherwise, the function returns NULL. +If the value is a number, +then lua_tostring also +changes the actual value in the stack to a string. +(This change confuses lua_next +when lua_tostring is applied to keys.) +lua_tostring returns a fully aligned pointer +to a string inside the Lua state. +This string always has a zero ('\0') +after its last character (as in C), +but may contain other zeros in its body. +If you do not know whether a string may contain zeros, +you can use lua_strlen to get its actual length. +Because Lua has garbage collection, +there is no guarantee that the pointer returned by lua_tostring +will be valid after the corresponding value is removed from the stack. +If you need the string after the current function returns, +then you should duplicate it or put it into the registry (see 3.18). + +

lua_tocfunction converts a value in the stack to a C function. +This value must be a C function; +otherwise, lua_tocfunction returns NULL. +The type lua_CFunction is explained in 3.16. + +

lua_tothread converts a value in the stack to a Lua thread +(represented as lua_State *). +This value must be a thread; +otherwise, lua_tothread returns NULL. + +

lua_topointer converts a value in the stack to a generic +C pointer (void *). +The value may be a userdata, a table, a thread, or a function; +otherwise, lua_topointer returns NULL. +Lua ensures that different objects of the +same type return different pointers. +There is no direct way to convert the pointer back to its original value. +Typically this function is used for debug information. + +

lua_touserdata is explained in 3.8. + +

3.6 - Pushing Values onto the Stack

+ +

The API has the following functions to +push C values onto the stack: +

+       void lua_pushboolean       (lua_State *L, int b);
+       void lua_pushnumber        (lua_State *L, lua_Number n);
+       void lua_pushlstring       (lua_State *L, const char *s, size_t len);
+       void lua_pushstring        (lua_State *L, const char *s);
+       void lua_pushnil           (lua_State *L);
+       void lua_pushcfunction     (lua_State *L, lua_CFunction f);
+       void lua_pushlightuserdata (lua_State *L, void *p);
+
+ +

+ + +These functions receive a C value, +convert it to a corresponding Lua value, +and push the result onto the stack. +In particular, lua_pushlstring and lua_pushstring +make an internal copy of the given string. +lua_pushstring can only be used to push proper C strings +(that is, strings that end with a zero and do not contain embedded zeros); +otherwise, you should use the more general lua_pushlstring, +which accepts an explicit size. + +

You can also push "formatted" strings: +

+       const char *lua_pushfstring  (lua_State *L, const char *fmt, ...);
+       const char *lua_pushvfstring (lua_State *L, const char *fmt, va_list argp);
+
+ +These functions push onto the stack a formatted string +and return a pointer to that string. +They are similar to sprintf and vsprintf, +but with some important differences: + + +

The function +

+       void lua_concat (lua_State *L, int n);
+
+ +concatenates the n values at the top of the stack, +pops them, and leaves the result at the top. +If n is 1, the result is that single string +(that is, the function does nothing); +if n is 0, the result is the empty string. +Concatenation is done following the usual semantics of Lua +(see 2.5.4). + +

3.7 - Controlling Garbage Collection

+ +

Lua uses two numbers to control its garbage collection: +the count and the threshold (see 2.9). +The first counts the amount of memory in use by Lua; +when the count reaches the threshold, +Lua runs its garbage collector. +After the collection, the count is updated +and the threshold is set to twice the count value. + +

You can access the current values of these two numbers through the +following functions: +

+       int  lua_getgccount     (lua_State *L);
+       int  lua_getgcthreshold (lua_State *L);
+
+ +Both return their respective values in Kbytes. +You can change the threshold value with +
+       void  lua_setgcthreshold (lua_State *L, int newthreshold);
+
+ +Again, the newthreshold value is given in Kbytes. +When you call this function, +Lua sets the new threshold and checks it against the byte counter. +If the new threshold is less than the byte counter, +then Lua immediately runs the garbage collector. +In particular +lua_setgcthreshold(L,0) forces a garbage collection. +After the collection, +a new threshold is set according to the previous rule. + +

3.8 - Userdata

+ +

Userdata represents C values in Lua. +Lua supports two types of userdata: +full userdata and light userdata. + +

A full userdata represents a block of memory. +It is an object (like a table): +You must create it, it can have its own metatable, +and you can detect when it is being collected. +A full userdata is only equal to itself (under raw equality). + +

A light userdata represents a pointer. +It is a value (like a number): +You do not create it, it has no metatables, +it is not collected (as it was never created). +A light userdata is equal to "any" +light userdata with the same C address. + +

In Lua code, there is no way to test whether a userdata is full or light; +both have type userdata. +In C code, lua_type returns LUA_TUSERDATA for full userdata, +and LUA_TLIGHTUSERDATA for light userdata. + +

You can create a new full userdata with the following function: +

+       void *lua_newuserdata (lua_State *L, size_t size);
+
+ +This function allocates a new block of memory with the given size, +pushes on the stack a new userdata with the block address, +and returns this address. + +

To push a light userdata into the stack you use +lua_pushlightuserdata (see 3.6). + +

lua_touserdata (see 3.5) retrieves the value of a userdata. +When applied on a full userdata, it returns the address of its block; +when applied on a light userdata, it returns its pointer; +when applied on a non-userdata value, it returns NULL. + +

When Lua collects a full userdata, +it calls the userdata's gc metamethod, if any, +and then it frees the userdata's corresponding memory. + +

3.9 - Metatables

+ +

The following functions allow you to manipulate the metatables +of an object: +

+       int lua_getmetatable (lua_State *L, int index);
+       int lua_setmetatable (lua_State *L, int index);
+
+ +lua_getmetatable pushes on the stack the metatable of a given object. +If the index is not valid, +or if the object does not have a metatable, +lua_getmetatable returns 0 and pushes nothing on the stack. + +

lua_setmetatable pops a table from the stack and +sets it as the new metatable for the given object. +lua_setmetatable returns 0 when it cannot +set the metatable of the given object +(that is, when the object is neither a userdata nor a table); +even then it pops the table from the stack. + +

3.10 - Loading Lua Chunks

+ +

You can load a Lua chunk with lua_load: +

+       typedef const char * (*lua_Chunkreader)
+                                (lua_State *L, void *data, size_t *size);
+
+       int lua_load (lua_State *L, lua_Chunkreader reader, void *data,
+                                   const char *chunkname);
+
+ +The return values of lua_load are: + +If there are no errors, +lua_load pushes the compiled chunk as a Lua +function on top of the stack. +Otherwise, it pushes an error message. + +

lua_load automatically detects whether the chunk is text or binary, +and loads it accordingly (see program luac). + +

lua_load uses a user-supplied reader function to read the chunk. +Everytime it needs another piece of the chunk, +lua_load calls the reader, +passing along its data parameter. +The reader must return a pointer to a block of memory +with a new piece of the chunk +and set size to the block size. +To signal the end of the chunk, the reader returns NULL. +The reader function may return pieces of any size greater than zero. + +

In the current implementation, +the reader function cannot call any Lua function; +to ensure that, it always receives NULL as the Lua state. + +

The chunkname is used for error messages +and debug information (see 4). + +

See the auxiliary library (lauxlib.c) +for examples of how to use lua_load +and for some ready-to-use functions to load chunks +from files and strings. + +

3.11 - Manipulating Tables

+ +

Tables are created by calling +the function +

+       void lua_newtable (lua_State *L);
+
+ +This function creates a new, empty table and pushes it onto the stack. + +

To read a value from a table that resides somewhere in the stack, +call +

+       void lua_gettable (lua_State *L, int index);
+
+ +where index points to the table. +lua_gettable pops a key from the stack +and returns (on the stack) the contents of the table at that key. +The table is left where it was in the stack. +As in Lua, this function may trigger a metamethod +for the "index" event (see 2.8). +To get the real value of any table key, +without invoking any metamethod, +use the raw version: +
+       void lua_rawget (lua_State *L, int index);
+
+ + +

To store a value into a table that resides somewhere in the stack, +you push the key and then the value onto the stack, +and call +

+       void lua_settable (lua_State *L, int index);
+
+ +where index points to the table. +lua_settable pops from the stack both the key and the value. +The table is left where it was in the stack. +As in Lua, this operation may trigger a metamethod +for the "settable" or "newindex" events. +To set the real value of any table index, +without invoking any metamethod, +use the raw version: +
+       void lua_rawset (lua_State *L, int index);
+
+ + +

You can traverse a table with the function +

+       int lua_next (lua_State *L, int index);
+
+ +where index points to the table to be traversed. +The function pops a key from the stack, +and pushes a key-value pair from the table +(the "next" pair after the given key). +If there are no more elements, then lua_next returns 0 +(and pushes nothing). +Use a nil key to signal the start of a traversal. + +

A typical traversal looks like this: +

+       /* table is in the stack at index `t' */
+       lua_pushnil(L);  /* first key */
+       while (lua_next(L, t) != 0) {
+         /* `key' is at index -2 and `value' at index -1 */
+         printf("%s - %s\n",
+           lua_typename(L, lua_type(L, -2)), lua_typename(L, lua_type(L, -1)));
+         lua_pop(L, 1);  /* removes `value'; keeps `key' for next iteration */
+       }
+
+ +

While traversing a table, +do not call lua_tostring directly on a key, +unless you know that the key is actually a string. +Recall that lua_tostring changes the value at the given index; +this confuses the next call to lua_next. + +

3.12 - Manipulating Environments

+ +

All global variables are kept in ordinary Lua tables, +called environments. +The initial environment is called the global environment. +This table is always at pseudo-index LUA_GLOBALSINDEX. + +

To access and change the value of global variables, +you can use regular table operations over an environment table. +For instance, to access the value of a global variable, do +

+       lua_pushstring(L, varname);
+       lua_gettable(L, LUA_GLOBALSINDEX);
+
+ +

You can change the global environment of a Lua thread using lua_replace. + +

The following functions get and set the environment of Lua functions: +

+       void lua_getfenv (lua_State *L, int index);
+       int  lua_setfenv (lua_State *L, int index);
+
+ +lua_getfenv pushes on the stack the environment table of +the function at index index in the stack. +If the function is a C function, +lua_getfenv pushes the global environment. +lua_setfenv pops a table from the stack and sets it as +the new environment for the function at index index in the stack. +If the object at the given index is not a Lua function, +lua_setfenv returns 0. + +

3.13 - Using Tables as Arrays

+The API has functions that help to use Lua tables as arrays, +that is, +tables indexed by numbers only: +
+       void lua_rawgeti (lua_State *L, int index, int n);
+       void lua_rawseti (lua_State *L, int index, int n);
+
+ + + +

lua_rawgeti pushes the value of the n-th element of the table +at stack position index. +lua_rawseti sets the value of the n-th element of the table +at stack position index to the value at the top of the stack, +removing this value from the stack. + +

3.14 - Calling Functions

+ +

Functions defined in Lua +and C functions registered in Lua +can be called from the host program. +This is done using the following protocol: +First, the function to be called is pushed onto the stack; +then, the arguments to the function are pushed +in direct order, that is, the first argument is pushed first. +Finally, the function is called using +

+       void lua_call (lua_State *L, int nargs, int nresults);
+
+ +nargs is the number of arguments that you pushed onto the stack. +All arguments and the function value are popped from the stack, +and the function results are pushed. +The number of results are adjusted to nresults, +unless nresults is LUA_MULTRET. +In that case, all results from the function are pushed. +Lua takes care that the returned values fit into the stack space. +The function results are pushed onto the stack in direct order +(the first result is pushed first), +so that after the call the last result is on the top. + +

The following example shows how the host program may do the +equivalent to this Lua code: +

+       a = f("how", t.x, 14)
+
+Here it is in C: +
+    lua_pushstring(L, "t");
+    lua_gettable(L, LUA_GLOBALSINDEX);          /* global `t' (for later use) */
+    lua_pushstring(L, "a");                                       /* var name */
+    lua_pushstring(L, "f");                                  /* function name */
+    lua_gettable(L, LUA_GLOBALSINDEX);               /* function to be called */
+    lua_pushstring(L, "how");                                 /* 1st argument */
+    lua_pushstring(L, "x");                            /* push the string "x" */
+    lua_gettable(L, -5);                      /* push result of t.x (2nd arg) */
+    lua_pushnumber(L, 14);                                    /* 3rd argument */
+    lua_call(L, 3, 1);         /* call function with 3 arguments and 1 result */
+    lua_settable(L, LUA_GLOBALSINDEX);             /* set global variable `a' */
+    lua_pop(L, 1);                               /* remove `t' from the stack */
+
+Note that the code above is "balanced": +at its end, the stack is back to its original configuration. +This is considered good programming practice. + +

(We did this example using only the raw functions provided by Lua's API, +to show all the details. +Usually programmers define and use several macros and auxiliary functions +that provide higher level access to Lua. +See the source code of the standard libraries for examples.) + +

3.15 - Protected Calls

+ +

When you call a function with lua_call, +any error inside the called function is propagated upwards +(with a longjmp). +If you need to handle errors, +then you should use lua_pcall: +

+       int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc);
+
+Both nargs and nresults have the same meaning as +in lua_call. +If there are no errors during the call, +lua_pcall behaves exactly like lua_call. +However, if there is any error, +lua_pcall catches it, +pushes a single value at the stack (the error message), +and returns an error code. +Like lua_call, +lua_pcall always removes the function +and its arguments from the stack. + +

If errfunc is 0, +then the error message returned is exactly the original error message. +Otherwise, errfunc gives the stack index for an +error handler function. +(In the current implementation, that index cannot be a pseudo-index.) +In case of runtime errors, +that function will be called with the error message +and its return value will be the message returned by lua_pcall. + +

Typically, the error handler function is used to add more debug +information to the error message, such as a stack traceback. +Such information cannot be gathered after the return of lua_pcall, +since by then the stack has unwound. + +

The lua_pcall function returns 0 in case of success +or one of the following error codes +(defined in lua.h): +

+ +

3.16 - Defining C Functions

+ +

Lua can be extended with functions written in C. +These functions must be of type lua_CFunction, +which is defined as +

+       typedef int (*lua_CFunction) (lua_State *L);
+
+ +A C function receives a Lua state and returns an integer, +the number of values it wants to return to Lua. + +

In order to communicate properly with Lua, +a C function must follow the following protocol, +which defines the way parameters and results are passed: +A C function receives its arguments from Lua in its stack +in direct order (the first argument is pushed first). +So, when the function starts, +its first argument (if any) is at index 1. +To return values to Lua, a C function just pushes them onto the stack, +in direct order (the first result is pushed first), +and returns the number of results. +Any other value in the stack below the results will be properly +discharged by Lua. +Like a Lua function, a C function called by Lua can also return +many results. + +

As an example, the following function receives a variable number +of numerical arguments and returns their average and sum: +

+       static int foo (lua_State *L) {
+         int n = lua_gettop(L);    /* number of arguments */
+         lua_Number sum = 0;
+         int i;
+         for (i = 1; i <= n; i++) {
+           if (!lua_isnumber(L, i)) {
+             lua_pushstring(L, "incorrect argument to function `average'");
+             lua_error(L);
+           }
+           sum += lua_tonumber(L, i);
+         }
+         lua_pushnumber(L, sum/n);        /* first result */
+         lua_pushnumber(L, sum);         /* second result */
+         return 2;                   /* number of results */
+       }
+
+ +

To register a C function to Lua, +there is the following convenience macro: +

+       #define lua_register(L,n,f) \
+               (lua_pushstring(L, n), \
+                lua_pushcfunction(L, f), \
+                lua_settable(L, LUA_GLOBALSINDEX))
+     /* lua_State *L;    */
+     /* const char *n;   */
+     /* lua_CFunction f; */
+
+ +which receives the name the function will have in Lua +and a pointer to the function. +Thus, +the C function foo above may be registered in Lua as +average by calling +
+       lua_register(L, "average", foo);
+
+ +

3.17 - Defining C Closures

+ +

When a C function is created, +it is possible to associate some values with it, +thus creating a C closure; +these values are then accessible to the function whenever it is called. +To associate values with a C function, +first these values should be pushed onto the stack +(when there are multiple values, the first value is pushed first). +Then the function +

+       void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);
+
+ +is used to push the C function onto the stack, +with the argument n telling how many values should be +associated with the function +(lua_pushcclosure also pops these values from the stack); +in fact, the macro lua_pushcfunction is defined as +lua_pushcclosure with n set to 0. + +

Then, whenever the C function is called, +those values are located at specific pseudo-indices. +Those pseudo-indices are produced by a macro lua_upvalueindex. +The first value associated with a function is at position +lua_upvalueindex(1), and so on. +Any access to lua_upvalueindex(n), +where n is greater than the number of upvalues of the +current function, +produces an acceptable (but invalid) index. + +

For examples of C functions and closures, +see the standard libraries in the official Lua distribution +(src/lib/*.c). + +

3.18 - Registry

+ +

Lua provides a registry, +a pre-defined table that can be used by any C code to +store whatever Lua value it needs to store, +specially if the C code needs to keep that Lua value +outside the life span of a C function. +This table is always located at pseudo-index +LUA_REGISTRYINDEX. +Any C library can store data into this table, +as long as it chooses keys different from other libraries. +Typically, you should use as key a string containing your library name +or a light userdata with the address of a C object in your code. + +

The integer keys in the registry are used by the reference mechanism, +implemented by the auxiliary library, +and therefore should not be used by other purposes. + +

3.19 - Error Handling in C

+ +

Internally, Lua uses the C longjmp facility to handle errors. +When Lua faces any error +(such as memory allocation errors, type errors, syntax errors) +it raises an error, that is, it does a long jump. +A protected environment uses setjmp +to set a recover point; +any error jumps to the most recent active recover point. + +

If an error happens outside any protected environment, +Lua calls a panic function +and then calls exit(EXIT_FAILURE). +You can change the panic function with +

+       lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);
+
+Your new panic function may avoid the application exit by +never returning (e.g., by doing a long jump). +Nevertheless, the corresponding Lua state will not be consistent; +the only safe operation with it is to close it. + +

Almost any function in the API may raise an error, +for instance due to a memory allocation error. +The following functions run in protected mode +(that is, they create a protected environment to run), +so they never raise an error: +lua_open, lua_close, lua_load, +and lua_pcall. + +

There is yet another function that runs a given C function in protected mode: +

+       int lua_cpcall (lua_State *L, lua_CFunction func, void *ud);
+
+ +lua_cpcall calls func in protected mode. +func starts with only one element in its stack, +a light userdata containing ud. +In case of errors, +lua_cpcall returns the same error codes as lua_pcall +(see 3.15), +plus the error object on the top of the stack; +otherwise, it returns zero, and does not change the stack. +Any value returned by func is discarded. + +

C code can generate a Lua error calling the function +

+       void lua_error (lua_State *L);
+
+ +The error message (which actually can be any type of object) +must be on the stack top. +This function does a long jump, +and therefore never returns. + +

3.20 - Threads

+ +

Lua offers partial support for multiple threads of execution. +If you have a C library that offers multi-threading, +then Lua can cooperate with it to implement the equivalent facility in Lua. +Also, Lua implements its own coroutine system on top of threads. +The following function creates a new thread in Lua: +

+       lua_State *lua_newthread (lua_State *L);
+
+ +This function pushes the thread on the stack and returns a pointer to +a lua_State that represents this new thread. +The new state returned by this function shares with the original state +all global objects (such as tables), +but has an independent run-time stack. + +

Each thread has an independent global environment table. +When you create a thread, this table is the same as that of the given state, +but you can change each one independently. + +

There is no explicit function to close or to destroy a thread. +Threads are subject to garbage collection, +like any Lua object. + +

To manipulate threads as coroutines, +Lua offers the following functions: +

+       int lua_resume (lua_State *L, int narg);
+       int lua_yield  (lua_State *L, int nresults);
+
+ +To start a coroutine, you first create a new thread; +then you push on its stack the body function plus any eventual arguments; +then you call lua_resume, +with narg being the number of arguments. +This call returns when the coroutine suspends or finishes its execution. +When it returns, the stack contains all values passed to lua_yield, +or all values returned by the body function. +lua_resume returns 0 if there are no errors running the coroutine, +or an error code (see 3.15). +In case of errors, +the stack contains only the error message. +To restart a coroutine, you put on its stack only the values to +be passed as results from yield, +and then call lua_resume. + +

The lua_yield function can only be called as the +return expression of a C function, as follows: +

+       return lua_yield (L, nresults);
+
+When a C function calls lua_yield in that way, +the running coroutine suspends its execution, +and the call to lua_resume that started this coroutine returns. +The parameter nresults is the number of values from the stack +that are passed as results to lua_resume. + +

To exchange values between different threads, +you may use lua_xmove: +

+       void lua_xmove (lua_State *from, lua_State *to, int n);
+
+It pops n values from the stack from, +and puhses them into the stack to. + +

+

4 - The Debug Interface

+ +

Lua has no built-in debugging facilities. +Instead, it offers a special interface +by means of functions and hooks. +This interface allows the construction of different +kinds of debuggers, profilers, and other tools +that need "inside information" from the interpreter. + +

4.1 - Stack and Function Information

+ +

The main function to get information about the interpreter runtime stack is +

+       int lua_getstack (lua_State *L, int level, lua_Debug *ar);
+
+ +This function fills parts of a lua_Debug structure with +an identification of the activation record +of the function executing at a given level. +Level 0 is the current running function, +whereas level n+1 is the function that has called level n. +When there are no errors, lua_getstack returns 1; +when called with a level greater than the stack depth, +it returns 0. + +

The structure lua_Debug is used to carry different pieces of +information about an active function: +

+      typedef struct lua_Debug {
+        int event;
+        const char *name;      /* (n) */
+        const char *namewhat;  /* (n) `global', `local', `field', `method' */
+        const char *what;      /* (S) `Lua' function, `C' function, Lua `main' */
+        const char *source;    /* (S) */
+        int currentline;       /* (l) */
+        int nups;              /* (u) number of upvalues */
+        int linedefined;       /* (S) */
+        char short_src[LUA_IDSIZE]; /* (S) */
+
+        /* private part */
+        ...
+      } lua_Debug;
+
+ +lua_getstack fills only the private part +of this structure, for later use. +To fill the other fields of lua_Debug with useful information, +call +
+       int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
+
+ +This function returns 0 on error +(for instance, an invalid option in what). +Each character in the string what +selects some fields of the structure ar to be filled, +as indicated by the letter in parentheses in the definition of lua_Debug +above: +`S´ fills in the fields source, linedefined, +and what; +`l´ fills in the field currentline, etc. +Moreover, `f´ pushes onto the stack the function that is +running at the given level. + +

To get information about a function that is not active +(that is, not in the stack), +you push it onto the stack +and start the what string with the character `>´. +For instance, to know in which line a function f was defined, +you can write +

+       lua_Debug ar;
+       lua_pushstring(L, "f");
+       lua_gettable(L, LUA_GLOBALSINDEX);  /* get global `f' */
+       lua_getinfo(L, ">S", &ar);
+       printf("%d\n", ar.linedefined);
+
+The fields of lua_Debug have the following meaning: + + +

4.2 - Manipulating Local Variables and Upvalues

+ +

For the manipulation of local variables and upvalues, +the debug interface uses indices: +The first parameter or local variable has index 1, and so on, +until the last active local variable. +Upvalues have no particular order, +as they are active through the whole function. + +

The following functions allow the manipulation of the +local variables of a given activation record: +

+       const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);
+       const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);
+
+ +The parameter ar must be a valid activation record that was +filled by a previous call to lua_getstack or +given as argument to a hook (see 4.3). +lua_getlocal gets the index n of a local variable, +pushes the variable's value onto the stack, +and returns its name. +lua_setlocal assigns the value at the top of the stack +to the variable and returns its name. +Both functions return NULL +when the index is greater than +the number of active local variables. + +

The following functions allow the manipulation of the +upvalues of a given function +(unlike local variables, +the upvalues of a function are accessible even when the +function is not active): +

+       const char *lua_getupvalue (lua_State *L, int funcindex, int n);
+       const char *lua_setupvalue (lua_State *L, int funcindex, int n);
+
+ +These functions operate both on Lua functions and on C functions. +(For Lua functions, +upvalues are the external local variables that the function uses, +and that consequently are included in its closure.) +funcindex points to a function in the stack. +lua_getpuvalue gets the index n of an upvalue, +pushes the upvalue's value onto the stack, +and returns its name. +lua_setupvalue assigns the value at the top of the stack +to the upvalue and returns its name. +Both functions return NULL +when the index is greater than the number of upvalues. +For C functions, these functions use the empty string "" +as a name for all upvalues. + +

As an example, the following function lists the names of all +local variables and upvalues for a function at a given level of the stack: +

+       int listvars (lua_State *L, int level) {
+         lua_Debug ar;
+         int i;
+         const char *name;
+         if (lua_getstack(L, level, &ar) == 0)
+           return 0;  /* failure: no such level in the stack */
+         i = 1;
+         while ((name = lua_getlocal(L, &ar, i++)) != NULL) {
+           printf("local %d %s\n", i-1, name);
+           lua_pop(L, 1);  /* remove variable value */
+         }
+         lua_getinfo(L, "f", &ar);  /* retrieves function */
+         i = 1;
+         while ((name = lua_getpuvalue(L, -1, i++)) != NULL) {
+           printf("upvalue %d %s\n", i-1, name);
+           lua_pop(L, 1);  /* remove upvalue value */
+         }
+         return 1;
+       }
+
+ +

4.3 - Hooks

+ +

Lua offers a mechanism of hooks, which are +user-defined C functions that are called during the program execution. +A hook may be called in four different events: +a call event, when Lua calls a function; +a return event, when Lua returns from a function; +a line event, when Lua starts executing a new line of code; +and a count event, which happens every "count" instructions. +Lua identifies these events with the following constants: +LUA_HOOKCALL, +LUA_HOOKRET (or LUA_HOOKTAILRET, see below), +LUA_HOOKLINE, +and LUA_HOOKCOUNT. + +

A hook has type lua_Hook, defined as follows: +

+       typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
+
+ +You can set the hook with the following function: +
+       int lua_sethook (lua_State *L, lua_Hook func, int mask, int count);
+
+ +func is the hook. +mask specifies on which events the hook will be called: +It is formed by a disjunction of the constants +LUA_MASKCALL, +LUA_MASKRET, +LUA_MASKLINE, +and LUA_MASKCOUNT. +The count argument is only meaningful when the mask +includes LUA_MASKCOUNT. +For each event, the hook is called as explained below: + + +

A hook is disabled by setting mask to zero. + +

You can get the current hook, the current mask, +and the current count with the next functions: +

+       lua_Hook lua_gethook      (lua_State *L);
+       int      lua_gethookmask  (lua_State *L);
+       int      lua_gethookcount (lua_State *L);
+
+ + +

Whenever a hook is called, its ar argument has its field +event set to the specific event that triggered the hook. +Moreover, for line events, the field currentline is also set. +To get the value of any other field in ar, +the hook must call lua_getinfo. +For return events, event may be LUA_HOOKRET, +the normal value, or LUA_HOOKTAILRET. +In the latter case, Lua is simulating a return from +a function that did a tail call; +in this case, it is useless to call lua_getinfo. + +

While Lua is running a hook, it disables other calls to hooks. +Therefore, if a hook calls back Lua to execute a function or a chunk, +that execution occurs without any calls to hooks. + +

+

5 - Standard Libraries

+ +

The standard libraries provide useful functions +that are implemented directly through the C API. +Some of these functions provide essential services to the language +(e.g., type and getmetatable); +others provide access to "outside" services (e.g., I/O); +and others could be implemented in Lua itself, +but are quite useful or have critical performance to +deserve an implementation in C (e.g., sort). + +

All libraries are implemented through the official C API +and are provided as separate C modules. +Currently, Lua has the following standard libraries: +

+Except for the basic library, +each library provides all its functions as fields of a global table +or as methods of its objects. + +

To have access to these libraries, +the C host program must first call the functions +luaopen_base (for the basic library), +luaopen_string (for the string library), +luaopen_table (for the table library), +luaopen_math (for the mathematical library), +luaopen_io (for the I/O and the Operating System libraries), +and luaopen_debug (for the debug library). +These functions are declared in lualib.h. + + + + + + + +

5.1 - Basic Functions

+ +

The basic library provides some core functions to Lua. +If you do not include this library in your application, +you should check carefully whether you need to provide some alternative +implementation for some of its facilities. + +

assert (v [, message])

+Issues an error when +the value of its argument v is nil or false; +otherwise, returns this value. +message is an error message; +when absent, it defaults to "assertion failed!" + +

collectgarbage ([limit])

+ +

Sets the garbage-collection threshold to the given limit +(in Kbytes) and checks it against the byte counter. +If the new threshold is smaller than the byte counter, +then Lua immediately runs the garbage collector (see 2.9). +If limit is absent, it defaults to zero +(thus forcing a garbage-collection cycle). + +

dofile (filename)

+Opens the named file and executes its contents as a Lua chunk. +When called without arguments, +dofile executes the contents of the standard input (stdin). +Returns any value returned by the chunk. +In case of errors, dofile propagates the error +to its caller (that is, it does not run in protected mode). + +

error (message [, level])

+ +Terminates the last protected function called +and returns message as the error message. +Function error never returns. + +

The level argument specifies where the error +message points the error. +With level 1 (the default), the error position is where the +error function was called. +Level 2 points the error to where the function +that called error was called; and so on. + +

_G

+A global variable (not a function) that +holds the global environment (that is, _G._G = _G). +Lua itself does not use this variable; +changing its value does not affect any environment. +(Use setfenv to change environments.) + +

getfenv (f)

+Returns the current environment in use by the function. +f can be a Lua function or a number, +which specifies the function at that stack level: +Level 1 is the function calling getfenv. +If the given function is not a Lua function, +or if f is 0, +getfenv returns the global environment. +The default for f is 1. + +

If the environment has a "__fenv" field, +returns the associated value, instead of the environment. + +

getmetatable (object)

+ + +

If the object does not have a metatable, returns nil. +Otherwise, +if the object's metatable has a "__metatable" field, +returns the associated value. +Otherwise, returns the metatable of the given object. + +

gcinfo ()

+ +

Returns two results: +the number of Kbytes of dynamic memory that Lua is using +and the current garbage collector threshold (also in Kbytes). + +

ipairs (t)

+ +

Returns an iterator function, the table t, and 0, +so that the construction +

+       for i,v in ipairs(t) do ... end
+
+will iterate over the pairs (1,t[1]), (2,t[2]), ..., +up to the first integer key with a nil value in the table. + +

loadfile (filename)

+ +

Loads a file as a Lua chunk (without running it). +If there are no errors, +returns the compiled chunk as a function; +otherwise, returns nil plus the error message. +The environment of the returned function is the global environment. + +

loadlib (libname, funcname)

+ +

Links the program with the dynamic C library libname. +Inside this library, looks for a function funcname +and returns this function as a C function. + +

libname must be the complete file name of the C library, +including any eventual path and extension. + +

This function is not supported by ANSI C. +As such, it is only available on some platforms +(Windows, Linux, Solaris, BSD, plus other Unix systems that +support the dlfcn standard). + +

loadstring (string [, chunkname])

+Loads a string as a Lua chunk (without running it). +If there are no errors, +returns the compiled chunk as a function; +otherwise, returns nil plus the error message. +The environment of the returned function is the global environment. + +

The optional parameter chunkname +is the name to be used in error messages and debug information. + +

To load and run a given string, use the idiom +

+      assert(loadstring(s))()
+
+ +

next (table [, index])

+Allows a program to traverse all fields of a table. +Its first argument is a table and its second argument +is an index in this table. +next returns the next index of the table and the +value associated with the index. +When called with nil as its second argument, +next returns the first index +of the table and its associated value. +When called with the last index, +or with nil in an empty table, +next returns nil. +If the second argument is absent, then it is interpreted as nil. + +

Lua has no declaration of fields; +There is no difference between a +field not present in a table or a field with value nil. +Therefore, next only considers fields with non-nil values. +The order in which the indices are enumerated is not specified, +even for numeric indices. +(To traverse a table in numeric order, +use a numerical for or the ipairs function.) + +

The behavior of next is undefined if, +during the traversal, +you assign any value to a non-existent field in the table. + +

pairs (t)

+ +

Returns the next function and the table t (plus a nil), +so that the construction +

+       for k,v in pairs(t) do ... end
+
+will iterate over all key-value pairs of table t. + +

pcall (f, arg1, arg2, ...)

+ +

Calls function f with +the given arguments in protected mode. +That means that any error inside f is not propagated; +instead, pcall catches the error +and returns a status code. +Its first result is the status code (a boolean), +which is true if the call succeeds without errors. +In such case, pcall also returns all results from the call, +after this first result. +In case of any error, pcall returns false plus the error message. + +

print (e1, e2, ...)

+Receives any number of arguments, +and prints their values in stdout, +using the tostring function to convert them to strings. +This function is not intended for formatted output, +but only as a quick way to show a value, +typically for debugging. +For formatted output, use format (see 5.3). + +

rawequal (v1, v2)

+Checks whether v1 is equal to v2, +without invoking any metamethod. +Returns a boolean. + +

rawget (table, index)

+Gets the real value of table[index], +without invoking any metamethod. +table must be a table; +index is any value different from nil. + +

rawset (table, index, value)

+Sets the real value of table[index] to value, +without invoking any metamethod. +table must be a table, +index is any value different from nil, +and value is any Lua value. + +

require (packagename)

+ +

Loads the given package. +The function starts by looking into the table _LOADED +to determine whether packagename is already loaded. +If it is, then require returns the value that the package +returned when it was first loaded. +Otherwise, it searches a path looking for a file to load. + +

If the global variable LUA_PATH is a string, +this string is the path. +Otherwise, require tries the environment variable LUA_PATH. +As a last resort, it uses the predefined path "?;?.lua". + +

The path is a sequence of templates separated by semicolons. +For each template, require will change each interrogation +mark in the template to packagename, +and then will try to load the resulting file name. +So, for instance, if the path is +

+  "./?.lua;./?.lc;/usr/local/?/?.lua;/lasttry"
+
+a require "mod" will try to load the files +./mod.lua, +./mod.lc, +/usr/local/mod/mod.lua, +and /lasttry, in that order. + +

The function stops the search as soon as it can load a file, +and then it runs the file. +After that, it associates, in table _LOADED, +the package name with the value that the package returned, +and returns that value. +If the package returns nil (or no value), +require converts this value to true. +If the package returns false, +require also returns false. +However, as the mark in table _LOADED is false, +any new attempt to reload the file +will happen as if the package was not loaded +(that is, the package will be loaded again). + +

If there is any error loading or running the file, +or if it cannot find any file in the path, +then require signals an error. + +

While running a file, +require defines the global variable _REQUIREDNAME +with the package name. +The package being loaded always runs within the global environment. + +

setfenv (f, table)

+ +

Sets the current environment to be used by the given function. +f can be a Lua function or a number, +which specifies the function at that stack level: +Level 1 is the function calling setfenv. + +

As a special case, when f is 0 setfenv changes +the global environment of the running thread. + +

If the original environment has a "__fenv" field, +setfenv raises an error. + +

setmetatable (table, metatable)

+ +

Sets the metatable for the given table. +(You cannot change the metatable of a userdata from Lua.) +If metatable is nil, removes the metatable of the given table. +If the original metatable has a "__metatable" field, +raises an error. + +

tonumber (e [, base])

+Tries to convert its argument to a number. +If the argument is already a number or a string convertible +to a number, then tonumber returns that number; +otherwise, it returns nil. + +

An optional argument specifies the base to interpret the numeral. +The base may be any integer between 2 and 36, inclusive. +In bases above 10, the letter `A´ (in either upper or lower case) +represents 10, `B´ represents 11, and so forth, +with `Z´ representing 35. +In base 10 (the default), the number may have a decimal part, +as well as an optional exponent part (see 2.2.1). +In other bases, only unsigned integers are accepted. + +

tostring (e)

+Receives an argument of any type and +converts it to a string in a reasonable format. +For complete control of how numbers are converted, +use format (see 5.3). + +

If the metatable of e has a "__tostring" field, +tostring calls the corresponding value +with e as argument, +and uses the result of the call as its result. + +

type (v)

+Returns the type of its only argument, coded as a string. +The possible results of this function are +"nil" (a string, not the value nil), +"number", +"string", +"boolean, +"table", +"function", +"thread", +and "userdata". + +

unpack (list)

+Returns all elements from the given list. +This function is equivalent to +
+  return list[1], list[2], ..., list[n]
+
+except that the above code can be written only for a fixed n. +The number n is the size of the list, +as defined for the table.getn function. + +

_VERSION

+A global variable (not a function) that +holds a string containing the current interpreter version. +The current content of this string is "Lua 5.0". + +

xpcall (f, err)

+ +

This function is similar to pcall, +except that you can set a new error handler. + +

xpcall calls function f in protected mode, +using err as the error handler. +Any error inside f is not propagated; +instead, xpcall catches the error, +calls the err function with the original error object, +and returns a status code. +Its first result is the status code (a boolean), +which is true if the call succeeds without errors. +In such case, xpcall also returns all results from the call, +after this first result. +In case of any error, +xpcall returns false plus the result from err. + +

5.2 - Coroutine Manipulation

+ +

The operations related to coroutines comprise a sub-library of +the basic library and come inside the table coroutine. +See 2.10 for a general description of coroutines. + +

coroutine.create (f)

+ +

Creates a new coroutine, with body f. +f must be a Lua function. +Returns this new coroutine, +an object with type "thread". + +

coroutine.resume (co, val1, ...)

+ +

Starts or continues the execution of coroutine co. +The first time you resume a coroutine, +it starts running its body. +The arguments val1, ... go as the arguments to the body function. +If the coroutine has yielded, +resume restarts it; +the arguments val1, ... go as the results from the yield. + +

If the coroutine runs without any errors, +resume returns true plus any values passed to yield +(if the coroutine yields) or any values returned by the body function +(if the coroutine terminates). +If there is any error, +resume returns false plus the error message. + +

coroutine.status (co)

+ +

Returns the status of coroutine co, as a string: +"running", +if the coroutine is running (that is, it called status); +"suspended", if the coroutine is suspended in a call to yield, +or if it has not started running yet; +and "dead" if the coroutine has finished its body function, +or if it has stopped with an error. + +

coroutine.wrap (f)

+ +

Creates a new coroutine, with body f. +f must be a Lua function. +Returns a function that resumes the coroutine each time it is called. +Any arguments passed to the function behave as the +extra arguments to resume. +Returns the same values returned by resume, +except the first boolean. +In case of error, propagates the error. + +

coroutine.yield (val1, ...)

+ +

Suspends the execution of the calling coroutine. +The coroutine cannot be running neither a C function, +nor a metamethod, nor an iterator. +Any arguments to yield go as extra results to resume. + +

5.3 - String Manipulation

+This library provides generic functions for string manipulation, +such as finding and extracting substrings, and pattern matching. +When indexing a string in Lua, the first character is at position 1 +(not at 0, as in C). +Indices are allowed to be negative and are interpreted as indexing backwards, +from the end of the string. +Thus, the last character is at position -1, and so on. + +

The string library provides all its functions inside the table +string. + +

string.byte (s [, i])

+Returns the internal numerical code of the i-th character of s, +or nil if the index is out of range. +If i is absent, then it is assumed to be 1. +i may be negative. + +

Note that numerical codes are not necessarily portable across platforms. + +

string.char (i1, i2, ...)

+Receives 0 or more integers. +Returns a string with length equal to the number of arguments, +in which each character has the internal numerical code equal +to its correspondent argument. + +

Note that numerical codes are not necessarily portable across platforms. + +

string.dump (function)

+ +

Returns a binary representation of the given function, +so that a later loadstring on that string returns +a copy of the function. +function must be a Lua function without upvalues. + +

string.find (s, pattern [, init [, plain]])

+Looks for the first match of +pattern in the string s. +If it finds one, then find returns the indices of s +where this occurrence starts and ends; +otherwise, it returns nil. +If the pattern specifies captures (see string.gsub below), +the captured strings are returned as extra results. +A third, optional numerical argument init specifies +where to start the search; +its default value is 1 and may be negative. +A value of true as a fourth, optional argument plain +turns off the pattern matching facilities, +so the function does a plain "find substring" operation, +with no characters in pattern being considered "magic". +Note that if plain is given, then init must be given too. + +

string.len (s)

+Receives a string and returns its length. +The empty string "" has length 0. +Embedded zeros are counted, +so "a\000b\000c" has length 5. + +

string.lower (s)

+Receives a string and returns a copy of that string with all +uppercase letters changed to lowercase. +All other characters are left unchanged. +The definition of what is an uppercase letter depends on the current locale. + +

string.rep (s, n)

+Returns a string that is the concatenation of n copies of +the string s. + +

string.sub (s, i [, j])

+Returns the substring of s that +starts at i and continues until j; +i and j may be negative. +If j is absent, then it is assumed to be equal to -1 +(which is the same as the string length). +In particular, +the call string.sub(s,1,j) returns a prefix of s +with length j, +and string.sub(s, -i) returns a suffix of s +with length i. + +

string.upper (s)

+Receives a string and returns a copy of that string with all +lowercase letters changed to uppercase. +All other characters are left unchanged. +The definition of what is a lowercase letter depends on the current locale. + +

string.format (formatstring, e1, e2, ...)

+ +Returns a formatted version of its variable number of arguments +following the description given in its first argument (which must be a string). +The format string follows the same rules as the printf family of +standard C functions. +The only differences are that the options/modifiers +*, l, L, n, p, +and h are not supported, +and there is an extra option, q. +The q option formats a string in a form suitable to be safely read +back by the Lua interpreter: +The string is written between double quotes, +and all double quotes, newlines, and backslashes in the string +are correctly escaped when written. +For instance, the call +
+       string.format('%q', 'a string with "quotes" and \n new line')
+
+will produce the string: +
+"a string with \"quotes\" and \
+ new line"
+
+ +

The options c, d, E, e, f, +g, G, i, o, u, X, and x all +expect a number as argument, +whereas q and s expect a string. +The * modifier can be simulated by building +the appropriate format string. +For example, "%*g" can be simulated with +"%"..width.."g". + +

String values to be formatted with +%s cannot contain embedded zeros. + +

string.gfind (s, pat)

+ +

Returns an iterator function that, +each time it is called, +returns the next captures from pattern pat over string s. + +

If pat specifies no captures, +then the whole match is produced in each call. + +

As an example, the following loop +

+  s = "hello world from Lua"
+  for w in string.gfind(s, "%a+") do
+    print(w)
+  end
+
+will iterate over all the words from string s, +printing one per line. +The next example collects all pairs key=value from the +given string into a table: +
+  t = {}
+  s = "from=world, to=Lua"
+  for k, v in string.gfind(s, "(%w+)=(%w+)") do
+    t[k] = v
+  end
+
+ +

string.gsub (s, pat, repl [, n])

+ +Returns a copy of s +in which all occurrences of the pattern pat have been +replaced by a replacement string specified by repl. +gsub also returns, as a second value, +the total number of substitutions made. + +

If repl is a string, then its value is used for replacement. +Any sequence in repl of the form %n, +with n between 1 and 9, +stands for the value of the n-th captured substring (see below). + +

If repl is a function, then this function is called every time a +match occurs, with all captured substrings passed as arguments, +in order; +if the pattern specifies no captures, +then the whole match is passed as a sole argument. +If the value returned by this function is a string, +then it is used as the replacement string; +otherwise, the replacement string is the empty string. + +

The optional last parameter n limits +the maximum number of substitutions to occur. +For instance, when n is 1 only the first occurrence of +pat is replaced. + +

Here are some examples: +

+   x = string.gsub("hello world", "(%w+)", "%1 %1")
+   --> x="hello hello world world"
+
+   x = string.gsub("hello world", "(%w+)", "%1 %1", 1)
+   --> x="hello hello world"
+
+   x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")
+   --> x="world hello Lua from"
+
+   x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv)
+   --> x="home = /home/roberto, user = roberto"
+
+   x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s)
+         return loadstring(s)()
+       end)
+   --> x="4+5 = 9"
+
+   local t = {name="lua", version="5.0"}
+   x = string.gsub("$name_$version.tar.gz", "%$(%w+)", function (v)
+         return t[v]
+       end)
+   --> x="lua_5.0.tar.gz"
+
+ +

Patterns

+ +

+A character class is used to represent a set of characters. +The following combinations are allowed in describing a character class: +

+For all classes represented by single letters (%a, %c, etc.), +the corresponding uppercase letter represents the complement of the class. +For instance, %S represents all non-space characters. + +

The definitions of letter, space, and other character groups +depend on the current locale. +In particular, the class [a-z] may not be equivalent to %l. +The second form should be preferred for portability. + +

+A pattern item may be +

+ +

+A pattern is a sequence of pattern items. +A `^´ at the beginning of a pattern anchors the match at the +beginning of the subject string. +A `$´ at the end of a pattern anchors the match at the +end of the subject string. +At other positions, +`^´ and `$´ have no special meaning and represent themselves. + +

+A pattern may contain sub-patterns enclosed in parentheses; +they describe captures. +When a match succeeds, the substrings of the subject string +that match captures are stored (captured) for future use. +Captures are numbered according to their left parentheses. +For instance, in the pattern "(a*(.)%w(%s*))", +the part of the string matching "a*(.)%w(%s*)" is +stored as the first capture (and therefore has number 1); +the character matching . is captured with number 2, +and the part matching %s* has number 3. + +

As a special case, the empty capture () captures +the current string position (a number). +For instance, if we apply the pattern "()aa()" on the +string "flaaap", there will be two captures: 3 and 5. + +

A pattern cannot contain embedded zeros. Use %z instead. + +

5.4 - Table Manipulation

+This library provides generic functions for table manipulation. +It provides all its functions inside the table table. + +

Most functions in the table library assume that the table +represents an array or a list. +For those functions, an important concept is the size of the array. +There are three ways to specify that size: +

+For more details, see the descriptions of the table.getn and +table.setn functions. + +

table.concat (table [, sep [, i [, j]]])

+ +Returns table[i]..sep..table[i+1] ... sep..table[j]. +The default value for sep is the empty string, +the default for i is 1, +and the default for j is the size of the table. +If i is greater than j, returns the empty string. + +

table.foreach (table, f)

+Executes the given f over all elements of table. +For each element, f is called with the index and +respective value as arguments. +If f returns a non-nil value, +then the loop is broken, and this value is returned +as the final value of foreach. + +

See the next function for extra information about table traversals. + +

table.foreachi (table, f)

+Executes the given f over the +numerical indices of table. +For each index, f is called with the index and +respective value as arguments. +Indices are visited in sequential order, +from 1 to n, +where n is the size of the table (see 5.4). +If f returns a non-nil value, +then the loop is broken and this value is returned +as the result of foreachi. + +

table.getn (table)

+Returns the size of a table, when seen as a list. +If the table has an n field with a numeric value, +this value is the size of the table. +Otherwise, if there was a previous call +to table.setn over this table, +the respective value is returned. +Otherwise, the size is one less the first integer index with +a nil value. + +

table.sort (table [, comp])

+Sorts table elements in a given order, in-place, +from table[1] to table[n], +where n is the size of the table (see 5.4). +If comp is given, +then it must be a function that receives two table elements, +and returns true +when the first is less than the second +(so that not comp(a[i+1],a[i]) will be true after the sort). +If comp is not given, +then the standard Lua operator < is used instead. + +

The sort algorithm is not stable, +that is, elements considered equal by the given order +may have their relative positions changed by the sort. + +

table.insert (table, [pos,] value)

+ +

Inserts element value at position pos in table, +shifting up other elements to open space, if necessary. +The default value for pos is n+1, +where n is the size of the table (see 5.4), +so that a call table.insert(t,x) inserts x at the end +of table t. +This function also updates the size of the table by +calling table.setn(table, n+1). + +

table.remove (table [, pos])

+ +

Removes from table the element at position pos, +shifting down other elements to close the space, if necessary. +Returns the value of the removed element. +The default value for pos is n, +where n is the size of the table (see 5.4), +so that a call table.remove(t) removes the last element +of table t. +This function also updates the size of the table by +calling table.setn(table, n-1). + +

table.setn (table, n)

+ +

Updates the size of a table. +If the table has a field "n" with a numerical value, +that value is changed to the given n. +Otherwise, it updates an internal state +so that subsequent calls to table.getn(table) return n. + +

5.5 - Mathematical Functions

+ +

This library is an interface to most of the functions of the +standard C math library. +(Some have slightly different names.) +It provides all its functions inside the table math. +In addition, +it registers the global __pow +for the binary exponentiation operator ^, +so that x^y returns xy. +The library provides the following functions: + + + + + + + + + +

+       math.abs     math.acos    math.asin    math.atan    math.atan2
+       math.ceil    math.cos     math.deg     math.exp     math.floor
+       math.log     math.log10   math.max     math.min     math.mod
+       math.pow     math.rad     math.sin     math.sqrt    math.tan
+       math.frexp   math.ldexp   math.random  math.randomseed
+
+plus a variable math.pi. +Most of them +are only interfaces to the corresponding functions in the C library. +All trigonometric functions work in radians +(previous versions of Lua used degrees). +The functions math.deg and math.rad convert +between radians and degrees. + +

The function math.max returns the maximum +value of its numeric arguments. +Similarly, math.min computes the minimum. +Both can be used with 1, 2, or more arguments. + +

The functions math.random and math.randomseed +are interfaces to the simple random generator functions +rand and srand that are provided by ANSI C. +(No guarantees can be given for their statistical properties.) +When called without arguments, +math.random returns a pseudo-random real number +in the range [0,1). +When called with a number n, +math.random returns a pseudo-random integer in the range [1,n]. +When called with two arguments, l and u, +math.random returns a pseudo-random integer in the range [l,u]. +The math.randomseed function sets a "seed" +for the pseudo-random generator: +Equal seeds produce equal sequences of numbers. + +

5.6 - Input and Output Facilities

+ +

The I/O library provides two different styles for file manipulation. +The first one uses implicit file descriptors, +that is, there are operations to set a default input file and a +default output file, +and all input/output operations are over those default files. +The second style uses explicit file descriptors. + +

When using implicit file descriptors, +all operations are supplied by table io. +When using explicit file descriptors, +the operation io.open returns a file descriptor +and then all operations are supplied as methods by the file descriptor. + +

The table io also provides +three predefined file descriptors with their usual meanings from C: +io.stdin, io.stdout, and io.stderr. + +

A file handle is a userdata containing the file stream (FILE*), +with a distinctive metatable created by the I/O library. + +

Unless otherwise stated, +all I/O functions return nil on failure +(plus an error message as a second result) +and some value different from nil on success. + +

io.close ([file])

+ +

Equivalent to file:close(). +Without a file, closes the default output file. + +

io.flush ()

+ +

Equivalent to file:flush over the default output file. + +

io.input ([file])

+ +

When called with a file name, it opens the named file (in text mode), +and sets its handle as the default input file. +When called with a file handle, +it simply sets that file handle as the default input file. +When called without parameters, +it returns the current default input file. + +

In case of errors this function raises the error, +instead of returning an error code. + +

io.lines ([filename])

+ +

Opens the given file name in read mode +and returns an iterator function that, +each time it is called, +returns a new line from the file. +Therefore, the construction +

+       for line in io.lines(filename) do ... end
+
+will iterate over all lines of the file. +When the iterator function detects the end of file, +it returns nil (to finish the loop) and automatically closes the file. + +

The call io.lines() (without a file name) is equivalent +to io.input():lines(), that is, it iterates over the +lines of the default input file. + +

io.open (filename [, mode])

+ +

This function opens a file, +in the mode specified in the string mode. +It returns a new file handle, +or, in case of errors, nil plus an error message. + +

The mode string can be any of the following: +

+The mode string may also have a b at the end, +which is needed in some systems to open the file in binary mode. +This string is exactly what is used in the standard C function fopen. + +

io.output ([file])

+ +

Similar to io.input, but operates over the default output file. + +

io.read (format1, ...)

+ +

Equivalent to io.input():read. + +

io.tmpfile ()

+ +

Returns a handle for a temporary file. +This file is open in update mode +and it is automatically removed when the program ends. + +

io.type (obj)

+ +

Checks whether obj is a valid file handle. +Returns the string "file" if obj is an open file handle, +"closed file" if obj is a closed file handle, +and nil if obj is not a file handle. + +

io.write (value1, ...)

+ +

Equivalent to io.output():write. + +

file:close ()

+ +

Closes file. + +

file:flush ()

+ +

Saves any written data to file. + +

file:lines ()

+ +

Returns an iterator function that, +each time it is called, +returns a new line from the file. +Therefore, the construction +

+       for line in file:lines() do ... end
+
+will iterate over all lines of the file. +(Unlike io.lines, this function does not close the file +when the loop ends.) + +

file:read (format1, ...)

+ +

Reads the file file, +according to the given formats, which specify what to read. +For each format, +the function returns a string (or a number) with the characters read, +or nil if it cannot read data with the specified format. +When called without formats, +it uses a default format that reads the entire next line +(see below). + +

The available formats are +

+ +

file:seek ([whence] [, offset])

+ +

Sets and gets the file position, +measured from the beginning of the file, +to the position given by offset plus a base +specified by the string whence, as follows: +

+In case of success, function seek returns the final file position, +measured in bytes from the beginning of the file. +If this function fails, it returns nil, +plus a string describing the error. + +

The default value for whence is "cur", +and for offset is 0. +Therefore, the call file:seek() returns the current +file position, without changing it; +the call file:seek("set") sets the position to the +beginning of the file (and returns 0); +and the call file:seek("end") sets the position to the +end of the file, and returns its size. + +

file:write (value1, ...)

+ +

Writes the value of each of its arguments to +the filehandle file. +The arguments must be strings or numbers. +To write other values, +use tostring or string.format before write. + +

5.7 - Operating System Facilities

+ +

This library is implemented through table os. + +

os.clock ()

+ +

Returns an approximation of the amount of CPU time +used by the program, in seconds. + +

os.date ([format [, time]])

+ +

Returns a string or a table containing date and time, +formatted according to the given string format. + +

If the time argument is present, +this is the time to be formatted +(see the os.time function for a description of this value). +Otherwise, date formats the current time. + +

If format starts with `!´, +then the date is formatted in Coordinated Universal Time. +After that optional character, +if format is *t, +then date returns a table with the following fields: +year (four digits), month (1--12), day (1--31), +hour (0--23), min (0--59), sec (0--61), +wday (weekday, Sunday is 1), +yday (day of the year), +and isdst (daylight saving flag, a boolean). + +

If format is not *t, +then date returns the date as a string, +formatted according with the same rules as the C function strftime. + +

When called without arguments, +date returns a reasonable date and time representation that depends on +the host system and on the current locale +(that is, os.date() is equivalent to os.date("%c")). + +

os.difftime (t2, t1)

+ +

Returns the number of seconds from time t1 to time t2. +In Posix, Windows, and some other systems, +this value is exactly t2-t1. + +

os.execute (command)

+ +

This function is equivalent to the C function system. +It passes command to be executed by an operating system shell. +It returns a status code, which is system-dependent. + +

os.exit ([code])

+ +

Calls the C function exit, +with an optional code, +to terminate the host program. +The default value for code is the success code. + +

os.getenv (varname)

+ +

Returns the value of the process environment variable varname, +or nil if the variable is not defined. + +

os.remove (filename)

+ +

Deletes the file with the given name. +If this function fails, it returns nil, +plus a string describing the error. + +

os.rename (oldname, newname)

+ +

Renames file named oldname to newname. +If this function fails, it returns nil, +plus a string describing the error. + +

os.setlocale (locale [, category])

+ +

Sets the current locale of the program. +locale is a string specifying a locale; +category is an optional string describing which category to change: +"all", "collate", "ctype", +"monetary", "numeric", or "time"; +the default category is "all". +The function returns the name of the new locale, +or nil if the request cannot be honored. + +

os.time ([table])

+ +

Returns the current time when called without arguments, +or a time representing the date and time specified by the given table. +This table must have fields year, month, and day, +and may have fields hour, min, sec, and isdst +(for a description of these fields, see the os.date function). + +

The returned value is a number, whose meaning depends on your system. +In Posix, Windows, and some other systems, this number counts the number +of seconds since some given start time (the "epoch"). +In other systems, the meaning is not specified, +and the number returned by time can be used only as an argument to +date and difftime. + +

os.tmpname ()

+ +

Returns a string with a file name that can +be used for a temporary file. +The file must be explicitly opened before its use +and removed when no longer needed. + +

This function is equivalent to the tmpnam C function, +and many people (and even some compilers!) advise against its use, +because between the time you call this function +and the time you open the file, +it is possible for another process +to create a file with the same name. + +

5.8 - The Reflexive Debug Interface

+ +

The debug library provides +the functionality of the debug interface to Lua programs. +You should exert care when using this library. +The functions provided here should be used exclusively for debugging +and similar tasks, such as profiling. +Please resist the temptation to use them as a +usual programming tool: +They can be very slow. +Moreover, setlocal and getlocal +violate the privacy of local variables +and therefore can compromise some otherwise secure code. + +

All functions in this library are provided +inside a debug table. + +

debug.debug ()

+ +

Enters an interactive mode with the user, +running each string that the user enters. +Using simple commands and other debug facilities, +the user can inspect global and local variables, +change their values, evaluate expressions, and so on. +A line containing only the word cont finishes this function, +so that the caller continues its execution. + +

Note that commands for debug.debug are not lexically nested +with any function, so they have no direct access to local variables. + +

debug.gethook ()

+ +

Returns the current hook settings, as three values: +the current hook function, the current hook mask, +and the current hook count (as set by the debug.sethook function). + +

debug.getinfo (function [, what])

+ +

This function returns a table with information about a function. +You can give the function directly, +or you can give a number as the value of function, +which means the function running at level function of the call stack: +Level 0 is the current function (getinfo itself); +level 1 is the function that called getinfo; +and so on. +If function is a number larger than the number of active functions, +then getinfo returns nil. + +

The returned table contains all the fields returned by lua_getinfo, +with the string what describing which fields to fill in. +The default for what is to get all information available. +If present, +the option `f´ +adds a field named func with the function itself. + +

For instance, the expression debug.getinfo(1,"n").name returns +the name of the current function, if a reasonable name can be found, +and debug.getinfo(print) returns a table with all available information +about the print function. + +

debug.getlocal (level, local)

+ +

This function returns the name and the value of the local variable +with index local of the function at level level of the stack. +(The first parameter or local variable has index 1, and so on, +until the last active local variable.) +The function returns nil if there is no local +variable with the given index, +and raises an error when called with a level out of range. +(You can call debug.getinfo to check whether the level is valid.) + +

debug.getupvalue (func, up)

+ +

This function returns the name and the value of the upvalue +with index up of the function func. +The function returns nil if there is no upvalue with the given index. + +

debug.setlocal (level, local, value)

+ +

This function assigns the value value to the local variable +with index local of the function at level level of the stack. +The function returns nil if there is no local +variable with the given index, +and raises an error when called with a level out of range. +(You can call getinfo to check whether the level is valid.) + +

debug.setupvalue (func, up, value)

+ +

This function assigns the value value to the upvalue +with index up of the function func. +The function returns nil if there is no upvalue +with the given index. + +

debug.sethook (hook, mask [, count])

+ + +

Sets the given function as a hook. +The string mask and the number count describe +when the hook will be called. +The string mask may have the following characters, +with the given meaning: +

+With a count different from zero, +the hook is called after every count instructions. + +

When called without arguments, +the debug.sethook function turns off the hook. + +

When the hook is called, its first parameter is always a string +describing the event that triggered its call: +"call", "return" (or "tail return"), +"line", and "count". +Moreover, for line events, +it also gets as its second parameter the new line number. +Inside a hook, +you can call getinfo with level 2 to get more information about +the running function +(level 0 is the getinfo function, +and level 1 is the hook function), +unless the event is "tail return". +In this case, Lua is only simulating the return, +and a call to getinfo will return invalid data. + +

debug.traceback ([message])

+ +

Returns a string with a traceback of the call stack. +An optional message string is appended +at the beginning of the traceback. +This function is typically used with xpcall to produce +better error messages. + +

+

6 - Lua Stand-alone

+ +

Although Lua has been designed as an extension language, +to be embedded in a host C program, +it is also frequently used as a stand-alone language. +An interpreter for Lua as a stand-alone language, +called simply lua, +is provided with the standard distribution. +The stand-alone interpreter includes +all standard libraries plus the reflexive debug interface. +Its usage is: +

+      lua [options] [script [args]]
+
+The options are: + +After handling its options, lua runs the given script, +passing to it the given args. +When called without arguments, +lua behaves as lua -v -i when stdin is a terminal, +and as lua - otherwise. + +

Before running any argument, +the interpreter checks for an environment variable LUA_INIT. +If its format is @filename, +then lua executes the file. +Otherwise, lua executes the string itself. + +

All options are handled in order, except -i. +For instance, an invocation like +

+       $ lua -e'a=1' -e 'print(a)' script.lua
+
+will first set a to 1, then print a, +and finally run the file script.lua. +(Here, $ is the shell prompt. Your prompt may be different.) + +

Before starting to run the script, +lua collects all arguments in the command line +in a global table called arg. +The script name is stored in index 0, +the first argument after the script name goes to index 1, +and so on. +The field n gets the number of arguments after the script name. +Any arguments before the script name +(that is, the interpreter name plus the options) +go to negative indices. +For instance, in the call +

+       $ lua -la.lua b.lua t1 t2
+
+the interpreter first runs the file a.lua, +then creates a table +
+       arg = { [-2] = "lua", [-1] = "-la.lua", [0] = "b.lua",
+               [1] = "t1", [2] = "t2"; n = 2 }
+
+and finally runs the file b.lua. + +

In interactive mode, +if you write an incomplete statement, +the interpreter waits for its completion. + +

If the global variable _PROMPT is defined as a string, +then its value is used as the prompt. +Therefore, the prompt can be changed directly on the command line: +

+       $ lua -e"_PROMPT='myprompt> '" -i
+
+(the outer pair of quotes is for the shell, +the inner is for Lua), +or in any Lua programs by assigning to _PROMPT. +Note the use of -i to enter interactive mode; otherwise, +the program would end just after the assignment to _PROMPT. + +

In Unix systems, Lua scripts can be made into executable programs +by using chmod +x and the #! form, +as in +

+#!/usr/local/bin/lua
+
+(Of course, +the location of the Lua interpreter may be different in your machine. +If lua is in your PATH, +then +
+#!/usr/bin/env lua
+
+is a more portable solution.) + +

+

Acknowledgments

+ +

The Lua team is grateful to Tecgraf for its continued support to Lua. +We thank everyone at Tecgraf, +specially the head of the group, Marcelo Gattass. +At the risk of omitting several names, +we also thank the following individuals for supporting, +contributing to, and spreading the word about Lua: +Alan Watson. +André Clinio, +André Costa, +Antonio Scuri, +Asko Kauppi, +Bret Mogilefsky, +Cameron Laird, +Carlos Cassino, +Carlos Henrique Levy, +Claudio Terra, +David Jeske, +Ed Ferguson, +Edgar Toernig, +Erik Hougaard, +Jim Mathies, +John Belmonte, +John Passaniti, +John Roll, +Jon Erickson, +Jon Kleiser, +Mark Ian Barlow, +Nick Trout, +Noemi Rodriguez, +Norman Ramsey, +Philippe Lhoste, +Renata Ratton, +Renato Borges, +Renato Cerqueira, +Reuben Thomas, +Stephan Herrmann, +Steve Dekorte, +Thatcher Ulrich, +Tomás Gorham, +Vincent Penquerc'h. +Thank you! + +


+ +

Incompatibilities with Previous Versions

+ + +

Lua 5.0 is a major release. +There are several incompatibilities with its previous version, Lua 4.0. + +

Incompatibilities with version 4.0

+ +

Changes in the Language

+ + +

Changes in the Libraries

+ + +

Changes in the API

+ + +

+ +

The Complete Syntax of Lua

+ + +

+ +

+
+

chunk ::= {stat [`;´]} + +

block ::= chunk + +

stat ::= varlist1 `=´ explist1 | functioncall | do block end | while exp do block end | repeat block until exp | if exp then block {elseif exp then block} [else block] end | return [explist1] | break | for Name `=´ exp `,´ exp [`,´ exp] do block end | for Name {`,´ Name} in explist1 do block end | function funcname funcbody | local function Name funcbody | local namelist [init] + +

funcname ::= Name {`.´ Name} [`:´ Name] + +

varlist1 ::= var {`,´ var} + +

var ::= Name | prefixexp `[´ exp `]´ | prefixexp `.´ Name + +

namelist ::= Name {`,´ Name} + +

init ::= `=´ explist1 + +

explist1 ::= {exp `,´} exp + +

exp ::= nil | false | true | Number | Literal | function | prefixexp | tableconstructor | exp binop exp | unop exp + +

prefixexp ::= var | functioncall | `(´ exp `)´ + +

functioncall ::= prefixexp args | prefixexp `:´ Name args + +

args ::= `(´ [explist1] `)´ | tableconstructor | Literal + +

function ::= function funcbody + +

funcbody ::= `(´ [parlist1] `)´ block end + +

parlist1 ::= Name {`,´ Name} [`,´ `...´] | `...´ + +

tableconstructor ::= `{´ [fieldlist] `}´ + fieldlist ::= field {fieldsep field} [fieldsep] + field ::= `[´ exp `]´ `=´ exp | name `=´ exp | exp + fieldsep ::= `,´ | `;´ + +

binop ::= `+´ | `-´ | `*´ | `/´ | `^´ | `..´ | `<´ | `<=´ | `>´ | `>=´ | `==´ | `~=´ | and | or + +

unop ::= `-´ | not + +

+ +

+ +

+ +


+ +Last update: +Tue Nov 25 16:08:37 BRST 2003 + + + + diff --git a/doc/readme.html b/doc/readme.html new file mode 100644 index 0000000..baa7cc8 --- /dev/null +++ b/doc/readme.html @@ -0,0 +1,35 @@ + + +Lua documentation + + + + +
+

+Lua +Documentation +

+ + + +
+ +Last update: +Thu Mar 11 23:08:56 BRT 2004 + + + + diff --git a/etc/Makefile b/etc/Makefile new file mode 100644 index 0000000..1286c64 --- /dev/null +++ b/etc/Makefile @@ -0,0 +1,42 @@ +# makefile for Lua etc + +LUA= .. + +include $(LUA)/config + +LIBLUA=$(LIB)/liblua.a +ALL= bin2c min trace noparser luab + +all: + @echo 'choose a target:' $(ALL) + +bin2c: bin2c.c + $(CC) $(CFLAGS) -o $@ $@.c + +min: min.c $(LIBLUA) + $(CC) $(CFLAGS) -o $@ $@.c -L$(LIB) -llua + +trace: trace.c $(LIBLUA) + $(CC) -g $(CFLAGS) -o $@ $@.c -L$(LIB) -llua -llualib $(EXTRA_LIBS) + +noparser: noparser.c + $(CC) $(CFLAGS) -I$(LUA)/src -o $@.o -c $@.c + +luab: noparser $(LIBLUA) + cc -o $@ noparser.o $(LUA)/src/lua/lua.o -L$(LIB) -llua -llualib $(EXTRA_LIBS) + $(BIN)/luac $(LUA)/test/hello.lua + $@ luac.out + -$@ -e'a=1' + +flat: + cd ..; mkdir flat; mv include/*.h src/*.[ch] src/*/*.[ch] flat + +$(LIBLUA): + cd ../src; $(MAKE) + +clean: + rm -f $(ALL) a.out core *.o luac.out + +luser_tests.h: RCS/ltests.h,v + co -q -M ltests.h + mv -f ltests.h $@ diff --git a/etc/README b/etc/README new file mode 100644 index 0000000..c838a7f --- /dev/null +++ b/etc/README @@ -0,0 +1,54 @@ +This directory contains some useful files and code. +Unlike the code in ../src, everything here is in the public domain. + +bin2c.c + This program converts files to byte arrays that are automatically run + with lua_dobuffer. This allows C programs to include all necessary Lua + code, even in precompiled form. Even if the code is included in source + form, bin2c is useful because it avoids the hassle of having to quote + special characters in C strings. + Example of usage: Run bin2c file1 file2 ... > init.h. Then, in your + C program, just do #include "init.h" anywhere in the *body* of a + function. This will be equivalent to calling + lua_dofile(L,"file1"); lua_dofile(L,"file2"); ... + Note that the Lua state is called "L". If you use a different name, + say "mystate", just #define L mystate before you #include "init.h". + +compat.lua + A compatibility module for Lua 4.0 functions. + +doall.lua + Emulate the command line behaviour of Lua 4.0 + +lua.ico + A Lua icon for Windows. + Drawn by hand by Markus Gritsch . + +lua.magic + Data for teaching file(1) about Lua precompiled chunks. + +lua.xpm + The same icon as lua.ico, but in XPM format. + It was converted with ImageMagick by Andy Tai . + +luser_number.h + Number type configuration for Lua core. + +luser_tests.h + Self-test configuration for Lua core. + +min.c + A minimal Lua interpreter. + Good for learning and for starting your own. + +noparser.c + Linking with noparser.o avoids loading the parsing modules in lualib.a. + Do "make luab" to build a sample Lua intepreter that does not parse + Lua programs, only loads precompiled programs. + +saconfig.c + Configuration for Lua interpreter. + +trace.c + A simple execution tracer. + An example of how to use the debug hooks in C. diff --git a/etc/bin2c.c b/etc/bin2c.c new file mode 100644 index 0000000..0993b16 --- /dev/null +++ b/etc/bin2c.c @@ -0,0 +1,67 @@ +/* +* bin2c.c +* convert files to byte arrays for automatic loading with lua_dobuffer +* Luiz Henrique de Figueiredo (lhf@tecgraf.puc-rio.br) +* 02 Apr 2003 20:44:31 +*/ + +#include +#include +#include + +static void dump(FILE* f, int n) +{ + printf("static const unsigned char B%d[]={\n",n); + for (n=1;;n++) + { + int c=getc(f); + if (c==EOF) break; + printf("%3u,",c); + if (n==20) { putchar('\n'); n=0; } + } + printf("\n};\n\n"); +} + +static void fdump(const char* fn, int n) +{ + FILE* f= fopen(fn,"rb"); /* must open in binary mode */ + if (f==NULL) + { + fprintf(stderr,"bin2c: cannot open "); + perror(fn); + exit(1); + } + else + { + printf("/* %s */\n",fn); + dump(f,n); + fclose(f); + } +} + +static void emit(const char* fn, int n) +{ + printf(" lua_dobuffer(L,(const char*)B%d,sizeof(B%d),\"%s\");\n",n,n,fn); +} + +int main(int argc, char* argv[]) +{ + printf("/* code automatically generated by bin2c -- DO NOT EDIT */\n"); + printf("{\n"); + if (argc<2) + { + dump(stdin,0); + emit("=stdin",0); + } + else + { + int i; + printf("/* #include'ing this file in a C program is equivalent to calling\n"); + for (i=1; i protect(f, err) +-- loadfile +-- loadstring + +-- rawget +-- rawset + +-- getargs = Main.getargs ?? + + +function do_ (f, err) + if not f then print(err); return end + local a,b = pcall(f) + if not a then print(b); return nil + else return b or true + end +end + +function dostring(s) return do_(loadstring(s)) end +-- function dofile(s) return do_(loadfile(s)) end + +------------------------------------------------------------------- +-- Table library +local tab = table +foreach = tab.foreach +foreachi = tab.foreachi +getn = tab.getn +tinsert = tab.insert +tremove = tab.remove +sort = tab.sort + +------------------------------------------------------------------- +-- Debug library +local dbg = debug +getinfo = dbg.getinfo +getlocal = dbg.getlocal +setcallhook = function () error"`setcallhook' is deprecated" end +setlinehook = function () error"`setlinehook' is deprecated" end +setlocal = dbg.setlocal + +------------------------------------------------------------------- +-- math library +local math = math +abs = math.abs +acos = function (x) return math.deg(math.acos(x)) end +asin = function (x) return math.deg(math.asin(x)) end +atan = function (x) return math.deg(math.atan(x)) end +atan2 = function (x,y) return math.deg(math.atan2(x,y)) end +ceil = math.ceil +cos = function (x) return math.cos(math.rad(x)) end +deg = math.deg +exp = math.exp +floor = math.floor +frexp = math.frexp +ldexp = math.ldexp +log = math.log +log10 = math.log10 +max = math.max +min = math.min +mod = math.mod +PI = math.pi +--??? pow = math.pow +rad = math.rad +random = math.random +randomseed = math.randomseed +sin = function (x) return math.sin(math.rad(x)) end +sqrt = math.sqrt +tan = function (x) return math.tan(math.rad(x)) end + +------------------------------------------------------------------- +-- string library +local str = string +strbyte = str.byte +strchar = str.char +strfind = str.find +format = str.format +gsub = str.gsub +strlen = str.len +strlower = str.lower +strrep = str.rep +strsub = str.sub +strupper = str.upper + +------------------------------------------------------------------- +-- os library +clock = os.clock +date = os.date +difftime = os.difftime +execute = os.execute --? +exit = os.exit +getenv = os.getenv +remove = os.remove +rename = os.rename +setlocale = os.setlocale +time = os.time +tmpname = os.tmpname + +------------------------------------------------------------------- +-- compatibility only +getglobal = function (n) return _G[n] end +setglobal = function (n,v) _G[n] = v end + +------------------------------------------------------------------- + +local io, tab = io, table + +-- IO library (files) +_STDIN = io.stdin +_STDERR = io.stderr +_STDOUT = io.stdout +_INPUT = io.stdin +_OUTPUT = io.stdout +seek = io.stdin.seek -- sick ;-) +tmpfile = io.tmpfile +closefile = io.close +openfile = io.open + +function flush (f) + if f then f:flush() + else _OUTPUT:flush() + end +end + +function readfrom (name) + if name == nil then + local f, err, cod = io.close(_INPUT) + _INPUT = io.stdin + return f, err, cod + else + local f, err, cod = io.open(name, "r") + _INPUT = f or _INPUT + return f, err, cod + end +end + +function writeto (name) + if name == nil then + local f, err, cod = io.close(_OUTPUT) + _OUTPUT = io.stdout + return f, err, cod + else + local f, err, cod = io.open(name, "w") + _OUTPUT = f or _OUTPUT + return f, err, cod + end +end + +function appendto (name) + local f, err, cod = io.open(name, "a") + _OUTPUT = f or _OUTPUT + return f, err, cod +end + +function read (...) + local f = _INPUT + if type(arg[1]) == 'userdata' then + f = tab.remove(arg, 1) + end + return f:read(unpack(arg)) +end + +function write (...) + local f = _OUTPUT + if type(arg[1]) == 'userdata' then + f = tab.remove(arg, 1) + end + return f:write(unpack(arg)) +end + diff --git a/etc/doall.lua b/etc/doall.lua new file mode 100644 index 0000000..fb0fad7 --- /dev/null +++ b/etc/doall.lua @@ -0,0 +1,6 @@ +-- emulate the command line behaviour of Lua 4.0 +-- usage: lua doall.lua f1.lua f2.lua f3.lua ... + +for i=1,table.getn(arg) do + dofile(arg[i]) +end diff --git a/etc/lua.ico b/etc/lua.ico new file mode 100644 index 0000000..ccbabc4 Binary files /dev/null and b/etc/lua.ico differ diff --git a/etc/lua.magic b/etc/lua.magic new file mode 100644 index 0000000..c7ae595 --- /dev/null +++ b/etc/lua.magic @@ -0,0 +1,12 @@ + +# Lua precompiled files. Versions 2.3 and 4.1 were never officially released. +0 string \33Lua precompiled chunk for Lua +>4 byte 0x23 2.3* +>4 byte 0x24 2.4 +>4 byte 0x25 2.5 +>4 byte 0x30 3.0 +>4 byte 0x31 3.1 +>4 byte 0x32 3.2 +>4 byte 0x40 4.0 +>4 byte 0x41 4.1* +>4 byte 0x50 5.0 diff --git a/etc/lua.xpm b/etc/lua.xpm new file mode 100644 index 0000000..d3dcd37 --- /dev/null +++ b/etc/lua.xpm @@ -0,0 +1,44 @@ +/* XPM */ +static char *magick[] = { +/* columns rows colors chars-per-pixel */ +"32 32 6 1", +" c Gray0", +". c #000000008080", +"X c #808080808080", +"o c #c0c0c0c0c0c0", +"O c Gray100", +"+ c None", +/* pixels */ +"++++++++++++++++++++++++++ooo+++", +"++++++++++++++++++++++++oX...Xo+", +"++++++++++++++++++++++++X.....X+", +"+++++++++++++++++++++++o.......o", +"+++++++++XX......XX++++o.......o", +"+++++++X............X++o.......o", +"+++++o................o+X.....X+", +"++++X..................XoX...Xo+", +"+++X..............XXX...X+ooo+++", +"++o.............XoOOOoX..o++++++", +"++..............oOOOOOo...++++++", +"+X.............XOOOOOOOX..X+++++", +"+..............XOOOOOOOX...+++++", +"X..............XOOOOOOOX...X++++", +"X...............oOOOOOo....X++++", +"................XoOOOoX.....++++", +"....XO............XXX.......++++", +"....XO......................++++", +"....XO.....OX..OX.XOOOo.....++++", +"....XO.....OX..OX.OoXXOX....++++", +"....XO.....OX..OX....XOX....++++", +"X...XO.....OX..OX..OOoOX...X++++", +"X...XO.....OX..OX.OX..OX...X++++", +"+...XOXXXX.OoXoOX.OXXXOX...+++++", +"+X..XOOOOO.XOOXOX.XOOOXo..X+++++", +"++........................++++++", +"++o......................o++++++", +"+++X....................X+++++++", +"++++X..................X++++++++", +"+++++o................o+++++++++", +"+++++++X............X+++++++++++", +"+++++++++XX......XX+++++++++++++" +}; diff --git a/etc/luser_number.h b/etc/luser_number.h new file mode 100644 index 0000000..8cc2678 --- /dev/null +++ b/etc/luser_number.h @@ -0,0 +1,34 @@ +/* luser_number.h -- number type configuration for Lua core +* +* #define LUA_USER_H to this file and #define one of USE_* below +*/ + +#ifdef USE_DOUBLE +#define LUA_NUMBER double +#define LUA_NUMBER_SCAN "%lf" +#define LUA_NUMBER_FMT "%.14g" +#endif + +#ifdef USE_FLOAT +#define LUA_NUMBER float +#define LUA_NUMBER_SCAN "%f" +#define LUA_NUMBER_FMT "%.5g" +#endif + +#ifdef USE_LONG +#define LUA_NUMBER long +#define LUA_NUMBER_SCAN "%ld" +#define LUA_NUMBER_FMT "%ld" +#define lua_str2number(s,p) strtol((s), (p), 10) +#endif + +#ifdef USE_INT +#define LUA_NUMBER int +#define LUA_NUMBER_SCAN "%d" +#define LUA_NUMBER_FMT "%d" +#define lua_str2number(s,p) ((int) strtol((s), (p), 10)) +#endif + +#ifdef USE_FASTROUND +#define lua_number2int(i,d) __asm__("fldl %1\nfistpl %0":"=m"(i):"m"(d)) +#endif diff --git a/etc/luser_tests.h b/etc/luser_tests.h new file mode 100644 index 0000000..1ee6e3f --- /dev/null +++ b/etc/luser_tests.h @@ -0,0 +1,68 @@ +/* +** $Id: ltests.h,v 1.20 2002/12/04 17:29:05 roberto Exp $ +** Internal Header for Debugging of the Lua Implementation +** See Copyright Notice in lua.h +*/ + +#ifndef ltests_h +#define ltests_h + + +#include + + +#define LUA_DEBUG + +#define LUA_OPNAMES + +#undef NDEBUG +#include +#define lua_assert(c) assert(c) +#define check_exp(c,e) (lua_assert(c), (e)) +#define api_check(L, o) lua_assert(o) + + +/* to avoid warnings, and to make sure value is really unused */ +#define UNUSED(x) (x=0, (void)(x)) + + +/* memory allocator control variables */ +extern unsigned long memdebug_numblocks; +extern unsigned long memdebug_total; +extern unsigned long memdebug_maxmem; +extern unsigned long memdebug_memlimit; + + +#define l_realloc(b, os, s) debug_realloc(b, os, s) +#define l_free(b, os) debug_realloc(b, os, 0) + +void *debug_realloc (void *block, size_t oldsize, size_t size); + + + +/* test for lock/unlock */ +extern int islocked; +#define LUA_USERSTATE int * +#define getlock(l) (*(cast(LUA_USERSTATE *, l) - 1)) +#define lua_userstateopen(l) if (l != NULL) getlock(l) = &islocked; +#define lua_lock(l) lua_assert((*getlock(l))++ == 0) +#define lua_unlock(l) lua_assert(--(*getlock(l)) == 0) + + +int luaB_opentests (lua_State *L); + +#define LUA_EXTRALIBS { "tests", luaB_opentests }, + + +/* real main will be defined at `ltests.c' */ +int l_main (int argc, char *argv[]); +#define main l_main + + + +/* change some sizes to give some bugs a chance */ + +#define LUAL_BUFFERSIZE 27 +#define MINSTRTABSIZE 2 + +#endif diff --git a/etc/min.c b/etc/min.c new file mode 100644 index 0000000..45731c9 --- /dev/null +++ b/etc/min.c @@ -0,0 +1,46 @@ +/* +* min.c -- a minimal Lua interpreter +* loads stdin only with minimal error handling. +* no interaction, and no standard library, only a "print" function. +*/ + +#include +#include "lua.h" + +static int print(lua_State *L) +{ + int n=lua_gettop(L); + int i; + for (i=1; i<=n; i++) + { + if (i>1) printf("\t"); + if (lua_isstring(L,i)) + printf("%s",lua_tostring(L,i)); + else if (lua_isnil(L,i)) + printf("%s","nil"); + else if (lua_isboolean(L,i)) + printf("%s",lua_toboolean(L,i) ? "true" : "false"); + else + printf("%s:%p",lua_typename(L,lua_type(L,i)),lua_topointer(L,i)); + } + printf("\n"); + return 0; +} + +static const char *getF(lua_State *L, void *ud, size_t *size) +{ + FILE *f=(FILE *)ud; + static char buff[512]; + if (feof(f)) return NULL; + *size=fread(buff,1,sizeof(buff),f); + return (*size>0) ? buff : NULL; +} + +int main(void) +{ + lua_State *L=lua_open(); + lua_register(L,"print",print); + if (lua_load(L,getF,stdin,"=stdin") || lua_pcall(L,0,0,0)) + fprintf(stderr,"%s\n",lua_tostring(L,-1)); + return 0; +} diff --git a/etc/noparser.c b/etc/noparser.c new file mode 100644 index 0000000..00c2b12 --- /dev/null +++ b/etc/noparser.c @@ -0,0 +1,26 @@ +/* +* The code below can be used to make a Lua core that does not contain the +* parsing modules (lcode, llex, lparser), which represent 35% of the total core. +* You'll only be able to load binary files and strings, precompiled with luac. +* (Of course, you'll have to build luac with the original parsing modules!) +* +* To use this module, simply compile it ("make noparser" does that) and +* list its object file before the Lua libraries. The linker should then not +* load the parsing modules. To try it, do "make luab". +*/ + +#include "llex.h" +#include "lparser.h" +#include "lzio.h" + +void luaX_init (lua_State *L) { + UNUSED(L); +} + +Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff) { + UNUSED(z); + UNUSED(buff); + lua_pushstring(L,"parser not loaded"); + lua_error(L); + return NULL; +} diff --git a/etc/saconfig.c b/etc/saconfig.c new file mode 100644 index 0000000..bf3c64b --- /dev/null +++ b/etc/saconfig.c @@ -0,0 +1,87 @@ +/* sa-config.c -- configuration for stand-alone Lua interpreter +* +* #define LUA_USERCONFIG to this file +* +* Here are the features that can be customized using #define: +* +*** Line edit and history: +* #define USE_READLINE to use the GNU readline library. +* +* To use another library for this, use the code below as a start. +* Make sure you #define lua_readline and lua_saveline accordingly. +* If you do not #define lua_readline, you'll get a version based on fgets +* that uses a static buffer of size MAXINPUT. +* +* +*** Static Lua libraries to be loaded at startup: +* #define lua_userinit(L) to a Lua function that loads libraries; typically +* #define lua_userinit(L) openstdlibs(L);myinit(L) +* or +* #define lua_userinit(L) myinit(L) +* +* Another way is to add the prototypes of the init functions here and +* #define LUA_EXTRALIBS accordingly. For example, +* #define LUA_EXTRALIBS {"mylib","luaopen_mylib"}, +* Note the ending comma! +* +* +*** Prompts: +* The stand-alone Lua interpreter uses two prompts: PROMPT and PROMPT2. +* PROMPT is the primary prompt, shown when the intepreter is ready to receive +* a new statement. PROMPT2 is the secondary prompt, shown while a statement +* is being entered but is still incomplete. +* +* +*** Program name: +* Error messages usually show argv[0] as a program name. In systems that do +* not give a valid string as argv[0], error messages show PROGNAME instead. +* +* +*/ + +#ifdef USE_READLINE +/* +* This section implements of lua_readline and lua_saveline for lua.c using +* the GNU readline and history libraries. It should also work with drop-in +* replacements such as editline and libedit (you may have to include +* different headers, though). +* +*/ + +#define lua_readline myreadline +#define lua_saveline mysaveline + +#include +#include +#include + +static int myreadline (lua_State *L, const char *prompt) { + char *s=readline(prompt); + if (s==NULL) + return 0; + else { + lua_pushstring(L,s); + lua_pushliteral(L,"\n"); + lua_concat(L,2); + free(s); + return 1; + } +} + +static void mysaveline (lua_State *L, const char *s) { + const char *p; + for (p=s; isspace(*p); p++) + ; + if (*p!=0) { + size_t n=strlen(s)-1; + if (s[n]!='\n') + add_history(s); + else { + lua_pushlstring(L,s,n); + s=lua_tostring(L,-1); + add_history(s); + lua_remove(L,-1); + } + } +} +#endif diff --git a/etc/trace.c b/etc/trace.c new file mode 100644 index 0000000..c29f1c9 --- /dev/null +++ b/etc/trace.c @@ -0,0 +1,55 @@ +/* +* trace.c -- a simple execution tracer for Lua +*/ + +#include +#include +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" + +static FILE* LOG; /* log file */ +static int I=0; /* indentation level */ + +static void hook(lua_State *L, lua_Debug *ar) +{ + const char* s=""; + switch (ar->event) + { + case LUA_HOOKTAILRET: ar->event=LUA_HOOKRET; + case LUA_HOOKRET: s="return"; break; + case LUA_HOOKCALL: s="call"; break; + case LUA_HOOKLINE: s="line"; break; + default: break; + } + fprintf(LOG,"[%d]\t%*s%s\t-- %d\n",I,I,"",s,ar->currentline); + if (ar->event==LUA_HOOKCALL) ++I; else if (ar->event==LUA_HOOKRET) --I; +} + +static void start_trace(lua_State *L, FILE* logfile) +{ + lua_sethook(L,hook,LUA_MASKCALL | LUA_MASKRET | LUA_MASKLINE, 0); + LOG=logfile; +} + +static void stop_trace(lua_State *L) +{ + lua_sethook(L,NULL,0,0); + fclose(LOG); +} + +int main(void) +{ + int rc; + lua_State *L=lua_open(); + lua_baselibopen(L); + lua_tablibopen(L); + lua_iolibopen(L); + lua_strlibopen(L); + lua_mathlibopen(L); + lua_dblibopen(L); + start_trace(L,stderr); + rc=lua_dofile(L,NULL); + stop_trace(L); + return rc; +} diff --git a/include/Makefile b/include/Makefile new file mode 100644 index 0000000..d75997d --- /dev/null +++ b/include/Makefile @@ -0,0 +1,17 @@ +# makefile for Lua distribution (includes) + +LUA= .. + +include $(LUA)/config + +SRCS= lua.h lualib.h lauxlib.h + +all: + +clean: + +co: + co -q -f -M $(SRCS) + +klean: clean + rm -f $(SRCS) diff --git a/include/lauxlib.h b/include/lauxlib.h new file mode 100644 index 0000000..450e16c --- /dev/null +++ b/include/lauxlib.h @@ -0,0 +1,145 @@ +/* +** $Id: lauxlib.h,v 1.60 2003/04/03 13:35:34 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lauxlib_h +#define lauxlib_h + + +#include +#include + +#include "lua.h" + + +#ifndef LUALIB_API +#define LUALIB_API LUA_API +#endif + + + +typedef struct luaL_reg { + const char *name; + lua_CFunction func; +} luaL_reg; + + +LUALIB_API void luaL_openlib (lua_State *L, const char *libname, + const luaL_reg *l, int nup); +LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *e); +LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *e); +LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname); +LUALIB_API int luaL_argerror (lua_State *L, int numarg, const char *extramsg); +LUALIB_API const char *luaL_checklstring (lua_State *L, int numArg, size_t *l); +LUALIB_API const char *luaL_optlstring (lua_State *L, int numArg, + const char *def, size_t *l); +LUALIB_API lua_Number luaL_checknumber (lua_State *L, int numArg); +LUALIB_API lua_Number luaL_optnumber (lua_State *L, int nArg, lua_Number def); + +LUALIB_API void luaL_checkstack (lua_State *L, int sz, const char *msg); +LUALIB_API void luaL_checktype (lua_State *L, int narg, int t); +LUALIB_API void luaL_checkany (lua_State *L, int narg); + +LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname); +LUALIB_API void luaL_getmetatable (lua_State *L, const char *tname); +LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname); + +LUALIB_API void luaL_where (lua_State *L, int lvl); +LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...); + +LUALIB_API int luaL_findstring (const char *st, const char *const lst[]); + +LUALIB_API int luaL_ref (lua_State *L, int t); +LUALIB_API void luaL_unref (lua_State *L, int t, int ref); + +LUALIB_API int luaL_getn (lua_State *L, int t); +LUALIB_API void luaL_setn (lua_State *L, int t, int n); + +LUALIB_API int luaL_loadfile (lua_State *L, const char *filename); +LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t sz, + const char *name); + + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define luaL_argcheck(L, cond,numarg,extramsg) if (!(cond)) \ + luaL_argerror(L, numarg,extramsg) +#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) +#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) +#define luaL_checkint(L,n) ((int)luaL_checknumber(L, n)) +#define luaL_checklong(L,n) ((long)luaL_checknumber(L, n)) +#define luaL_optint(L,n,d) ((int)luaL_optnumber(L, n,(lua_Number)(d))) +#define luaL_optlong(L,n,d) ((long)luaL_optnumber(L, n,(lua_Number)(d))) + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + + +#ifndef LUAL_BUFFERSIZE +#define LUAL_BUFFERSIZE BUFSIZ +#endif + + +typedef struct luaL_Buffer { + char *p; /* current position in buffer */ + int lvl; /* number of strings in the stack (level) */ + lua_State *L; + char buffer[LUAL_BUFFERSIZE]; +} luaL_Buffer; + +#define luaL_putchar(B,c) \ + ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ + (*(B)->p++ = (char)(c))) + +#define luaL_addsize(B,n) ((B)->p += (n)) + +LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B); +LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B); +LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l); +LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s); +LUALIB_API void luaL_addvalue (luaL_Buffer *B); +LUALIB_API void luaL_pushresult (luaL_Buffer *B); + + +/* }====================================================== */ + + + +/* +** Compatibility macros and functions +*/ + +LUALIB_API int lua_dofile (lua_State *L, const char *filename); +LUALIB_API int lua_dostring (lua_State *L, const char *str); +LUALIB_API int lua_dobuffer (lua_State *L, const char *buff, size_t sz, + const char *n); + + +#define luaL_check_lstr luaL_checklstring +#define luaL_opt_lstr luaL_optlstring +#define luaL_check_number luaL_checknumber +#define luaL_opt_number luaL_optnumber +#define luaL_arg_check luaL_argcheck +#define luaL_check_string luaL_checkstring +#define luaL_opt_string luaL_optstring +#define luaL_check_int luaL_checkint +#define luaL_check_long luaL_checklong +#define luaL_opt_int luaL_optint +#define luaL_opt_long luaL_optlong + + +#endif + + diff --git a/include/lua.h b/include/lua.h new file mode 100644 index 0000000..953e813 --- /dev/null +++ b/include/lua.h @@ -0,0 +1,395 @@ +/* +** $Id: lua.h,v 1.175b 2003/03/18 12:31:39 roberto Exp $ +** Lua - An Extensible Extension Language +** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil +** http://www.lua.org mailto:info@lua.org +** See Copyright Notice at the end of this file +*/ + + +#ifndef lua_h +#define lua_h + +#include +#include + + +#define LUA_VERSION "Lua 5.0.2" +#define LUA_COPYRIGHT "Copyright (C) 1994-2004 Tecgraf, PUC-Rio" +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" + + + +/* option for multiple returns in `lua_pcall' and `lua_call' */ +#define LUA_MULTRET (-1) + + +/* +** pseudo-indices +*/ +#define LUA_REGISTRYINDEX (-10000) +#define LUA_GLOBALSINDEX (-10001) +#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) + + +/* error codes for `lua_load' and `lua_pcall' */ +#define LUA_ERRRUN 1 +#define LUA_ERRFILE 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRERR 5 + + +typedef struct lua_State lua_State; + +typedef int (*lua_CFunction) (lua_State *L); + + +/* +** functions that read/write blocks when loading/dumping Lua chunks +*/ +typedef const char * (*lua_Chunkreader) (lua_State *L, void *ud, size_t *sz); + +typedef int (*lua_Chunkwriter) (lua_State *L, const void* p, + size_t sz, void* ud); + + +/* +** basic types +*/ +#define LUA_TNONE (-1) + +#define LUA_TNIL 0 +#define LUA_TBOOLEAN 1 +#define LUA_TLIGHTUSERDATA 2 +#define LUA_TNUMBER 3 +#define LUA_TSTRING 4 +#define LUA_TTABLE 5 +#define LUA_TFUNCTION 6 +#define LUA_TUSERDATA 7 +#define LUA_TTHREAD 8 + + +/* minimum Lua stack available to a C function */ +#define LUA_MINSTACK 20 + + +/* +** generic extra include file +*/ +#ifdef LUA_USER_H +#include LUA_USER_H +#endif + + +/* type of numbers in Lua */ +#ifndef LUA_NUMBER +typedef double lua_Number; +#else +typedef LUA_NUMBER lua_Number; +#endif + + +/* mark for all API functions */ +#ifndef LUA_API +#ifndef LUA_DLL +# define LUA_API extern "C" +#else +# define LUA_API extern "C" __declspec(dllexport) +#endif +#endif + + +/* +** state manipulation +*/ +LUA_API lua_State *lua_open (void); +LUA_API void lua_close (lua_State *L); +LUA_API lua_State *lua_newthread (lua_State *L); + +LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf); + + +/* +** basic stack manipulation +*/ +LUA_API int lua_gettop (lua_State *L); +LUA_API void lua_settop (lua_State *L, int idx); +LUA_API void lua_pushvalue (lua_State *L, int idx); +LUA_API void lua_remove (lua_State *L, int idx); +LUA_API void lua_insert (lua_State *L, int idx); +LUA_API void lua_replace (lua_State *L, int idx); +LUA_API int lua_checkstack (lua_State *L, int sz); + +LUA_API void lua_xmove (lua_State *from, lua_State *to, int n); + + +/* +** access functions (stack -> C) +*/ + +LUA_API int lua_isnumber (lua_State *L, int idx); +LUA_API int lua_isstring (lua_State *L, int idx); +LUA_API int lua_iscfunction (lua_State *L, int idx); +LUA_API int lua_isuserdata (lua_State *L, int idx); +LUA_API int lua_type (lua_State *L, int idx); +LUA_API const char *lua_typename (lua_State *L, int tp); + +LUA_API int lua_equal (lua_State *L, int idx1, int idx2); +LUA_API int lua_rawequal (lua_State *L, int idx1, int idx2); +LUA_API int lua_lessthan (lua_State *L, int idx1, int idx2); + +LUA_API lua_Number lua_tonumber (lua_State *L, int idx); +LUA_API int lua_toboolean (lua_State *L, int idx); +LUA_API const char *lua_tostring (lua_State *L, int idx); +LUA_API size_t lua_strlen (lua_State *L, int idx); +LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx); +LUA_API void *lua_touserdata (lua_State *L, int idx); +LUA_API lua_State *lua_tothread (lua_State *L, int idx); +LUA_API const void *lua_topointer (lua_State *L, int idx); + + +/* +** push functions (C -> stack) +*/ +LUA_API void lua_pushnil (lua_State *L); +LUA_API void lua_pushnumber (lua_State *L, lua_Number n); +LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t l); +LUA_API void lua_pushstring (lua_State *L, const char *s); +LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, + va_list argp); +LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...); +LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n); +LUA_API void lua_pushboolean (lua_State *L, int b); +LUA_API void lua_pushlightuserdata (lua_State *L, void *p); + + +/* +** get functions (Lua -> stack) +*/ +LUA_API void lua_gettable (lua_State *L, int idx); +LUA_API void lua_rawget (lua_State *L, int idx); +LUA_API void lua_rawgeti (lua_State *L, int idx, int n); +LUA_API void lua_newtable (lua_State *L); +LUA_API void *lua_newuserdata (lua_State *L, size_t sz); +LUA_API int lua_getmetatable (lua_State *L, int objindex); +LUA_API void lua_getfenv (lua_State *L, int idx); + + +/* +** set functions (stack -> Lua) +*/ +LUA_API void lua_settable (lua_State *L, int idx); +LUA_API void lua_rawset (lua_State *L, int idx); +LUA_API void lua_rawseti (lua_State *L, int idx, int n); +LUA_API int lua_setmetatable (lua_State *L, int objindex); +LUA_API int lua_setfenv (lua_State *L, int idx); + + +/* +** `load' and `call' functions (load and run Lua code) +*/ +LUA_API void lua_call (lua_State *L, int nargs, int nresults); +LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc); +LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud); +LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *dt, + const char *chunkname); + +LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data); + + +/* +** coroutine functions +*/ +LUA_API int lua_yield (lua_State *L, int nresults); +LUA_API int lua_resume (lua_State *L, int narg); + +/* +** garbage-collection functions +*/ +LUA_API int lua_getgcthreshold (lua_State *L); +LUA_API int lua_getgccount (lua_State *L); +LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold); + +/* +** miscellaneous functions +*/ + +LUA_API const char *lua_version (void); + +LUA_API int lua_error (lua_State *L); + +LUA_API int lua_next (lua_State *L, int idx); + +LUA_API void lua_concat (lua_State *L, int n); + + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define lua_boxpointer(L,u) \ + (*(void **)(lua_newuserdata(L, sizeof(void *))) = (u)) + +#define lua_unboxpointer(L,i) (*(void **)(lua_touserdata(L, i))) + +#define lua_pop(L,n) lua_settop(L, -(n)-1) + +#define lua_register(L,n,f) \ + (lua_pushstring(L, n), \ + lua_pushcfunction(L, f), \ + lua_settable(L, LUA_GLOBALSINDEX)) + +#define lua_pushcfunction(L,f) lua_pushcclosure(L, f, 0) + +#define lua_isfunction(L,n) (lua_type(L,n) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L,n) == LUA_TTABLE) +#define lua_islightuserdata(L,n) (lua_type(L,n) == LUA_TLIGHTUSERDATA) +#define lua_isnil(L,n) (lua_type(L,n) == LUA_TNIL) +#define lua_isboolean(L,n) (lua_type(L,n) == LUA_TBOOLEAN) +#define lua_isnone(L,n) (lua_type(L,n) == LUA_TNONE) +#define lua_isnoneornil(L, n) (lua_type(L,n) <= 0) + +#define lua_pushliteral(L, s) \ + lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) + + + +/* +** compatibility macros and functions +*/ + + +LUA_API int lua_pushupvalues (lua_State *L); + +#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) +#define lua_setglobal(L,s) \ + (lua_pushstring(L, s), lua_insert(L, -2), lua_settable(L, LUA_GLOBALSINDEX)) + +#define lua_getglobal(L,s) \ + (lua_pushstring(L, s), lua_gettable(L, LUA_GLOBALSINDEX)) + + +/* compatibility with ref system */ + +/* pre-defined references */ +#define LUA_NOREF (-2) +#define 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) + + + +/* +** {====================================================================== +** useful definitions for Lua kernel and libraries +** ======================================================================= +*/ + +/* formats for Lua numbers */ +#ifndef LUA_NUMBER_SCAN +#define LUA_NUMBER_SCAN "%lf" +#endif + +#ifndef LUA_NUMBER_FMT +#define LUA_NUMBER_FMT "%.14g" +#endif + +/* }====================================================================== */ + + +/* +** {====================================================================== +** Debug API +** ======================================================================= +*/ + + +/* +** Event codes +*/ +#define LUA_HOOKCALL 0 +#define LUA_HOOKRET 1 +#define LUA_HOOKLINE 2 +#define LUA_HOOKCOUNT 3 +#define LUA_HOOKTAILRET 4 + + +/* +** Event masks +*/ +#define LUA_MASKCALL (1 << LUA_HOOKCALL) +#define LUA_MASKRET (1 << LUA_HOOKRET) +#define LUA_MASKLINE (1 << LUA_HOOKLINE) +#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) + +typedef struct lua_Debug lua_Debug; /* activation record */ + +typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); + + +LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); +LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); +LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); + +LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); +LUA_API lua_Hook lua_gethook (lua_State *L); +LUA_API int lua_gethookmask (lua_State *L); +LUA_API int lua_gethookcount (lua_State *L); + + +#define LUA_IDSIZE 60 + +struct lua_Debug { + int event; + const char *name; /* (n) */ + const char *namewhat; /* (n) `global', `local', `field', `method' */ + const char *what; /* (S) `Lua', `C', `main', `tail' */ + const char *source; /* (S) */ + int currentline; /* (l) */ + int nups; /* (u) number of upvalues */ + int linedefined; /* (S) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + int i_ci; /* active function */ +}; + +/* }====================================================================== */ + + +/****************************************************************************** +* Copyright (C) 1994-2004 Tecgraf, PUC-Rio. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + + +#endif diff --git a/include/lualib.h b/include/lualib.h new file mode 100644 index 0000000..e22c4c3 --- /dev/null +++ b/include/lualib.h @@ -0,0 +1,56 @@ +/* +** $Id: lualib.h,v 1.28 2003/03/18 12:24:26 roberto Exp $ +** Lua standard libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lualib_h +#define lualib_h + +#include "lua.h" + + +#ifndef LUALIB_API +#define LUALIB_API LUA_API +#endif + + +#define LUA_COLIBNAME "coroutine" +LUALIB_API int luaopen_base (lua_State *L); + +#define LUA_TABLIBNAME "table" +LUALIB_API int luaopen_table (lua_State *L); + +#define LUA_IOLIBNAME "io" +#define LUA_OSLIBNAME "os" +LUALIB_API int luaopen_io (lua_State *L); + +#define LUA_STRLIBNAME "string" +LUALIB_API int luaopen_string (lua_State *L); + +#define LUA_MATHLIBNAME "math" +LUALIB_API int luaopen_math (lua_State *L); + +#define LUA_DBLIBNAME "debug" +LUALIB_API int luaopen_debug (lua_State *L); + + +LUALIB_API int luaopen_loadlib (lua_State *L); + + +/* to help testing the libraries */ +#ifndef lua_assert +#define lua_assert(c) /* empty */ +#endif + + +/* compatibility code */ +#define lua_baselibopen luaopen_base +#define lua_tablibopen luaopen_table +#define lua_iolibopen luaopen_io +#define lua_strlibopen luaopen_string +#define lua_mathlibopen luaopen_math +#define lua_dblibopen luaopen_debug + +#endif diff --git a/lua/502_plugin/502_plugin.vcxproj b/lua/502_plugin/502_plugin.vcxproj new file mode 100644 index 0000000..dd915c5 --- /dev/null +++ b/lua/502_plugin/502_plugin.vcxproj @@ -0,0 +1,74 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {7159FC3C-3F14-4884-B97F-C2D80765A104} + My502_plugin + + + + Application + true + MultiByte + + + DynamicLibrary + false + true + MultiByte + + + + + + + + + + + + + ..\..\..\GMod9_Server\gmod9\lua\bin + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + true + true + D:\lua502\lua\lua502_sdk;D:\source2006\public\tier1;D:\source2006\public\tier0;D:\source2006\public;D:\source2006\common;%(AdditionalIncludeDirectories) + + + true + true + true + D:\lua502\lua\Release;D:\source2006\lib\public;%(AdditionalLibraryDirectories) + tier0.lib;tier1.lib;lua502_sdk.lib;%(AdditionalDependencies) + LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) + + + + + + + + + \ No newline at end of file diff --git a/lua/502_plugin/502_plugin.vcxproj.filters b/lua/502_plugin/502_plugin.vcxproj.filters new file mode 100644 index 0000000..1aa6936 --- /dev/null +++ b/lua/502_plugin/502_plugin.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Файлы иÑходного кода + + + \ No newline at end of file diff --git a/lua/502_plugin/502_plugin.vcxproj.user b/lua/502_plugin/502_plugin.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/lua/502_plugin/502_plugin.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lua/502_plugin/Release/502_plugin.dll.intermediate.manifest b/lua/502_plugin/Release/502_plugin.dll.intermediate.manifest new file mode 100644 index 0000000..ecea6f7 --- /dev/null +++ b/lua/502_plugin/Release/502_plugin.dll.intermediate.manifest @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/lua/502_plugin/Release/502_plugin.lastbuildstate b/lua/502_plugin/Release/502_plugin.lastbuildstate new file mode 100644 index 0000000..c2d4a05 --- /dev/null +++ b/lua/502_plugin/Release/502_plugin.lastbuildstate @@ -0,0 +1,2 @@ +#v4.0:v100:false +Release|Win32|D:\lua502\lua\| diff --git a/lua/502_plugin/Release/502_plugin.log b/lua/502_plugin/Release/502_plugin.log new file mode 100644 index 0000000..2ccd18d --- /dev/null +++ b/lua/502_plugin/Release/502_plugin.log @@ -0,0 +1,23 @@ +Build started 27.10.2017 17:32:40. + 1>Project "D:\lua502\lua\502_plugin\502_plugin.vcxproj" on node 2 (build target(s)). + 1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppBuild.targets(299,5): warning MSB8004: каталог Output заканчиваетÑÑ Ð½Ðµ коÑой чертой. Этот ÑкземплÑÑ€ поÑÑ‚Ñ€Ð¾ÐµÐ½Ð¸Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ‚ коÑую черту, поÑкольку она необходима Ð´Ð»Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ð¾Ð³Ð¾ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð° Output. + 1>InitializeBuildStatus: + Touching "Release\502_plugin.unsuccessfulbuild". + ClCompile: + All outputs are up-to-date. + Link: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:"..\..\..\GMod9_Server\gmod9\lua\bin\502_plugin.dll" /NOLOGO /LIBPATH:D:\lua502\lua\Release /LIBPATH:D:\source2006\lib\public tier0.lib tier1.lib lua502_sdk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NODEFAULTLIB:LIBCMT.lib /MANIFEST /ManifestFile:"Release\502_plugin.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"D:\GMod9_Server\gmod9\lua\bin\502_plugin.pdb" /OPT:REF /OPT:ICF /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"..\..\..\GMod9_Server\gmod9\lua\bin\502_plugin.lib" /MACHINE:X86 /DLL Release\main.obj + СоздаетÑÑ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ° ..\..\..\GMod9_Server\gmod9\lua\bin\502_plugin.lib и объект ..\..\..\GMod9_Server\gmod9\lua\bin\502_plugin.exp + Создание кода + Создание кода завершено + 502_plugin.vcxproj -> D:\lua502\lua\502_plugin\..\..\..\GMod9_Server\gmod9\lua\bin\502_plugin.dll + Manifest: + C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe /nologo /verbose /outputresource:"..\..\..\GMod9_Server\gmod9\lua\bin\502_plugin.dll;#2" /manifest Release\502_plugin.dll.intermediate.manifest + FinalizeBuildStatus: + Deleting file "Release\502_plugin.unsuccessfulbuild". + Touching "Release\502_plugin.lastbuildstate". + 1>Done Building Project "D:\lua502\lua\502_plugin\502_plugin.vcxproj" (build target(s)). + +ПоÑтроение уÑпешно завершено. + +Time Elapsed 00:00:01.61 diff --git a/lua/502_plugin/Release/502_plugin.vcxprojResolveAssemblyReference.cache b/lua/502_plugin/Release/502_plugin.vcxprojResolveAssemblyReference.cache new file mode 100644 index 0000000..3f01681 Binary files /dev/null and b/lua/502_plugin/Release/502_plugin.vcxprojResolveAssemblyReference.cache differ diff --git a/lua/502_plugin/Release/502_plugin.write.1.tlog b/lua/502_plugin/Release/502_plugin.write.1.tlog new file mode 100644 index 0000000..0280685 --- /dev/null +++ b/lua/502_plugin/Release/502_plugin.write.1.tlog @@ -0,0 +1,30 @@ +^D:\lua502\lua\502_plugin\502_plugin.vcxproj +D:\GMod9_Server\gmod9\lua\bin\502_plugin.lib +D:\GMod9_Server\gmod9\lua\bin\502_plugin.lib +D:\GMod9_Server\gmod9\lua\bin\502_plugin.exp +D:\GMod9_Server\gmod9\lua\bin\502_plugin.exp +^D:\lua502\lua\502_plugin\502_plugin.vcxproj +D:\GMod9_Server\gmod9\lua\bin\502_plugin.lib +D:\GMod9_Server\gmod9\lua\bin\502_plugin.lib +D:\GMod9_Server\gmod9\lua\bin\502_plugin.exp +D:\GMod9_Server\gmod9\lua\bin\502_plugin.exp +^D:\lua502\lua\502_plugin\502_plugin.vcxproj +D:\GMod9_Server\gmod9\lua\bin\502_plugin.lib +D:\GMod9_Server\gmod9\lua\bin\502_plugin.lib +D:\GMod9_Server\gmod9\lua\bin\502_plugin.exp +D:\GMod9_Server\gmod9\lua\bin\502_plugin.exp +^D:\lua502\lua\502_plugin\502_plugin.vcxproj +D:\GMod9_Server\gmod9\lua\bin\502_plugin.lib +D:\GMod9_Server\gmod9\lua\bin\502_plugin.lib +D:\GMod9_Server\gmod9\lua\bin\502_plugin.exp +D:\GMod9_Server\gmod9\lua\bin\502_plugin.exp +^D:\lua502\lua\502_plugin\502_plugin.vcxproj +D:\GMod9_Server\gmod9\lua\bin\502_plugin.lib +D:\GMod9_Server\gmod9\lua\bin\502_plugin.lib +D:\GMod9_Server\gmod9\lua\bin\502_plugin.exp +D:\GMod9_Server\gmod9\lua\bin\502_plugin.exp +^D:\lua502\lua\502_plugin\502_plugin.vcxproj +D:\GMod9_Server\gmod9\lua\bin\502_plugin.lib +D:\GMod9_Server\gmod9\lua\bin\502_plugin.lib +D:\GMod9_Server\gmod9\lua\bin\502_plugin.exp +D:\GMod9_Server\gmod9\lua\bin\502_plugin.exp diff --git a/lua/502_plugin/Release/CL.read.1.tlog b/lua/502_plugin/Release/CL.read.1.tlog new file mode 100644 index 0000000..2ba8a4c Binary files /dev/null and b/lua/502_plugin/Release/CL.read.1.tlog differ diff --git a/lua/502_plugin/Release/CL.write.1.tlog b/lua/502_plugin/Release/CL.write.1.tlog new file mode 100644 index 0000000..f144696 Binary files /dev/null and b/lua/502_plugin/Release/CL.write.1.tlog differ diff --git a/lua/502_plugin/Release/cl.command.1.tlog b/lua/502_plugin/Release/cl.command.1.tlog new file mode 100644 index 0000000..3296061 Binary files /dev/null and b/lua/502_plugin/Release/cl.command.1.tlog differ diff --git a/lua/502_plugin/Release/link.command.1.tlog b/lua/502_plugin/Release/link.command.1.tlog new file mode 100644 index 0000000..b524e8f Binary files /dev/null and b/lua/502_plugin/Release/link.command.1.tlog differ diff --git a/lua/502_plugin/Release/link.read.1.tlog b/lua/502_plugin/Release/link.read.1.tlog new file mode 100644 index 0000000..8cd568b Binary files /dev/null and b/lua/502_plugin/Release/link.read.1.tlog differ diff --git a/lua/502_plugin/Release/link.write.1.tlog b/lua/502_plugin/Release/link.write.1.tlog new file mode 100644 index 0000000..2aacdec Binary files /dev/null and b/lua/502_plugin/Release/link.write.1.tlog differ diff --git a/lua/502_plugin/Release/main.obj b/lua/502_plugin/Release/main.obj new file mode 100644 index 0000000..ef85598 Binary files /dev/null and b/lua/502_plugin/Release/main.obj differ diff --git a/lua/502_plugin/Release/mt.command.1.tlog b/lua/502_plugin/Release/mt.command.1.tlog new file mode 100644 index 0000000..3ca1794 Binary files /dev/null and b/lua/502_plugin/Release/mt.command.1.tlog differ diff --git a/lua/502_plugin/Release/mt.read.1.tlog b/lua/502_plugin/Release/mt.read.1.tlog new file mode 100644 index 0000000..6653c3a Binary files /dev/null and b/lua/502_plugin/Release/mt.read.1.tlog differ diff --git a/lua/502_plugin/Release/mt.write.1.tlog b/lua/502_plugin/Release/mt.write.1.tlog new file mode 100644 index 0000000..88dcb1e Binary files /dev/null and b/lua/502_plugin/Release/mt.write.1.tlog differ diff --git a/lua/502_plugin/Release/plugin.obj b/lua/502_plugin/Release/plugin.obj new file mode 100644 index 0000000..3f7f903 Binary files /dev/null and b/lua/502_plugin/Release/plugin.obj differ diff --git a/lua/502_plugin/Release/vc100.pdb b/lua/502_plugin/Release/vc100.pdb new file mode 100644 index 0000000..de0a2e1 Binary files /dev/null and b/lua/502_plugin/Release/vc100.pdb differ diff --git a/lua/502_plugin/main.cpp b/lua/502_plugin/main.cpp new file mode 100644 index 0000000..1052377 --- /dev/null +++ b/lua/502_plugin/main.cpp @@ -0,0 +1,38 @@ +#include "plugin.h" + +DECLARE_PLUGIN(CTestPlugin) + virtual bool GlobalInit(ILua502*); + virtual bool LuaInit(lua_State*); + + virtual void LevelInit(const char*); + virtual void ClientPutInServer(edict_t*,const char*); +END_PLUGIN(CTestPlugin,"testplugin"); + +bool CTestPlugin::GlobalInit(ILua502* pLua502) +{ + BaseClass::GlobalInit(pLua502); + Msg("CTestPlugin::GlobalInit!\n"); + return true; +} + +bool CTestPlugin::LuaInit(lua_State* L) +{ + BaseClass::LuaInit(L); + + lua_pushnumber(L,1234); + lua_setglobal(L,"magic"); + + Msg("CTestPlugin::LuaInit!\n"); + return true; +} + +void CTestPlugin::LevelInit(const char* pLevel) +{ + Msg("CTestPlugin::LevelInit %s\n",pLevel); +} + +void CTestPlugin::ClientPutInServer(edict_t* pEdict, + const char* pName) +{ + Msg("Player %s (%) put in server!\n",pEdict,pName); +} \ No newline at end of file diff --git a/lua/502_ppcore/502_ppcore.vcxproj b/lua/502_ppcore/502_ppcore.vcxproj new file mode 100644 index 0000000..50bd597 --- /dev/null +++ b/lua/502_ppcore/502_ppcore.vcxproj @@ -0,0 +1,67 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {A7610399-FAFB-4296-9352-58698BF87ED3} + My502_ppcore + + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + true + true + + + true + true + true + + + + + + + + \ No newline at end of file diff --git a/lua/502_ppcore/502_ppcore.vcxproj.filters b/lua/502_ppcore/502_ppcore.vcxproj.filters new file mode 100644 index 0000000..a967230 --- /dev/null +++ b/lua/502_ppcore/502_ppcore.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + \ No newline at end of file diff --git a/lua/502_ppcore/502_ppcore.vcxproj.user b/lua/502_ppcore/502_ppcore.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/lua/502_ppcore/502_ppcore.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lua/502_test/502_test.vcxproj b/lua/502_test/502_test.vcxproj new file mode 100644 index 0000000..40f6f70 --- /dev/null +++ b/lua/502_test/502_test.vcxproj @@ -0,0 +1,73 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {4F4C4E60-2C90-44D8-AA4A-B01874B76A5B} + My502_test + + + + Application + true + MultiByte + + + DynamicLibrary + false + true + MultiByte + + + + + + + + + + + + + ..\..\..\GMod9_Server\gmod9\lua\bin + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + true + true + D:\source2006\public;D:\lua502\lua\lua502_sdk;%(AdditionalIncludeDirectories) + + + true + true + true + ..\Release;%(AdditionalLibraryDirectories) + lua502_sdk.lib;%(AdditionalDependencies) + + + + + + + + + \ No newline at end of file diff --git a/lua/502_test/502_test.vcxproj.filters b/lua/502_test/502_test.vcxproj.filters new file mode 100644 index 0000000..1aa6936 --- /dev/null +++ b/lua/502_test/502_test.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Файлы иÑходного кода + + + \ No newline at end of file diff --git a/lua/502_test/502_test.vcxproj.user b/lua/502_test/502_test.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/lua/502_test/502_test.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lua/502_test/Release/502_test.Build.CppClean.log b/lua/502_test/Release/502_test.Build.CppClean.log new file mode 100644 index 0000000..3d67020 --- /dev/null +++ b/lua/502_test/Release/502_test.Build.CppClean.log @@ -0,0 +1,9 @@ +D:\lua502\lua\502_test\Release\502_test.write.1.tlog +D:\lua502\lua\502_test\Release\cl.command.1.tlog +D:\lua502\lua\502_test\Release\CL.read.1.tlog +D:\lua502\lua\502_test\Release\CL.write.1.tlog +D:\lua502\lua\502_test\Release\link.command.1.tlog +D:\lua502\lua\502_test\Release\link.read.1.tlog +D:\lua502\lua\502_test\Release\link.write.1.tlog +D:\LUA502\LUA\502_TEST\RELEASE\MAIN.OBJ +D:\LUA502\LUA\502_TEST\RELEASE\VC100.PDB diff --git a/lua/502_test/Release/502_test.dll.intermediate.manifest b/lua/502_test/Release/502_test.dll.intermediate.manifest new file mode 100644 index 0000000..ecea6f7 --- /dev/null +++ b/lua/502_test/Release/502_test.dll.intermediate.manifest @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/lua/502_test/Release/502_test.lastbuildstate b/lua/502_test/Release/502_test.lastbuildstate new file mode 100644 index 0000000..c2d4a05 --- /dev/null +++ b/lua/502_test/Release/502_test.lastbuildstate @@ -0,0 +1,2 @@ +#v4.0:v100:false +Release|Win32|D:\lua502\lua\| diff --git a/lua/502_test/Release/502_test.log b/lua/502_test/Release/502_test.log new file mode 100644 index 0000000..f7f619f --- /dev/null +++ b/lua/502_test/Release/502_test.log @@ -0,0 +1,24 @@ +Build started 05.10.2017 1:14:38. + 1>Project "D:\lua502\lua\502_test\502_test.vcxproj" on node 2 (build target(s)). + 1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppBuild.targets(299,5): warning MSB8004: каталог Output заканчиваетÑÑ Ð½Ðµ коÑой чертой. Этот ÑкземплÑÑ€ поÑÑ‚Ñ€Ð¾ÐµÐ½Ð¸Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ‚ коÑую черту, поÑкольку она необходима Ð´Ð»Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ð¾Ð³Ð¾ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð° Output. + 1>InitializeBuildStatus: + Touching "Release\502_test.unsuccessfulbuild". + ClCompile: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\CL.exe /c /ID:\source2006\public /ID:\lua502\lua\lua502_sdk /Zi /nologo /W3 /WX- /O2 /Oi /Oy- /GL /D _WINDLL /D _MBCS /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Release\\" /Fd"Release\vc100.pdb" /Gd /TP /analyze- /errorReport:prompt main.cpp + main.cpp + Link: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:"..\..\..\GMod9_Server\gmod9\lua\bin\502_test.dll" /NOLOGO /LIBPATH:..\Release lua502_sdk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /MANIFEST /ManifestFile:"Release\502_test.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"D:\GMod9_Server\gmod9\lua\bin\502_test.pdb" /OPT:REF /OPT:ICF /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"..\..\..\GMod9_Server\gmod9\lua\bin\502_test.lib" /MACHINE:X86 /DLL Release\main.obj + СоздаетÑÑ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ° ..\..\..\GMod9_Server\gmod9\lua\bin\502_test.lib и объект ..\..\..\GMod9_Server\gmod9\lua\bin\502_test.exp + Создание кода + Создание кода завершено + 502_test.vcxproj -> D:\lua502\lua\502_test\..\..\..\GMod9_Server\gmod9\lua\bin\502_test.dll + Manifest: + C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe /nologo /verbose /outputresource:"..\..\..\GMod9_Server\gmod9\lua\bin\502_test.dll;#2" /manifest Release\502_test.dll.intermediate.manifest + FinalizeBuildStatus: + Deleting file "Release\502_test.unsuccessfulbuild". + Touching "Release\502_test.lastbuildstate". + 1>Done Building Project "D:\lua502\lua\502_test\502_test.vcxproj" (build target(s)). + +ПоÑтроение уÑпешно завершено. + +Time Elapsed 00:00:02.32 diff --git a/lua/502_test/Release/502_test.write.1.tlog b/lua/502_test/Release/502_test.write.1.tlog new file mode 100644 index 0000000..9f43234 --- /dev/null +++ b/lua/502_test/Release/502_test.write.1.tlog @@ -0,0 +1,5 @@ +^D:\lua502\lua\502_test\502_test.vcxproj +D:\GMod9_Server\gmod9\lua\bin\502_test.lib +D:\GMod9_Server\gmod9\lua\bin\502_test.lib +D:\GMod9_Server\gmod9\lua\bin\502_test.exp +D:\GMod9_Server\gmod9\lua\bin\502_test.exp diff --git a/lua/502_test/Release/CL.read.1.tlog b/lua/502_test/Release/CL.read.1.tlog new file mode 100644 index 0000000..8fb4ba2 Binary files /dev/null and b/lua/502_test/Release/CL.read.1.tlog differ diff --git a/lua/502_test/Release/CL.write.1.tlog b/lua/502_test/Release/CL.write.1.tlog new file mode 100644 index 0000000..fb26445 Binary files /dev/null and b/lua/502_test/Release/CL.write.1.tlog differ diff --git a/lua/502_test/Release/cl.command.1.tlog b/lua/502_test/Release/cl.command.1.tlog new file mode 100644 index 0000000..f26b729 Binary files /dev/null and b/lua/502_test/Release/cl.command.1.tlog differ diff --git a/lua/502_test/Release/link.command.1.tlog b/lua/502_test/Release/link.command.1.tlog new file mode 100644 index 0000000..4ed8e68 Binary files /dev/null and b/lua/502_test/Release/link.command.1.tlog differ diff --git a/lua/502_test/Release/link.read.1.tlog b/lua/502_test/Release/link.read.1.tlog new file mode 100644 index 0000000..9ab7029 Binary files /dev/null and b/lua/502_test/Release/link.read.1.tlog differ diff --git a/lua/502_test/Release/link.write.1.tlog b/lua/502_test/Release/link.write.1.tlog new file mode 100644 index 0000000..23452bb Binary files /dev/null and b/lua/502_test/Release/link.write.1.tlog differ diff --git a/lua/502_test/Release/main.obj b/lua/502_test/Release/main.obj new file mode 100644 index 0000000..64006ec Binary files /dev/null and b/lua/502_test/Release/main.obj differ diff --git a/lua/502_test/Release/mt.command.1.tlog b/lua/502_test/Release/mt.command.1.tlog new file mode 100644 index 0000000..f72794c Binary files /dev/null and b/lua/502_test/Release/mt.command.1.tlog differ diff --git a/lua/502_test/Release/mt.read.1.tlog b/lua/502_test/Release/mt.read.1.tlog new file mode 100644 index 0000000..be648bf Binary files /dev/null and b/lua/502_test/Release/mt.read.1.tlog differ diff --git a/lua/502_test/Release/mt.write.1.tlog b/lua/502_test/Release/mt.write.1.tlog new file mode 100644 index 0000000..a5aadfc Binary files /dev/null and b/lua/502_test/Release/mt.write.1.tlog differ diff --git a/lua/502_test/Release/vc100.pdb b/lua/502_test/Release/vc100.pdb new file mode 100644 index 0000000..bed3433 Binary files /dev/null and b/lua/502_test/Release/vc100.pdb differ diff --git a/lua/502_test/main.cpp b/lua/502_test/main.cpp new file mode 100644 index 0000000..6f6367d --- /dev/null +++ b/lua/502_test/main.cpp @@ -0,0 +1,130 @@ +#include +#include +#include "lauxlib.h" +#include "lua502.h" +#include "appframework/iappsystemgroup.h" +#include "tier1/strtools.h" +#include "tier1/interface.h" +#include "tier1/utlvector.h" +#include "tier1/utldict.h" + +int Init(lua_State*); +int Exit(lua_State*); +DECLARE_GMOD9_PLUGIN2(Init,Exit,"testmodule"); + +/*class CAppSystemGroup +{ +public: + virtual int LoadModule( const char *pDLLName ) = 0; + virtual IAppSystem *AddSystem( int module, const char *pInterfaceName ) = 0; + virtual void *FindSystem( const char *pSystemName ) = 0; + virtual CreateInterfaceFn GetFactory() = 0; + + CUtlVector m_Modules; + CUtlVector m_Systems; + CUtlDict m_SystemDict; +};*/ + +int lua_MessageBox(lua_State* L) +{ + luaL_checktype(L,1,LUA_TSTRING); + luaL_checktype(L,2,LUA_TSTRING); + luaL_checktype(L,3,LUA_TNUMBER); + + lua_pushnumber(L,MessageBox(NULL,lua_tostring(L,1), + lua_tostring(L,2),(UINT)lua_tonumber(L,3))); + return 1; +} + +int lua_strcmp(lua_State* L) +{ + luaL_checktype(L,1,LUA_TSTRING); + luaL_checktype(L,2,LUA_TSTRING); + + lua_pushnumber(L,V_strcmp(lua_tostring(L,1), + lua_tostring(L,2))); + return 1; +} + +int lua_EngineError(lua_State* L) +{ + luaL_checktype(L,1,LUA_TSTRING); + Error("%s",lua_tostring(L,1)); + return 0; +} + +typedef void* (*GetInterfaceFn_t)(); +typedef struct interfacereg_s { + GetInterfaceFn_t m_fnGetInterface; + const char* m_pName; + struct interfacereg_s* m_pNext; +} interfacereg_t; + +void DumpCreateInterface(CreateInterfaceFn fnFactory) +{ + interfacereg_t* pReg = **(interfacereg_t***)((char*)fnFactory+0x05); + while(pReg) + { + Msg("\t%s %p\n",pReg->m_pName,pReg->m_fnGetInterface()); + pReg = pReg->m_pNext; + } +} + +typedef CreateInterfaceFn (*GetFactoryFn)(); + +void DumpAppFactoryGroup(CAppSystemGroup* pAppSystemGroup,int tier = 0) +{ + unsigned short i = pAppSystemGroup->m_SystemDict.First(); + Msg("== TIER %d ==\npAppSystemGroup %p\n",tier,pAppSystemGroup); + CUtlVector LegalSystems; + while(pAppSystemGroup->m_SystemDict.IsValidIndex(i)) + { + const char* pName = pAppSystemGroup->m_SystemDict.GetElementName(i); + int iAppID; + LegalSystems.AddToTail((iAppID = pAppSystemGroup->m_SystemDict.Element(i))); + + IAppSystem* pAppSystem = pAppSystemGroup->m_Systems.Element(iAppID); + Msg("\t%s %p\n",(pName?pName:"(null)"),pAppSystem); + i = pAppSystemGroup->m_SystemDict.Next(i); + } + + if(pAppSystemGroup->m_pParentAppSystem) + { + if(pAppSystemGroup->m_nErrorStage != CAppSystemGroup::NONE) return; + DumpAppFactoryGroup(pAppSystemGroup->m_pParentAppSystem,tier+1); + } +} + +int Init(lua_State* L) +{ + lua_pushcfunction(L,lua_MessageBox); + lua_setglobal(L,"MessageBox"); + + lua_pushcfunction(L,lua_strcmp); + lua_setglobal(L,"strcmp"); + + lua_pushcfunction(L,lua_EngineError); + lua_setglobal(L,"EngineError"); + + g_pLua502->Print("Hello World from ILua502!\n"); + g_pLua502->Print("AppFactory %p GameFactory %p\n", + g_PluginInfo.m_fnAppFactory,g_PluginInfo.m_fnGameFactory); + + CAppSystemGroup* pAppSystemGroup = **(CAppSystemGroup***)( + (char*)g_PluginInfo.m_fnAppFactory+0x06); + DumpAppFactoryGroup(pAppSystemGroup); + return 0; +} + +int Exit(lua_State* L) +{ + lua_pushnil(L); + lua_setglobal(L,"MessageBox"); + + lua_pushnil(L); + lua_setglobal(L,"strcmp"); + + lua_pushnil(L); + lua_setglobal(L,"EngineError"); + return 0; +} \ No newline at end of file diff --git a/lua/Release/502_test.pdb b/lua/Release/502_test.pdb new file mode 100644 index 0000000..7a75d90 Binary files /dev/null and b/lua/Release/502_test.pdb differ diff --git a/lua/Release/a2s_rules.exe b/lua/Release/a2s_rules.exe new file mode 100644 index 0000000..0aa5b86 Binary files /dev/null and b/lua/Release/a2s_rules.exe differ diff --git a/lua/Release/a2s_rules.pdb b/lua/Release/a2s_rules.pdb new file mode 100644 index 0000000..9257459 Binary files /dev/null and b/lua/Release/a2s_rules.pdb differ diff --git a/lua/Release/gm9_cvar.dll b/lua/Release/gm9_cvar.dll new file mode 100644 index 0000000..bc89e80 Binary files /dev/null and b/lua/Release/gm9_cvar.dll differ diff --git a/lua/Release/gm9_cvar.exp b/lua/Release/gm9_cvar.exp new file mode 100644 index 0000000..d01a3d1 Binary files /dev/null and b/lua/Release/gm9_cvar.exp differ diff --git a/lua/Release/gm9_cvar.lib b/lua/Release/gm9_cvar.lib new file mode 100644 index 0000000..af1d68b Binary files /dev/null and b/lua/Release/gm9_cvar.lib differ diff --git a/lua/Release/gm9_cvar.pdb b/lua/Release/gm9_cvar.pdb new file mode 100644 index 0000000..40625fc Binary files /dev/null and b/lua/Release/gm9_cvar.pdb differ diff --git a/lua/Release/gm9_fsdump.dll b/lua/Release/gm9_fsdump.dll new file mode 100644 index 0000000..74cdda1 Binary files /dev/null and b/lua/Release/gm9_fsdump.dll differ diff --git a/lua/Release/gm9_fsdump.pdb b/lua/Release/gm9_fsdump.pdb new file mode 100644 index 0000000..e3d9f2b Binary files /dev/null and b/lua/Release/gm9_fsdump.pdb differ diff --git a/lua/Release/gm9_interface.dll b/lua/Release/gm9_interface.dll new file mode 100644 index 0000000..7ad486b Binary files /dev/null and b/lua/Release/gm9_interface.dll differ diff --git a/lua/Release/gm9_interface.pdb b/lua/Release/gm9_interface.pdb new file mode 100644 index 0000000..7489c7f Binary files /dev/null and b/lua/Release/gm9_interface.pdb differ diff --git a/lua/Release/gm9_internal.dll b/lua/Release/gm9_internal.dll new file mode 100644 index 0000000..08b06a8 Binary files /dev/null and b/lua/Release/gm9_internal.dll differ diff --git a/lua/Release/gm9_internal.pdb b/lua/Release/gm9_internal.pdb new file mode 100644 index 0000000..5f65aa2 Binary files /dev/null and b/lua/Release/gm9_internal.pdb differ diff --git a/lua/Release/gm9_src7.dll b/lua/Release/gm9_src7.dll new file mode 100644 index 0000000..c3822c4 Binary files /dev/null and b/lua/Release/gm9_src7.dll differ diff --git a/lua/Release/gm9_src7.exp b/lua/Release/gm9_src7.exp new file mode 100644 index 0000000..d8bf95f Binary files /dev/null and b/lua/Release/gm9_src7.exp differ diff --git a/lua/Release/gm9_src7.id0 b/lua/Release/gm9_src7.id0 new file mode 100644 index 0000000..1d30d96 Binary files /dev/null and b/lua/Release/gm9_src7.id0 differ diff --git a/lua/Release/gm9_src7.id1 b/lua/Release/gm9_src7.id1 new file mode 100644 index 0000000..1dd8e70 Binary files /dev/null and b/lua/Release/gm9_src7.id1 differ diff --git a/lua/Release/gm9_src7.id2 b/lua/Release/gm9_src7.id2 new file mode 100644 index 0000000..1379911 Binary files /dev/null and b/lua/Release/gm9_src7.id2 differ diff --git a/lua/Release/gm9_src7.lib b/lua/Release/gm9_src7.lib new file mode 100644 index 0000000..55c6ce2 Binary files /dev/null and b/lua/Release/gm9_src7.lib differ diff --git a/lua/Release/gm9_src7.nam b/lua/Release/gm9_src7.nam new file mode 100644 index 0000000..7edb747 Binary files /dev/null and b/lua/Release/gm9_src7.nam differ diff --git a/lua/Release/gm9_src7.pdb b/lua/Release/gm9_src7.pdb new file mode 100644 index 0000000..5228e19 Binary files /dev/null and b/lua/Release/gm9_src7.pdb differ diff --git a/lua/Release/gm9_src7.til b/lua/Release/gm9_src7.til new file mode 100644 index 0000000..d358363 Binary files /dev/null and b/lua/Release/gm9_src7.til differ diff --git a/lua/Release/gm9_workerthread.dll b/lua/Release/gm9_workerthread.dll new file mode 100644 index 0000000..62fa05f Binary files /dev/null and b/lua/Release/gm9_workerthread.dll differ diff --git a/lua/Release/gm9_workerthread.exp b/lua/Release/gm9_workerthread.exp new file mode 100644 index 0000000..7e4f78c Binary files /dev/null and b/lua/Release/gm9_workerthread.exp differ diff --git a/lua/Release/gm9_workerthread.lib b/lua/Release/gm9_workerthread.lib new file mode 100644 index 0000000..3ef3101 Binary files /dev/null and b/lua/Release/gm9_workerthread.lib differ diff --git a/lua/Release/gm9_workerthread.pdb b/lua/Release/gm9_workerthread.pdb new file mode 100644 index 0000000..094ff75 Binary files /dev/null and b/lua/Release/gm9_workerthread.pdb differ diff --git a/lua/Release/gm9x_testapp.dll b/lua/Release/gm9x_testapp.dll new file mode 100644 index 0000000..0f8cb26 Binary files /dev/null and b/lua/Release/gm9x_testapp.dll differ diff --git a/lua/Release/gm9x_testapp.exp b/lua/Release/gm9x_testapp.exp new file mode 100644 index 0000000..dff0027 Binary files /dev/null and b/lua/Release/gm9x_testapp.exp differ diff --git a/lua/Release/gm9x_testapp.lib b/lua/Release/gm9x_testapp.lib new file mode 100644 index 0000000..f3aa73f Binary files /dev/null and b/lua/Release/gm9x_testapp.lib differ diff --git a/lua/Release/gm9x_testapp.pdb b/lua/Release/gm9x_testapp.pdb new file mode 100644 index 0000000..fb4f171 Binary files /dev/null and b/lua/Release/gm9x_testapp.pdb differ diff --git a/lua/Release/lcore.lib b/lua/Release/lcore.lib new file mode 100644 index 0000000..2991b94 Binary files /dev/null and b/lua/Release/lcore.lib differ diff --git a/lua/Release/ltest.exe b/lua/Release/ltest.exe new file mode 100644 index 0000000..93466c5 Binary files /dev/null and b/lua/Release/ltest.exe differ diff --git a/lua/Release/ltest.pdb b/lua/Release/ltest.pdb new file mode 100644 index 0000000..ce1350e Binary files /dev/null and b/lua/Release/ltest.pdb differ diff --git a/lua/Release/lua502.lib b/lua/Release/lua502.lib new file mode 100644 index 0000000..3060cc1 Binary files /dev/null and b/lua/Release/lua502.lib differ diff --git a/lua/Release/lua502.pdb b/lua/Release/lua502.pdb new file mode 100644 index 0000000..3eb28f6 Binary files /dev/null and b/lua/Release/lua502.pdb differ diff --git a/lua/Release/lua502_sdk.lib b/lua/Release/lua502_sdk.lib new file mode 100644 index 0000000..270dd47 Binary files /dev/null and b/lua/Release/lua502_sdk.lib differ diff --git a/lua/Release/lzss.dll b/lua/Release/lzss.dll new file mode 100644 index 0000000..55e430d Binary files /dev/null and b/lua/Release/lzss.dll differ diff --git a/lua/Release/lzss.exe b/lua/Release/lzss.exe new file mode 100644 index 0000000..7590828 Binary files /dev/null and b/lua/Release/lzss.exe differ diff --git a/lua/Release/lzss.pdb b/lua/Release/lzss.pdb new file mode 100644 index 0000000..0e2c549 Binary files /dev/null and b/lua/Release/lzss.pdb differ diff --git a/lua/Release/masterfix.dll b/lua/Release/masterfix.dll new file mode 100644 index 0000000..faebd9f Binary files /dev/null and b/lua/Release/masterfix.dll differ diff --git a/lua/Release/masterfix.exp b/lua/Release/masterfix.exp new file mode 100644 index 0000000..01b55c9 Binary files /dev/null and b/lua/Release/masterfix.exp differ diff --git a/lua/Release/masterfix.lib b/lua/Release/masterfix.lib new file mode 100644 index 0000000..85fb433 Binary files /dev/null and b/lua/Release/masterfix.lib differ diff --git a/lua/Release/masterfix.pdb b/lua/Release/masterfix.pdb new file mode 100644 index 0000000..faacb03 Binary files /dev/null and b/lua/Release/masterfix.pdb differ diff --git a/lua/Release/rules.bin b/lua/Release/rules.bin new file mode 100644 index 0000000..53733bc Binary files /dev/null and b/lua/Release/rules.bin differ diff --git a/lua/Release/rw1132.dll b/lua/Release/rw1132.dll new file mode 100644 index 0000000..c78729e Binary files /dev/null and b/lua/Release/rw1132.dll differ diff --git a/lua/Release/rw1132.exp b/lua/Release/rw1132.exp new file mode 100644 index 0000000..3c97404 Binary files /dev/null and b/lua/Release/rw1132.exp differ diff --git a/lua/Release/rw1132.lib b/lua/Release/rw1132.lib new file mode 100644 index 0000000..02c7ae4 Binary files /dev/null and b/lua/Release/rw1132.lib differ diff --git a/lua/Release/rw1132.pdb b/lua/Release/rw1132.pdb new file mode 100644 index 0000000..ed5a603 Binary files /dev/null and b/lua/Release/rw1132.pdb differ diff --git a/lua/Release/sdk_net.dll b/lua/Release/sdk_net.dll new file mode 100644 index 0000000..4eebd32 Binary files /dev/null and b/lua/Release/sdk_net.dll differ diff --git a/lua/Release/sdk_net.exp b/lua/Release/sdk_net.exp new file mode 100644 index 0000000..c0b905a Binary files /dev/null and b/lua/Release/sdk_net.exp differ diff --git a/lua/Release/sdk_net.lib b/lua/Release/sdk_net.lib new file mode 100644 index 0000000..0e4458a Binary files /dev/null and b/lua/Release/sdk_net.lib differ diff --git a/lua/Release/sdk_net.pdb b/lua/Release/sdk_net.pdb new file mode 100644 index 0000000..482383b Binary files /dev/null and b/lua/Release/sdk_net.pdb differ diff --git a/lua/Release/tier0.dll b/lua/Release/tier0.dll new file mode 100644 index 0000000..9ee328e Binary files /dev/null and b/lua/Release/tier0.dll differ diff --git a/lua/a2s_rules/Release/CL.read.1.tlog b/lua/a2s_rules/Release/CL.read.1.tlog new file mode 100644 index 0000000..43f76eb Binary files /dev/null and b/lua/a2s_rules/Release/CL.read.1.tlog differ diff --git a/lua/a2s_rules/Release/CL.write.1.tlog b/lua/a2s_rules/Release/CL.write.1.tlog new file mode 100644 index 0000000..710263b Binary files /dev/null and b/lua/a2s_rules/Release/CL.write.1.tlog differ diff --git a/lua/a2s_rules/Release/a2s_rules.exe.intermediate.manifest b/lua/a2s_rules/Release/a2s_rules.exe.intermediate.manifest new file mode 100644 index 0000000..ecea6f7 --- /dev/null +++ b/lua/a2s_rules/Release/a2s_rules.exe.intermediate.manifest @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/lua/a2s_rules/Release/a2s_rules.lastbuildstate b/lua/a2s_rules/Release/a2s_rules.lastbuildstate new file mode 100644 index 0000000..c2d4a05 --- /dev/null +++ b/lua/a2s_rules/Release/a2s_rules.lastbuildstate @@ -0,0 +1,2 @@ +#v4.0:v100:false +Release|Win32|D:\lua502\lua\| diff --git a/lua/a2s_rules/Release/a2s_rules.log b/lua/a2s_rules/Release/a2s_rules.log new file mode 100644 index 0000000..638e517 --- /dev/null +++ b/lua/a2s_rules/Release/a2s_rules.log @@ -0,0 +1,25 @@ +Build started 12.04.2018 4:18:30. + 1>Project "D:\lua502\lua\a2s_rules\a2s_rules.vcxproj" on node 2 (build target(s)). + 1>InitializeBuildStatus: + Creating "Release\a2s_rules.unsuccessfulbuild" because "AlwaysCreate" was specified. + ClCompile: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\CL.exe /c /ID:\bzip2 /Zi /nologo /W3 /WX- /O2 /Oi /Oy- /GL /D _MBCS /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Release\\" /Fd"Release\vc100.pdb" /Gd /TP /analyze- /errorReport:prompt main.cpp + main.cpp + 1>main.cpp(113): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(234): Ñм. объÑвление "fopen" + 1>main.cpp(42): warning C4101: rules: неиÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð½Ð°Ñ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ð°Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ + Link: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:"D:\lua502\lua\Release\a2s_rules.exe" /NOLOGO /LIBPATH:D:\bzip2\Release WS2_32.lib libbz2.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NODEFAULTLIB:LIBCMT.lib /MANIFEST /ManifestFile:"Release\a2s_rules.exe.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"D:\lua502\lua\Release\a2s_rules.pdb" /OPT:REF /OPT:ICF /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"D:\lua502\lua\Release\a2s_rules.lib" /MACHINE:X86 Release\main.obj + Создание кода + Создание кода завершено + a2s_rules.vcxproj -> D:\lua502\lua\Release\a2s_rules.exe + Manifest: + C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe /nologo /verbose /outputresource:"D:\lua502\lua\Release\a2s_rules.exe;#1" /manifest Release\a2s_rules.exe.intermediate.manifest + FinalizeBuildStatus: + Deleting file "Release\a2s_rules.unsuccessfulbuild". + Touching "Release\a2s_rules.lastbuildstate". + 1>Done Building Project "D:\lua502\lua\a2s_rules\a2s_rules.vcxproj" (build target(s)). + +ПоÑтроение уÑпешно завершено. + +Time Elapsed 00:00:00.74 diff --git a/lua/a2s_rules/Release/a2s_rules.vcxprojResolveAssemblyReference.cache b/lua/a2s_rules/Release/a2s_rules.vcxprojResolveAssemblyReference.cache new file mode 100644 index 0000000..3f01681 Binary files /dev/null and b/lua/a2s_rules/Release/a2s_rules.vcxprojResolveAssemblyReference.cache differ diff --git a/lua/a2s_rules/Release/a2s_rules.write.1.tlog b/lua/a2s_rules/Release/a2s_rules.write.1.tlog new file mode 100644 index 0000000..e69de29 diff --git a/lua/a2s_rules/Release/cl.command.1.tlog b/lua/a2s_rules/Release/cl.command.1.tlog new file mode 100644 index 0000000..eec5fd0 Binary files /dev/null and b/lua/a2s_rules/Release/cl.command.1.tlog differ diff --git a/lua/a2s_rules/Release/link.command.1.tlog b/lua/a2s_rules/Release/link.command.1.tlog new file mode 100644 index 0000000..86a2ba1 Binary files /dev/null and b/lua/a2s_rules/Release/link.command.1.tlog differ diff --git a/lua/a2s_rules/Release/link.read.1.tlog b/lua/a2s_rules/Release/link.read.1.tlog new file mode 100644 index 0000000..cf94b7d Binary files /dev/null and b/lua/a2s_rules/Release/link.read.1.tlog differ diff --git a/lua/a2s_rules/Release/link.write.1.tlog b/lua/a2s_rules/Release/link.write.1.tlog new file mode 100644 index 0000000..a01dad4 Binary files /dev/null and b/lua/a2s_rules/Release/link.write.1.tlog differ diff --git a/lua/a2s_rules/Release/main.obj b/lua/a2s_rules/Release/main.obj new file mode 100644 index 0000000..e6f374f Binary files /dev/null and b/lua/a2s_rules/Release/main.obj differ diff --git a/lua/a2s_rules/Release/mt.command.1.tlog b/lua/a2s_rules/Release/mt.command.1.tlog new file mode 100644 index 0000000..511aaa7 Binary files /dev/null and b/lua/a2s_rules/Release/mt.command.1.tlog differ diff --git a/lua/a2s_rules/Release/mt.read.1.tlog b/lua/a2s_rules/Release/mt.read.1.tlog new file mode 100644 index 0000000..a42788f Binary files /dev/null and b/lua/a2s_rules/Release/mt.read.1.tlog differ diff --git a/lua/a2s_rules/Release/mt.write.1.tlog b/lua/a2s_rules/Release/mt.write.1.tlog new file mode 100644 index 0000000..ab2d9f1 Binary files /dev/null and b/lua/a2s_rules/Release/mt.write.1.tlog differ diff --git a/lua/a2s_rules/Release/vc100.pdb b/lua/a2s_rules/Release/vc100.pdb new file mode 100644 index 0000000..89113b1 Binary files /dev/null and b/lua/a2s_rules/Release/vc100.pdb differ diff --git a/lua/a2s_rules/a2s_rules.vcxproj b/lua/a2s_rules/a2s_rules.vcxproj new file mode 100644 index 0000000..acf6b00 --- /dev/null +++ b/lua/a2s_rules/a2s_rules.vcxproj @@ -0,0 +1,72 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {A80D0688-8E8C-46CE-ABB9-110F7076CC13} + a2s_rules + + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + true + true + D:\bzip2;%(AdditionalIncludeDirectories) + + + true + true + true + WS2_32.lib;libbz2.lib;%(AdditionalDependencies) + D:\bzip2\Release;%(AdditionalLibraryDirectories) + LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) + + + + + + + + + \ No newline at end of file diff --git a/lua/a2s_rules/a2s_rules.vcxproj.filters b/lua/a2s_rules/a2s_rules.vcxproj.filters new file mode 100644 index 0000000..1aa6936 --- /dev/null +++ b/lua/a2s_rules/a2s_rules.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Файлы иÑходного кода + + + \ No newline at end of file diff --git a/lua/a2s_rules/a2s_rules.vcxproj.user b/lua/a2s_rules/a2s_rules.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/lua/a2s_rules/a2s_rules.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lua/a2s_rules/main.cpp b/lua/a2s_rules/main.cpp new file mode 100644 index 0000000..910d724 --- /dev/null +++ b/lua/a2s_rules/main.cpp @@ -0,0 +1,116 @@ +#include +#include +#include +#include "bzlib.h" + +WSADATA g_WSA; + +#pragma pack(push,1) +typedef struct { + DWORD dwHdr; + BYTE bPck; + DWORD dwChallenge; +} a2schallenge_t; + +typedef struct { + DWORD dwHdr; + DWORD dwID; + BYTE bPcks; + BYTE bCurPck; + WORD wSplitSize; + + DWORD dwUSize; + DWORD dwCRC; +} multi_t; + +typedef struct { + DWORD dwHdr; + BYTE bPck; + WORD wRules; +} a2srules_t; +#pragma pack(pop) + +#define SADDR(adr) ((sockaddr*)&adr) +#define CSADDR(adr) ((const sockaddr*)&adr) + +int main(int argc,char** argv) +{ + SOCKET s; + struct sockaddr_in addr; + int socklen = sizeof(addr); + a2schallenge_t chl; + char* pRules = NULL; + char szBuf[1500]; + int iSize = 0,iRules = 0,iLen; + int iPcks = 0; + + WSAStartup(MAKEWORD(2,2),&g_WSA); + s = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr(argv[1]); + addr.sin_port = htons(atoi(argv[2])); + + chl.dwHdr = (DWORD)-1; + chl.bPck = 'V'; + chl.dwHdr = (DWORD)-1; + + sendto(s,(const char*)&chl,sizeof(chl),0,CSADDR(addr),socklen); + recvfrom(s,(char*)&chl,sizeof(chl),0,SADDR(addr),&socklen); + + pRules = (char*)calloc(1,1500); + printf("Challenge 0x%p\n",chl.dwChallenge); + socklen = sizeof(addr); + chl.bPck = 'V'; + sendto(s,(const char*)&chl,sizeof(chl),0,CSADDR(addr),socklen); + + multi_t m; + int iTotalSize = 0; + do { + if((iLen = recvfrom(s,szBuf,sizeof(szBuf),0,SADDR(addr),&socklen)) > 0) + { + int iPckSize = (iPcks?(sizeof(multi_t)-8):sizeof(multi_t)); + int iCurSize = iLen-iPckSize; + memcpy(&m,szBuf,iPckSize); + if(!iPcks) + { + iPcks = m.bPcks; + iTotalSize = m.dwUSize; + printf("%p\n",iTotalSize); + } + printf("Packet %d iLen %d\n",m.bCurPck,iLen); + + if(!pRules) pRules = (char*)malloc(iCurSize); + else pRules = (char*)realloc(pRules,iSize+iCurSize); + + memcpy((pRules+iSize),(char*)szBuf+iPckSize,iCurSize); + iSize += iCurSize; + } + } while(iLen > 0 && m.bCurPck < (iPcks-1)); + + /* Uses BZip2! */ + if(m.dwID & 0x80000000) + { + char* pOut = (char*)malloc(iTotalSize); + bz_stream strm; + + memset(&strm,'\0',sizeof(strm)); + strm.next_in = pRules; + strm.avail_in = iSize; + strm.next_out = pOut; + strm.avail_out = iTotalSize; + + BZ2_bzDecompressInit(&strm,0,0); + BZ2_bzDecompress(&strm); + BZ2_bzDecompressEnd(&strm); + puts("Decompressed!\n"); + + free(pRules); + iSize = iTotalSize; + pRules = pOut; + } + + FILE* fRules = fopen("rules.bin","wb"); + fwrite(pRules,iSize,1,fRules); + fclose(fRules); + return 0; +} \ No newline at end of file diff --git a/lua/gm9_cvar/Release/CL.read.1.tlog b/lua/gm9_cvar/Release/CL.read.1.tlog new file mode 100644 index 0000000..4291f59 Binary files /dev/null and b/lua/gm9_cvar/Release/CL.read.1.tlog differ diff --git a/lua/gm9_cvar/Release/CL.write.1.tlog b/lua/gm9_cvar/Release/CL.write.1.tlog new file mode 100644 index 0000000..9d3a5d2 Binary files /dev/null and b/lua/gm9_cvar/Release/CL.write.1.tlog differ diff --git a/lua/gm9_cvar/Release/cl.command.1.tlog b/lua/gm9_cvar/Release/cl.command.1.tlog new file mode 100644 index 0000000..d930e4c Binary files /dev/null and b/lua/gm9_cvar/Release/cl.command.1.tlog differ diff --git a/lua/gm9_cvar/Release/gm9_cvar.dll.intermediate.manifest b/lua/gm9_cvar/Release/gm9_cvar.dll.intermediate.manifest new file mode 100644 index 0000000..ecea6f7 --- /dev/null +++ b/lua/gm9_cvar/Release/gm9_cvar.dll.intermediate.manifest @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/lua/gm9_cvar/Release/gm9_cvar.lastbuildstate b/lua/gm9_cvar/Release/gm9_cvar.lastbuildstate new file mode 100644 index 0000000..c2d4a05 --- /dev/null +++ b/lua/gm9_cvar/Release/gm9_cvar.lastbuildstate @@ -0,0 +1,2 @@ +#v4.0:v100:false +Release|Win32|D:\lua502\lua\| diff --git a/lua/gm9_cvar/Release/gm9_cvar.log b/lua/gm9_cvar/Release/gm9_cvar.log new file mode 100644 index 0000000..bb2c58a --- /dev/null +++ b/lua/gm9_cvar/Release/gm9_cvar.log @@ -0,0 +1,24 @@ +Build started 06.06.2018 13:16:53. + 1>Project "D:\lua502\lua\gm9_cvar\gm9_cvar.vcxproj" on node 2 (build target(s)). + 1>InitializeBuildStatus: + Touching "Release\gm9_cvar.unsuccessfulbuild". + ClCompile: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\CL.exe /c /ID:\source2006\common /ID:\source2006\public\tier1 /ID:\source2006\public\tier0 /ID:\source2006\public /ID:\source2006\ /Zi /nologo /W3 /WX- /O2 /Oi /Oy- /GL /D _WINDLL /D _MBCS /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Release\\" /Fd"Release\vc100.pdb" /Gd /TP /analyze- /errorReport:prompt main.cpp + main.cpp + Link: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:"D:\lua502\lua\Release\gm9_cvar.dll" /NOLOGO /LIBPATH:D:\source2006\lib\public tier0.lib tier1.lib vstdlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NODEFAULTLIB:LIBCMT.lib /MANIFEST /ManifestFile:"Release\gm9_cvar.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"D:\lua502\lua\Release\gm9_cvar.pdb" /OPT:REF /OPT:ICF /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"D:\lua502\lua\Release\gm9_cvar.lib" /MACHINE:X86 /DLL Release\main.obj + Release\sigscan.obj + СоздаетÑÑ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ° D:\lua502\lua\Release\gm9_cvar.lib и объект D:\lua502\lua\Release\gm9_cvar.exp + Создание кода + Создание кода завершено + gm9_cvar.vcxproj -> D:\lua502\lua\Release\gm9_cvar.dll + Manifest: + C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe /nologo /verbose /outputresource:"D:\lua502\lua\Release\gm9_cvar.dll;#2" /manifest Release\gm9_cvar.dll.intermediate.manifest + FinalizeBuildStatus: + Deleting file "Release\gm9_cvar.unsuccessfulbuild". + Touching "Release\gm9_cvar.lastbuildstate". + 1>Done Building Project "D:\lua502\lua\gm9_cvar\gm9_cvar.vcxproj" (build target(s)). + +ПоÑтроение уÑпешно завершено. + +Time Elapsed 00:00:01.04 diff --git a/lua/gm9_cvar/Release/gm9_cvar.vcxprojResolveAssemblyReference.cache b/lua/gm9_cvar/Release/gm9_cvar.vcxprojResolveAssemblyReference.cache new file mode 100644 index 0000000..3f01681 Binary files /dev/null and b/lua/gm9_cvar/Release/gm9_cvar.vcxprojResolveAssemblyReference.cache differ diff --git a/lua/gm9_cvar/Release/gm9_cvar.write.1.tlog b/lua/gm9_cvar/Release/gm9_cvar.write.1.tlog new file mode 100644 index 0000000..06810ad --- /dev/null +++ b/lua/gm9_cvar/Release/gm9_cvar.write.1.tlog @@ -0,0 +1,65 @@ +^D:\lua502\lua\gm9_cvar\gm9_cvar.vcxproj +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.exp +D:\lua502\lua\Release\gm9_cvar.exp +^D:\lua502\lua\gm9_cvar\gm9_cvar.vcxproj +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.exp +D:\lua502\lua\Release\gm9_cvar.exp +^D:\lua502\lua\gm9_cvar\gm9_cvar.vcxproj +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.exp +D:\lua502\lua\Release\gm9_cvar.exp +^D:\lua502\lua\gm9_cvar\gm9_cvar.vcxproj +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.exp +D:\lua502\lua\Release\gm9_cvar.exp +^D:\lua502\lua\gm9_cvar\gm9_cvar.vcxproj +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.exp +D:\lua502\lua\Release\gm9_cvar.exp +^D:\lua502\lua\gm9_cvar\gm9_cvar.vcxproj +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.exp +D:\lua502\lua\Release\gm9_cvar.exp +^D:\lua502\lua\gm9_cvar\gm9_cvar.vcxproj +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.exp +D:\lua502\lua\Release\gm9_cvar.exp +^D:\lua502\lua\gm9_cvar\gm9_cvar.vcxproj +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.exp +D:\lua502\lua\Release\gm9_cvar.exp +^D:\lua502\lua\gm9_cvar\gm9_cvar.vcxproj +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.exp +D:\lua502\lua\Release\gm9_cvar.exp +^D:\lua502\lua\gm9_cvar\gm9_cvar.vcxproj +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.exp +D:\lua502\lua\Release\gm9_cvar.exp +^D:\lua502\lua\gm9_cvar\gm9_cvar.vcxproj +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.exp +D:\lua502\lua\Release\gm9_cvar.exp +^D:\lua502\lua\gm9_cvar\gm9_cvar.vcxproj +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.exp +D:\lua502\lua\Release\gm9_cvar.exp +^D:\lua502\lua\gm9_cvar\gm9_cvar.vcxproj +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.lib +D:\lua502\lua\Release\gm9_cvar.exp +D:\lua502\lua\Release\gm9_cvar.exp diff --git a/lua/gm9_cvar/Release/link.command.1.tlog b/lua/gm9_cvar/Release/link.command.1.tlog new file mode 100644 index 0000000..4a8dcc2 Binary files /dev/null and b/lua/gm9_cvar/Release/link.command.1.tlog differ diff --git a/lua/gm9_cvar/Release/link.read.1.tlog b/lua/gm9_cvar/Release/link.read.1.tlog new file mode 100644 index 0000000..ef65bc1 Binary files /dev/null and b/lua/gm9_cvar/Release/link.read.1.tlog differ diff --git a/lua/gm9_cvar/Release/link.write.1.tlog b/lua/gm9_cvar/Release/link.write.1.tlog new file mode 100644 index 0000000..e98b8b5 Binary files /dev/null and b/lua/gm9_cvar/Release/link.write.1.tlog differ diff --git a/lua/gm9_cvar/Release/main.obj b/lua/gm9_cvar/Release/main.obj new file mode 100644 index 0000000..4eb964d Binary files /dev/null and b/lua/gm9_cvar/Release/main.obj differ diff --git a/lua/gm9_cvar/Release/mt.command.1.tlog b/lua/gm9_cvar/Release/mt.command.1.tlog new file mode 100644 index 0000000..8bf52c0 Binary files /dev/null and b/lua/gm9_cvar/Release/mt.command.1.tlog differ diff --git a/lua/gm9_cvar/Release/mt.read.1.tlog b/lua/gm9_cvar/Release/mt.read.1.tlog new file mode 100644 index 0000000..c42f97a Binary files /dev/null and b/lua/gm9_cvar/Release/mt.read.1.tlog differ diff --git a/lua/gm9_cvar/Release/mt.write.1.tlog b/lua/gm9_cvar/Release/mt.write.1.tlog new file mode 100644 index 0000000..549b842 Binary files /dev/null and b/lua/gm9_cvar/Release/mt.write.1.tlog differ diff --git a/lua/gm9_cvar/Release/sigscan.obj b/lua/gm9_cvar/Release/sigscan.obj new file mode 100644 index 0000000..3a55727 Binary files /dev/null and b/lua/gm9_cvar/Release/sigscan.obj differ diff --git a/lua/gm9_cvar/Release/vc100.pdb b/lua/gm9_cvar/Release/vc100.pdb new file mode 100644 index 0000000..e290e4c Binary files /dev/null and b/lua/gm9_cvar/Release/vc100.pdb differ diff --git a/lua/gm9_cvar/gm9_cvar.vcxproj b/lua/gm9_cvar/gm9_cvar.vcxproj new file mode 100644 index 0000000..9167280 --- /dev/null +++ b/lua/gm9_cvar/gm9_cvar.vcxproj @@ -0,0 +1,76 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {AF48898D-1A3F-4E38-BC13-584E61CD0074} + gm9_cvar + + + + Application + true + MultiByte + + + DynamicLibrary + false + true + MultiByte + + + + + + + + + + + + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + true + true + D:\source2006\common;D:\source2006\public\tier1;D:\source2006\public\tier0;D:\source2006\public;D:\source2006\;%(AdditionalIncludeDirectories) + + + true + true + true + D:\source2006\lib\public;%(AdditionalLibraryDirectories) + tier0.lib;tier1.lib;vstdlib.lib;%(AdditionalDependencies) + LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) + + + + + + + + + + + + + \ No newline at end of file diff --git a/lua/gm9_cvar/gm9_cvar.vcxproj.filters b/lua/gm9_cvar/gm9_cvar.vcxproj.filters new file mode 100644 index 0000000..a5a3cdf --- /dev/null +++ b/lua/gm9_cvar/gm9_cvar.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + + + Заголовочные файлы + + + \ No newline at end of file diff --git a/lua/gm9_cvar/gm9_cvar.vcxproj.user b/lua/gm9_cvar/gm9_cvar.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/lua/gm9_cvar/gm9_cvar.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lua/gm9_cvar/main.cpp b/lua/gm9_cvar/main.cpp new file mode 100644 index 0000000..c7ed782 --- /dev/null +++ b/lua/gm9_cvar/main.cpp @@ -0,0 +1,122 @@ +#include +#include "sigscan.h" +#include "tier0/dbg.h" +#include "tier1.h" +#include "filesystem.h" +#include "icvar.h" +#include "igameevents.h" +#include "keyvalues.h" +#include "tier0/memdbgon.h" + +#define APPFACTORY_SIG "\x8B\x44\x24\x04\x8B\x0D\x00\x00\x00\x00\x50\xE8\x00\x00\x00\x00\x8B\x4C\x24\x08\x85\xC9\x74\x09\x33\xD2\x85\xC0\x0F\x94\xC2\x89\x11\xC3" +#define APPFACTORY_MASK "xxxxxx????xx????xxxxxxxxxxxxxxxxxx" + +IGameEventManager* gameeventmanager; +IFileSystem* filesystem; +ICvar* cvar; +ICvar* g_pCVar; + +const char* g_pCvarFlags[] = { + "FCVAR_UNREGISTERED", "FCVAR_LAUNCHER", + "FCVAR_GAMEDLL", "FCVAR_CLIENTDLL", + "FCVAR_MATERIAL_SYSTEM", "FCVAR_PROTECTED", + "FCVAR_SPONLY", "FCVAR_ARCHIVE", + "FCVAR_NOTIFY", "FCVAR_USERINFO", + "FCVAR_PRINTABLEONLY", "FCVAR_UNLOGGED", + "FCVAR_NEVER_AS_STRING", "FCVAR_REPLICATED", + "FCVAR_CHEAT", "FCVAR_STUDIORENDER", + "FCVAR_DEMO", "FCVAR_DONTRECORD", + "FCVAR_PLUGIN", "FCVAR_DATACACHE", + "FCVAR_TOOLSYSTEM", "FCVAR_FILESYSTEM", + "FCVAR_NOT_CONNECTED", "FCVAR_SOUNDSYSTEM", + "FCVAR_ARCHIVE_XBOX", "FCVAR_INPUTSYSTEM", + "FCVAR_NETWORKSYSTEM", "FCVAR_VPHYSICS" +}; + +extern "C" ICvar* GetCVarIF() +{ + return cvar; +} + +void GetCvarFlags(ConCommandBase* pBase,char* szBuf) +{ + int flags = pBase->m_nFlags&(~FCVAR_NON_ENGINE); + for(int i = 0; i < 28; i++) + { + if(!((flags>>i)&1)) continue; + //if(!pBase->IsBitSet(i)) continue; + if(!i) V_strcpy(szBuf,g_pCvarFlags[i]); + else sprintf(szBuf,"%s %s",szBuf,g_pCvarFlags[i]); + } +} + +CON_COMMAND(fire_event,"Fire test event") +{ + KeyValues* pEvent = new KeyValues("eventPlayerSpawnProp"); + pEvent->SetString("props","maps/gm_construct.bsp"); + gameeventmanager->FireEvent(pEvent); +} + +class SCvarAccessor : public IConCommandBaseAccessor +{ +public: + virtual bool RegisterConCommandBase(ConCommandBase* pCmd) + { + Msg("Registering %s\n",pCmd->GetName()); + + pCmd->AddFlags(FCVAR_PLUGIN); + pCmd->SetNext(NULL); + cvar->RegisterConCommandBase(pCmd); + return true; + } +}; +static SCvarAccessor s_CvarAccessor; + +DWORD WINAPI StartThread(LPVOID lpArg) +{ + CreateInterfaceFn fnAppFactory; + DECLARE_SIGSCAN(fnAppFactory,"engine.dll",APPFACTORY_SIG, + APPFACTORY_MASK,0,SigScan::CSigScan::SIG_FUNCTION); + SigScan::Scan(); + + gameeventmanager = (IGameEventManager*)fnAppFactory( + INTERFACEVERSION_GAMEEVENTSMANAGER,0); + filesystem = (IFileSystem*)fnAppFactory(FILESYSTEM_INTERFACE_VERSION,0); + cvar = (ICvar*)fnAppFactory(VENGINE_CVAR_INTERFACE_VERSION,0); + if(!gameeventmanager || !filesystem || !cvar) + { + Warning("Linking with appfactory failed!\n"); + return 1; + } + + char* pFlags = (char*)malloc(1024); + + ConCommandBase* pNext = cvar->GetCommands(); + FileHandle_t fLog = filesystem->Open("cvardump.txt","wb","MOD"); + while(pNext) + { + bool bIsCommand = pNext->IsCommand(); + GetCvarFlags(pNext,pFlags); + filesystem->FPrintf(fLog,"%s %s %p %s\n",(bIsCommand?"ConCommand":"ConVar"), + pNext->GetName(),(bIsCommand + ? (void*)((ConCommand*)pNext)->m_fnCommandCallback: + pNext),pFlags); + V_memset(pFlags,'\0',1024); + pNext = (ConCommandBase*)pNext->GetNext(); + } + + //0x18 + Msg("ConCommand callback %d\n",offsetof(ConCommand,m_fnCommandCallback)); + ConCommandBaseMgr::OneTimeInit(&s_CvarAccessor); + + free(pFlags); + filesystem->Close(fLog); + return 0; +} + +BOOL APIENTRY DllMain(HINSTANCE hDll,DWORD fdwReason,LPVOID) +{ + if(fdwReason==DLL_PROCESS_ATTACH) + CreateThread(0,0,StartThread,(LPVOID)hDll,0,0); + return TRUE; +} \ No newline at end of file diff --git a/lua/gm9_cvar/sigscan.cpp b/lua/gm9_cvar/sigscan.cpp new file mode 100644 index 0000000..599728f --- /dev/null +++ b/lua/gm9_cvar/sigscan.cpp @@ -0,0 +1,95 @@ +#include "sigscan.h" + +static SigScan::CSigScan* s_pLast; + +void SigScan_Notify(SigScan::CSigScan* pSigScan,SigScan::SigNotify_t notify) +{ + char szError[64]; + if(notify==SigScan::SIG_ERROR) + { + sprintf(szError,"%s (%p) sigscan failed!",pSigScan->m_pName,pSigScan->m_pdwDest); + MessageBoxA(NULL,szError,"SigScan",MB_ICONHAND); + ExitThread(1); + } +} + +SigScan::CSigScan::CSigScan(const char* pName,const char* pDll,const char* pSig,const char* pMask, + PDWORD pdwDest,DWORD dwOffset = 0,SigType_t type) +{ + m_pPrev = NULL; + + m_pName = pName; + m_pDll = pDll; + m_pSig = pSig; + m_pMask = pMask; + m_pdwDest = pdwDest; + m_dwOffset = dwOffset; + m_Type = type; + + Add(this); +} + +void SigScan::Add(CSigScan* pSigScan) +{ + pSigScan->m_pPrev = s_pLast; + s_pLast = pSigScan; +} + +void SigScan::Scan() +{ + CSigScan* pSigScan = s_pLast; + DWORD dwTrunk; + + do { + if(!(dwTrunk = SigScan(GetModuleHandle(pSigScan->m_pDll), + pSigScan->m_pSig,pSigScan->m_pMask))) + { + SigScan_Notify(pSigScan,SIG_ERROR); + continue; + } + + dwTrunk += pSigScan->m_dwOffset; + switch(pSigScan->m_Type) + { + case CSigScan::SIG_FUNCTION: + *pSigScan->m_pdwDest = dwTrunk; + break; + case CSigScan::SIG_PTR: + *pSigScan->m_pdwDest = *(PDWORD)(dwTrunk); + break; + case CSigScan::SIG_VARIABLE: + *pSigScan->m_pdwDest = **(PDWORD*)(dwTrunk); + break; + } + SigScan_Notify(pSigScan,SIG_LOG); + } while((pSigScan = pSigScan->m_pPrev)); +} + +size_t SigScan::GetModuleSize(HMODULE hDll) +{ + PIMAGE_DOS_HEADER DosHeader; + PIMAGE_NT_HEADERS NtHeaders; + + DosHeader = (PIMAGE_DOS_HEADER)hDll; + NtHeaders = (PIMAGE_NT_HEADERS)((LONG)hDll+DosHeader->e_lfanew); + + return NtHeaders->OptionalHeader.SizeOfImage; +} + +DWORD SigScan::SigScan(HMODULE hDll,const char* sig,const char* mask) +{ + size_t j,size = GetModuleSize(hDll),len = strlen(mask); + char* mem = (char*)hDll; + for(size_t i = 0; i < size; i++) + { + for(j = 0; j < len; j++) + { + if((mask[j] != '?') && (((char*)(mem+i))[j] != sig[j])) + break; + } + + if(j==len) + return (DWORD)(mem+i); + } + return NULL; +} \ No newline at end of file diff --git a/lua/gm9_cvar/sigscan.h b/lua/gm9_cvar/sigscan.h new file mode 100644 index 0000000..743d17c --- /dev/null +++ b/lua/gm9_cvar/sigscan.h @@ -0,0 +1,49 @@ +#ifndef __SIGSCAN_H +#define __SIGSCAN_H + +#include +#include + +namespace SigScan +{ + class CSigScan + { + public: + typedef enum { + SIG_FUNCTION, + SIG_VARIABLE, + SIG_PTR, + } SigType_t; + + CSigScan(const char* pName,const char* pDll,const char* pSig,const char* pMask, + PDWORD pdwDest,DWORD dwOffset,SigType_t type = SIG_FUNCTION); + + CSigScan* m_pPrev; + + const char* m_pName; + const char* m_pDll; + const char* m_pSig; + const char* m_pMask; + + PDWORD m_pdwDest; + DWORD m_dwOffset; + SigType_t m_Type; + }; + + typedef enum { + SIG_LOG, + SIG_ERROR, + } SigNotify_t; + + size_t GetModuleSize(HMODULE hDll); + DWORD SigScan(HMODULE hDll,const char* pSig,const char* pMask); + + void Scan(); + void Add(CSigScan* pSigScan); + + //CSigScan* s_pLast; +} + +#define DECLARE_SIGSCAN(dst,dll,sig,mask,ofst,type) SigScan::CSigScan dst##_s(#dst,dll,sig,mask,(PDWORD)&dst,ofst,type) + +#endif \ No newline at end of file diff --git a/lua/gm9_fsdump/Release/CL.read.1.tlog b/lua/gm9_fsdump/Release/CL.read.1.tlog new file mode 100644 index 0000000..46935e9 Binary files /dev/null and b/lua/gm9_fsdump/Release/CL.read.1.tlog differ diff --git a/lua/gm9_fsdump/Release/CL.write.1.tlog b/lua/gm9_fsdump/Release/CL.write.1.tlog new file mode 100644 index 0000000..fef0288 Binary files /dev/null and b/lua/gm9_fsdump/Release/CL.write.1.tlog differ diff --git a/lua/gm9_fsdump/Release/cl.command.1.tlog b/lua/gm9_fsdump/Release/cl.command.1.tlog new file mode 100644 index 0000000..593d7f2 Binary files /dev/null and b/lua/gm9_fsdump/Release/cl.command.1.tlog differ diff --git a/lua/gm9_fsdump/Release/gm9_fsdump.Build.CppClean.log b/lua/gm9_fsdump/Release/gm9_fsdump.Build.CppClean.log new file mode 100644 index 0000000..1616f26 --- /dev/null +++ b/lua/gm9_fsdump/Release/gm9_fsdump.Build.CppClean.log @@ -0,0 +1,15 @@ +D:\lua502\lua\gm9_fsdump\Release\cl.command.1.tlog +D:\lua502\lua\gm9_fsdump\Release\CL.read.1.tlog +D:\lua502\lua\gm9_fsdump\Release\CL.write.1.tlog +D:\LUA502\LUA\GM9_FSDUMP\RELEASE\GM9_FSDUMP.DLL.INTERMEDIATE.MANIFEST +D:\lua502\lua\gm9_fsdump\Release\gm9_fsdump.write.1.tlog +D:\lua502\lua\gm9_fsdump\Release\link.command.1.tlog +D:\lua502\lua\gm9_fsdump\Release\link.read.1.tlog +D:\lua502\lua\gm9_fsdump\Release\link.write.1.tlog +D:\LUA502\LUA\GM9_FSDUMP\RELEASE\MAIN.OBJ +D:\lua502\lua\gm9_fsdump\Release\mt.command.1.tlog +D:\lua502\lua\gm9_fsdump\Release\mt.read.1.tlog +D:\lua502\lua\gm9_fsdump\Release\mt.write.1.tlog +D:\LUA502\LUA\GM9_FSDUMP\RELEASE\VC100.PDB +D:\LUA502\LUA\RELEASE\GM9_FSDUMP.DLL +D:\LUA502\LUA\RELEASE\GM9_FSDUMP.PDB diff --git a/lua/gm9_fsdump/Release/gm9_fsdump.dll.intermediate.manifest b/lua/gm9_fsdump/Release/gm9_fsdump.dll.intermediate.manifest new file mode 100644 index 0000000..ecea6f7 --- /dev/null +++ b/lua/gm9_fsdump/Release/gm9_fsdump.dll.intermediate.manifest @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/lua/gm9_fsdump/Release/gm9_fsdump.lastbuildstate b/lua/gm9_fsdump/Release/gm9_fsdump.lastbuildstate new file mode 100644 index 0000000..c2d4a05 --- /dev/null +++ b/lua/gm9_fsdump/Release/gm9_fsdump.lastbuildstate @@ -0,0 +1,2 @@ +#v4.0:v100:false +Release|Win32|D:\lua502\lua\| diff --git a/lua/gm9_fsdump/Release/gm9_fsdump.log b/lua/gm9_fsdump/Release/gm9_fsdump.log new file mode 100644 index 0000000..8a1fe0f --- /dev/null +++ b/lua/gm9_fsdump/Release/gm9_fsdump.log @@ -0,0 +1,24 @@ +Build started 25.09.2017 22:40:40. + 1>Project "D:\lua502\lua\gm9_fsdump\gm9_fsdump.vcxproj" on node 2 (build target(s)). + 1>InitializeBuildStatus: + Creating "Release\gm9_fsdump.unsuccessfulbuild" because "AlwaysCreate" was specified. + ClCompile: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\CL.exe /c /ID:\gmbase\sdk\public\ /ID:\gmbase\sdk\public\tier1 /ID:\gmbase\sdk\public\tier0 /Zi /nologo /W3 /WX- /O2 /Oi /Oy- /GL /D _WINDLL /D _MBCS /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Release\\" /Fd"Release\vc100.pdb" /Gd /TP /analyze- /errorReport:prompt main.cpp + main.cpp + 1>main.cpp(57): warning C4018: <: неÑоответÑтвие типов Ñо знаком и без знака + 1>main.cpp(65): warning C4101: pFileSystemModule: неиÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð½Ð°Ñ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ð°Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ + Link: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:"D:\lua502\lua\Release\gm9_fsdump.dll" /NOLOGO /LIBPATH:D:\gmbase\sdk\lib\public\ tier1.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NODEFAULTLIB:LIBCMT.lib /MANIFEST /ManifestFile:"Release\gm9_fsdump.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"D:\lua502\lua\Release\gm9_fsdump.pdb" /OPT:REF /OPT:ICF /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"D:\lua502\lua\Release\gm9_fsdump.lib" /MACHINE:X86 /DLL Release\main.obj + Создание кода + Создание кода завершено + gm9_fsdump.vcxproj -> D:\lua502\lua\Release\gm9_fsdump.dll + Manifest: + C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe /nologo /verbose /outputresource:"D:\lua502\lua\Release\gm9_fsdump.dll;#2" /manifest Release\gm9_fsdump.dll.intermediate.manifest + FinalizeBuildStatus: + Deleting file "Release\gm9_fsdump.unsuccessfulbuild". + Touching "Release\gm9_fsdump.lastbuildstate". + 1>Done Building Project "D:\lua502\lua\gm9_fsdump\gm9_fsdump.vcxproj" (build target(s)). + +ПоÑтроение уÑпешно завершено. + +Time Elapsed 00:00:04.01 diff --git a/lua/gm9_fsdump/Release/gm9_fsdump.vcxprojResolveAssemblyReference.cache b/lua/gm9_fsdump/Release/gm9_fsdump.vcxprojResolveAssemblyReference.cache new file mode 100644 index 0000000..3f01681 Binary files /dev/null and b/lua/gm9_fsdump/Release/gm9_fsdump.vcxprojResolveAssemblyReference.cache differ diff --git a/lua/gm9_fsdump/Release/gm9_fsdump.write.1.tlog b/lua/gm9_fsdump/Release/gm9_fsdump.write.1.tlog new file mode 100644 index 0000000..e69de29 diff --git a/lua/gm9_fsdump/Release/link.command.1.tlog b/lua/gm9_fsdump/Release/link.command.1.tlog new file mode 100644 index 0000000..2875c8f Binary files /dev/null and b/lua/gm9_fsdump/Release/link.command.1.tlog differ diff --git a/lua/gm9_fsdump/Release/link.read.1.tlog b/lua/gm9_fsdump/Release/link.read.1.tlog new file mode 100644 index 0000000..d539ff1 Binary files /dev/null and b/lua/gm9_fsdump/Release/link.read.1.tlog differ diff --git a/lua/gm9_fsdump/Release/link.write.1.tlog b/lua/gm9_fsdump/Release/link.write.1.tlog new file mode 100644 index 0000000..3db9efb Binary files /dev/null and b/lua/gm9_fsdump/Release/link.write.1.tlog differ diff --git a/lua/gm9_fsdump/Release/main.obj b/lua/gm9_fsdump/Release/main.obj new file mode 100644 index 0000000..12a80a0 Binary files /dev/null and b/lua/gm9_fsdump/Release/main.obj differ diff --git a/lua/gm9_fsdump/Release/mt.command.1.tlog b/lua/gm9_fsdump/Release/mt.command.1.tlog new file mode 100644 index 0000000..93185b7 Binary files /dev/null and b/lua/gm9_fsdump/Release/mt.command.1.tlog differ diff --git a/lua/gm9_fsdump/Release/mt.read.1.tlog b/lua/gm9_fsdump/Release/mt.read.1.tlog new file mode 100644 index 0000000..3807356 Binary files /dev/null and b/lua/gm9_fsdump/Release/mt.read.1.tlog differ diff --git a/lua/gm9_fsdump/Release/mt.write.1.tlog b/lua/gm9_fsdump/Release/mt.write.1.tlog new file mode 100644 index 0000000..ea0c4ab Binary files /dev/null and b/lua/gm9_fsdump/Release/mt.write.1.tlog differ diff --git a/lua/gm9_fsdump/Release/vc100.pdb b/lua/gm9_fsdump/Release/vc100.pdb new file mode 100644 index 0000000..0fd1dbc Binary files /dev/null and b/lua/gm9_fsdump/Release/vc100.pdb differ diff --git a/lua/gm9_fsdump/gm9_fsdump.vcxproj b/lua/gm9_fsdump/gm9_fsdump.vcxproj new file mode 100644 index 0000000..940f710 --- /dev/null +++ b/lua/gm9_fsdump/gm9_fsdump.vcxproj @@ -0,0 +1,74 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {A183C6DC-B05F-40AC-B0DC-E1F8794F633D} + gm9_fsdump + + + + Application + true + MultiByte + + + DynamicLibrary + false + true + MultiByte + + + + + + + + + + + + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + true + true + D:\gmbase\sdk\public\;D:\gmbase\sdk\public\tier1;D:\gmbase\sdk\public\tier0;%(AdditionalIncludeDirectories) + + + true + true + true + D:\gmbase\sdk\lib\public\;%(AdditionalLibraryDirectories) + tier1.lib;%(AdditionalDependencies) + LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) + + + + + + + + + + + \ No newline at end of file diff --git a/lua/gm9_fsdump/gm9_fsdump.vcxproj.filters b/lua/gm9_fsdump/gm9_fsdump.vcxproj.filters new file mode 100644 index 0000000..1aa6936 --- /dev/null +++ b/lua/gm9_fsdump/gm9_fsdump.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Файлы иÑходного кода + + + \ No newline at end of file diff --git a/lua/gm9_fsdump/gm9_fsdump.vcxproj.user b/lua/gm9_fsdump/gm9_fsdump.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/lua/gm9_fsdump/gm9_fsdump.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lua/gm9_fsdump/main.cpp b/lua/gm9_fsdump/main.cpp new file mode 100644 index 0000000..9785d04 --- /dev/null +++ b/lua/gm9_fsdump/main.cpp @@ -0,0 +1,94 @@ +#include +#include +#include "utlvector.h" +#include "utlsymbol.h" +#include "utlmemory.h" +#include "interface.h" +//#define GMOD9 + +#ifdef GMOD9 +# define FILESYSTEM_INTERFACEVERSION "VFileSystem017" +# define FILESYSTEM_MODULE "filesystem_steam.dll" +# define VPRINTPATHS 65 +#else +# define FILESYSTEM_INTERFACEVERSION "VFileSystem022" +# define FILESYSTEM_MODULE "filesystem_stdio.dll" +# define VPRINTPATHS 63 +#endif +//Offset 0x48 + +#undef Msg +typedef void (*Msg_t)(const char*,...); +typedef void (__thiscall* PrintSearchPaths_t)(void* thisptr); +typedef HMODULE (__thiscall* LoadModule_t)(void* thisptr,const char* pName); +Msg_t g_pMsg; + +class CSearchPath +{ +public: + int m_iStoreId; + void* m_pPathInfo; + bool m_bIsRemotePath; + CUtlSymbol m_Path; +}; + +#define LOADMODULE_SIG "\x81\xEC\x00\x00\x00\x00\x53\x55\x56\x57\x8B\xF9\x8D\x44\x24\x28" +#define LOADMODULE_MASK "xx????xxxxxxxxxx" + +typedef struct { + const char* m_pSig; + const char* m_pMask; + const char* m_pName; +} signature_t; + +signature_t g_zSigs[] = { + {"\x81\xEC\x00\x00\x00\x00\x8B\x84\x24\x00\x00\x00\x00\x53\x55\x56\x57\x8B\xF1\x50\x89\x74\x24\x1C", + "xx????xxx????xxxxxxxxxxx","CBaseFileSystem::LoadModule"}, + {"\x81\xEC\x00\x00\x00\x00\x53\x55\x56\x57\x8B\xF9\x8D\x44\x24\x28","xx????xxxxxxxxxx", + "CBaseFileSystem::LoadModule__ALT"}, + {"\x81\xEC\x00\x00\x00\x00\x8B\x84\x24\x00\x00\x00\x00\x53\x55\x56\x57\x33\xFF\x3B\xC7\x8B\xF1", + "xx????xxx????xxxxxxxxxx","CBaseFileSystem::CacheFileCRCs_R"}, + {NULL,NULL,NULL} +}; + +bool SigCheck(char* pMem,const char* pSig,const char* pMask) +{ + size_t iLen = strlen(pMask); + for(int i = 0; i < iLen; i++) + if(pMask[i] == 'x' && pMem[i] != pSig[i]) return false; + return true; +} + +DWORD WINAPI StartThread(LPVOID lpArg) +{ + DWORD dwFileSystem = 0; + CSysModule* pFileSystemModule; + g_pMsg = (Msg_t)GetProcAddress(GetModuleHandle("tier0.dll"),"Msg"); + if(!(dwFileSystem = (DWORD)((CreateInterfaceFn)GetProcAddress(GetModuleHandle( + FILESYSTEM_MODULE),"CreateInterface"))(FILESYSTEM_INTERFACEVERSION,NULL))) + { + g_pMsg("FileSystem not found!\n"); + FreeLibraryAndExitThread((HMODULE)lpArg,1); + } + ((PrintSearchPaths_t)((*(PDWORD*)dwFileSystem)[VPRINTPATHS]))((void*)dwFileSystem); + PDWORD pdwVTable = *(PDWORD*)(dwFileSystem); + for(int i = 0; i < 100; i++) + { + for(signature_t* pSig = g_zSigs; pSig->m_pMask; pSig++) + { + if(SigCheck((char*)pdwVTable[i],pSig->m_pSig,pSig->m_pMask)) + g_pMsg("VFunc %d %s\n",i,pSig->m_pName); + } + } + + //((LoadModule_t)((*(PDWORD*)dwFileSystem)[29]))((void*)dwFileSystem,"gm9x_testapp"); + FreeLibraryAndExitThread((HMODULE)lpArg,0); + return 0; +} + +BOOL APIENTRY DllMain(HINSTANCE hDll,DWORD fdwReason,LPVOID lpArg) +{ + if(fdwReason==DLL_PROCESS_ATTACH) + CreateThread(0,0,StartThread,(LPVOID)hDll,0,0); + return TRUE; +} \ No newline at end of file diff --git a/lua/gm9_interface/Release/CL.read.1.tlog b/lua/gm9_interface/Release/CL.read.1.tlog new file mode 100644 index 0000000..c91360b Binary files /dev/null and b/lua/gm9_interface/Release/CL.read.1.tlog differ diff --git a/lua/gm9_interface/Release/CL.write.1.tlog b/lua/gm9_interface/Release/CL.write.1.tlog new file mode 100644 index 0000000..460921b Binary files /dev/null and b/lua/gm9_interface/Release/CL.write.1.tlog differ diff --git a/lua/gm9_interface/Release/cl.command.1.tlog b/lua/gm9_interface/Release/cl.command.1.tlog new file mode 100644 index 0000000..9a6bc39 Binary files /dev/null and b/lua/gm9_interface/Release/cl.command.1.tlog differ diff --git a/lua/gm9_interface/Release/gm9_interface.dll.intermediate.manifest b/lua/gm9_interface/Release/gm9_interface.dll.intermediate.manifest new file mode 100644 index 0000000..ecea6f7 --- /dev/null +++ b/lua/gm9_interface/Release/gm9_interface.dll.intermediate.manifest @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/lua/gm9_interface/Release/gm9_interface.lastbuildstate b/lua/gm9_interface/Release/gm9_interface.lastbuildstate new file mode 100644 index 0000000..c2d4a05 --- /dev/null +++ b/lua/gm9_interface/Release/gm9_interface.lastbuildstate @@ -0,0 +1,2 @@ +#v4.0:v100:false +Release|Win32|D:\lua502\lua\| diff --git a/lua/gm9_interface/Release/gm9_interface.log b/lua/gm9_interface/Release/gm9_interface.log new file mode 100644 index 0000000..2fe1f0d --- /dev/null +++ b/lua/gm9_interface/Release/gm9_interface.log @@ -0,0 +1,22 @@ +Build started 16.09.2017 0:33:33. + 1>Project "D:\lua502\lua\gm9_interface\gm9_interface.vcxproj" on node 2 (build target(s)). + 1>InitializeBuildStatus: + Creating "Release\gm9_interface.unsuccessfulbuild" because "AlwaysCreate" was specified. + ClCompile: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\CL.exe /c /Zi /nologo /W3 /WX- /O2 /Oi /Oy- /GL /D _WINDLL /D _MBCS /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Release\\" /Fd"Release\vc100.pdb" /Gd /TP /analyze- /errorReport:prompt main.cpp + main.cpp + Link: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:"D:\lua502\lua\Release\gm9_interface.dll" /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /MANIFEST /ManifestFile:"Release\gm9_interface.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"D:\lua502\lua\Release\gm9_interface.pdb" /OPT:REF /OPT:ICF /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"D:\lua502\lua\Release\gm9_interface.lib" /MACHINE:X86 /DLL Release\main.obj + Создание кода + Создание кода завершено + gm9_interface.vcxproj -> D:\lua502\lua\Release\gm9_interface.dll + Manifest: + C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe /nologo /verbose /outputresource:"D:\lua502\lua\Release\gm9_interface.dll;#2" /manifest Release\gm9_interface.dll.intermediate.manifest + FinalizeBuildStatus: + Deleting file "Release\gm9_interface.unsuccessfulbuild". + Touching "Release\gm9_interface.lastbuildstate". + 1>Done Building Project "D:\lua502\lua\gm9_interface\gm9_interface.vcxproj" (build target(s)). + +ПоÑтроение уÑпешно завершено. + +Time Elapsed 00:00:02.14 diff --git a/lua/gm9_interface/Release/gm9_interface.vcxprojResolveAssemblyReference.cache b/lua/gm9_interface/Release/gm9_interface.vcxprojResolveAssemblyReference.cache new file mode 100644 index 0000000..3f01681 Binary files /dev/null and b/lua/gm9_interface/Release/gm9_interface.vcxprojResolveAssemblyReference.cache differ diff --git a/lua/gm9_interface/Release/gm9_interface.write.1.tlog b/lua/gm9_interface/Release/gm9_interface.write.1.tlog new file mode 100644 index 0000000..e69de29 diff --git a/lua/gm9_interface/Release/link.command.1.tlog b/lua/gm9_interface/Release/link.command.1.tlog new file mode 100644 index 0000000..7731868 Binary files /dev/null and b/lua/gm9_interface/Release/link.command.1.tlog differ diff --git a/lua/gm9_interface/Release/link.read.1.tlog b/lua/gm9_interface/Release/link.read.1.tlog new file mode 100644 index 0000000..2f6df87 Binary files /dev/null and b/lua/gm9_interface/Release/link.read.1.tlog differ diff --git a/lua/gm9_interface/Release/link.write.1.tlog b/lua/gm9_interface/Release/link.write.1.tlog new file mode 100644 index 0000000..487e226 Binary files /dev/null and b/lua/gm9_interface/Release/link.write.1.tlog differ diff --git a/lua/gm9_interface/Release/main.obj b/lua/gm9_interface/Release/main.obj new file mode 100644 index 0000000..519045d Binary files /dev/null and b/lua/gm9_interface/Release/main.obj differ diff --git a/lua/gm9_interface/Release/mt.command.1.tlog b/lua/gm9_interface/Release/mt.command.1.tlog new file mode 100644 index 0000000..fc4ac95 Binary files /dev/null and b/lua/gm9_interface/Release/mt.command.1.tlog differ diff --git a/lua/gm9_interface/Release/mt.read.1.tlog b/lua/gm9_interface/Release/mt.read.1.tlog new file mode 100644 index 0000000..f9e9115 Binary files /dev/null and b/lua/gm9_interface/Release/mt.read.1.tlog differ diff --git a/lua/gm9_interface/Release/mt.write.1.tlog b/lua/gm9_interface/Release/mt.write.1.tlog new file mode 100644 index 0000000..1a0eaf5 Binary files /dev/null and b/lua/gm9_interface/Release/mt.write.1.tlog differ diff --git a/lua/gm9_interface/Release/vc100.pdb b/lua/gm9_interface/Release/vc100.pdb new file mode 100644 index 0000000..3bc3922 Binary files /dev/null and b/lua/gm9_interface/Release/vc100.pdb differ diff --git a/lua/gm9_interface/gm9_interface.vcxproj b/lua/gm9_interface/gm9_interface.vcxproj new file mode 100644 index 0000000..012f928 --- /dev/null +++ b/lua/gm9_interface/gm9_interface.vcxproj @@ -0,0 +1,68 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {6F268CBD-9B5A-4260-BFC1-74A657370DAA} + gm9_interface + + + + Application + true + MultiByte + + + DynamicLibrary + false + true + MultiByte + + + + + + + + + + + + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + true + true + + + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/lua/gm9_interface/gm9_interface.vcxproj.filters b/lua/gm9_interface/gm9_interface.vcxproj.filters new file mode 100644 index 0000000..1aa6936 --- /dev/null +++ b/lua/gm9_interface/gm9_interface.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Файлы иÑходного кода + + + \ No newline at end of file diff --git a/lua/gm9_interface/gm9_interface.vcxproj.user b/lua/gm9_interface/gm9_interface.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/lua/gm9_interface/gm9_interface.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lua/gm9_interface/main.cpp b/lua/gm9_interface/main.cpp new file mode 100644 index 0000000..117b406 --- /dev/null +++ b/lua/gm9_interface/main.cpp @@ -0,0 +1,64 @@ +#include +#include +#include + +typedef void* (*GetInterfaceFn_t)(); +typedef struct interfacereg_s { + GetInterfaceFn_t m_fnGetInterface; + const char* m_pName; + struct interfacereg_s* m_pNext; +} interfacereg_t; + +void DumpInterfaces(PMODULEENTRY32 pModEntry,FILE* fDump) +{ + DWORD dwFunc; + interfacereg_t* pInterfaceReg; + + if(!(dwFunc = (DWORD)GetProcAddress(pModEntry->hModule,"CreateInterface"))) return; + fprintf(fDump,"==== %s ====\n",pModEntry->szModule); + if(*(PWORD)((char*)dwFunc+0x03) != 0x3D8B){ + fputs("Signature failed\n",fDump); + return; + } + if(!(pInterfaceReg = **(interfacereg_t***)((char*)dwFunc+0x05))){ + fputs("interfacereg_t null\n",fDump); + return; + return; + } + do { + fprintf(fDump,"\t%s %p\n",pInterfaceReg->m_pName,(DWORD) + ((BYTE*)pInterfaceReg->m_fnGetInterface-pModEntry->modBaseAddr)); + } while(pInterfaceReg = pInterfaceReg->m_pNext); +} + +DWORD WINAPI StartThread(LPVOID lpArg) +{ + FILE* fDump; + fopen_s(&fDump,"gm9_interface.txt","wb"); + + MODULEENTRY32 modEntry; + HANDLE hSnapshot = NULL; + DWORD dwCurProcId = GetCurrentProcessId(); + + modEntry.dwSize = sizeof(MODULEENTRY32); + hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,dwCurProcId); + if(!hSnapshot) return 1; + if(Module32First(hSnapshot,&modEntry)) + { + do { + if(modEntry.th32ProcessID!=dwCurProcId) continue; + DumpInterfaces(&modEntry,fDump); + } while(Module32Next(hSnapshot,&modEntry)); + } + CloseHandle(hSnapshot); + fclose(fDump); + FreeLibraryAndExitThread((HMODULE)lpArg,0); + return 0; +} + +BOOL APIENTRY DllMain(HINSTANCE hDll,DWORD fdwReason,LPVOID lpArg) +{ + if(fdwReason==DLL_PROCESS_ATTACH) + CreateThread(0,0,StartThread,(LPVOID)hDll,0,0); + return TRUE; +} \ No newline at end of file diff --git a/lua/gm9_internal/Release/CL.read.1.tlog b/lua/gm9_internal/Release/CL.read.1.tlog new file mode 100644 index 0000000..2a702e4 Binary files /dev/null and b/lua/gm9_internal/Release/CL.read.1.tlog differ diff --git a/lua/gm9_internal/Release/CL.write.1.tlog b/lua/gm9_internal/Release/CL.write.1.tlog new file mode 100644 index 0000000..372a4e3 Binary files /dev/null and b/lua/gm9_internal/Release/CL.write.1.tlog differ diff --git a/lua/gm9_internal/Release/cl.command.1.tlog b/lua/gm9_internal/Release/cl.command.1.tlog new file mode 100644 index 0000000..b167cc7 Binary files /dev/null and b/lua/gm9_internal/Release/cl.command.1.tlog differ diff --git a/lua/gm9_internal/Release/gm9_internal.dll.intermediate.manifest b/lua/gm9_internal/Release/gm9_internal.dll.intermediate.manifest new file mode 100644 index 0000000..ecea6f7 --- /dev/null +++ b/lua/gm9_internal/Release/gm9_internal.dll.intermediate.manifest @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/lua/gm9_internal/Release/gm9_internal.lastbuildstate b/lua/gm9_internal/Release/gm9_internal.lastbuildstate new file mode 100644 index 0000000..c2d4a05 --- /dev/null +++ b/lua/gm9_internal/Release/gm9_internal.lastbuildstate @@ -0,0 +1,2 @@ +#v4.0:v100:false +Release|Win32|D:\lua502\lua\| diff --git a/lua/gm9_internal/Release/gm9_internal.log b/lua/gm9_internal/Release/gm9_internal.log new file mode 100644 index 0000000..9ca3734 --- /dev/null +++ b/lua/gm9_internal/Release/gm9_internal.log @@ -0,0 +1,23 @@ +Build started 16.09.2017 1:05:28. + 1>Project "D:\lua502\lua\gm9_internal\gm9_internal.vcxproj" on node 2 (build target(s)). + 1>InitializeBuildStatus: + Creating "Release\gm9_internal.unsuccessfulbuild" because "AlwaysCreate" was specified. + ClCompile: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\CL.exe /c /ID:\lua502\src /ID:\lua502\include /Zi /nologo /W3 /WX- /O2 /Oi /Oy- /GL /D _WINDLL /D _MBCS /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Release\\" /Fd"Release\vc100.pdb" /Gd /TP /analyze- /errorReport:prompt main.cpp + main.cpp + Link: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:"D:\lua502\lua\Release\gm9_internal.dll" /NOLOGO /LIBPATH:D:\lua502\lua\Release lcore.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /MANIFEST /ManifestFile:"Release\gm9_internal.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"D:\lua502\lua\Release\gm9_internal.pdb" /OPT:REF /OPT:ICF /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"D:\lua502\lua\Release\gm9_internal.lib" /MACHINE:X86 /DLL Release\main.obj + Release\sigscan.obj + Создание кода + Создание кода завершено + gm9_internal.vcxproj -> D:\lua502\lua\Release\gm9_internal.dll + Manifest: + C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe /nologo /verbose /outputresource:"D:\lua502\lua\Release\gm9_internal.dll;#2" /manifest Release\gm9_internal.dll.intermediate.manifest + FinalizeBuildStatus: + Deleting file "Release\gm9_internal.unsuccessfulbuild". + Touching "Release\gm9_internal.lastbuildstate". + 1>Done Building Project "D:\lua502\lua\gm9_internal\gm9_internal.vcxproj" (build target(s)). + +ПоÑтроение уÑпешно завершено. + +Time Elapsed 00:00:09.27 diff --git a/lua/gm9_internal/Release/gm9_internal.vcxprojResolveAssemblyReference.cache b/lua/gm9_internal/Release/gm9_internal.vcxprojResolveAssemblyReference.cache new file mode 100644 index 0000000..3f01681 Binary files /dev/null and b/lua/gm9_internal/Release/gm9_internal.vcxprojResolveAssemblyReference.cache differ diff --git a/lua/gm9_internal/Release/gm9_internal.write.1.tlog b/lua/gm9_internal/Release/gm9_internal.write.1.tlog new file mode 100644 index 0000000..e69de29 diff --git a/lua/gm9_internal/Release/link.command.1.tlog b/lua/gm9_internal/Release/link.command.1.tlog new file mode 100644 index 0000000..66a6c22 Binary files /dev/null and b/lua/gm9_internal/Release/link.command.1.tlog differ diff --git a/lua/gm9_internal/Release/link.read.1.tlog b/lua/gm9_internal/Release/link.read.1.tlog new file mode 100644 index 0000000..a54d0d5 Binary files /dev/null and b/lua/gm9_internal/Release/link.read.1.tlog differ diff --git a/lua/gm9_internal/Release/link.write.1.tlog b/lua/gm9_internal/Release/link.write.1.tlog new file mode 100644 index 0000000..218765f Binary files /dev/null and b/lua/gm9_internal/Release/link.write.1.tlog differ diff --git a/lua/gm9_internal/Release/main.obj b/lua/gm9_internal/Release/main.obj new file mode 100644 index 0000000..6eaf264 Binary files /dev/null and b/lua/gm9_internal/Release/main.obj differ diff --git a/lua/gm9_internal/Release/mt.command.1.tlog b/lua/gm9_internal/Release/mt.command.1.tlog new file mode 100644 index 0000000..aa5de14 Binary files /dev/null and b/lua/gm9_internal/Release/mt.command.1.tlog differ diff --git a/lua/gm9_internal/Release/mt.read.1.tlog b/lua/gm9_internal/Release/mt.read.1.tlog new file mode 100644 index 0000000..89d516c Binary files /dev/null and b/lua/gm9_internal/Release/mt.read.1.tlog differ diff --git a/lua/gm9_internal/Release/mt.write.1.tlog b/lua/gm9_internal/Release/mt.write.1.tlog new file mode 100644 index 0000000..e33e6e8 Binary files /dev/null and b/lua/gm9_internal/Release/mt.write.1.tlog differ diff --git a/lua/gm9_internal/Release/sigscan.obj b/lua/gm9_internal/Release/sigscan.obj new file mode 100644 index 0000000..8eb707d Binary files /dev/null and b/lua/gm9_internal/Release/sigscan.obj differ diff --git a/lua/gm9_internal/Release/vc100.pdb b/lua/gm9_internal/Release/vc100.pdb new file mode 100644 index 0000000..b2f7fab Binary files /dev/null and b/lua/gm9_internal/Release/vc100.pdb differ diff --git a/lua/gm9_internal/gm9_internal.vcxproj b/lua/gm9_internal/gm9_internal.vcxproj new file mode 100644 index 0000000..1f8c4f3 --- /dev/null +++ b/lua/gm9_internal/gm9_internal.vcxproj @@ -0,0 +1,75 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {C845B13A-C336-4529-8D3A-3B5CB9353830} + gm9_internal + + + + Application + true + MultiByte + + + DynamicLibrary + false + true + MultiByte + + + + + + + + + + + + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + true + true + D:\lua502\src;D:\lua502\include;%(AdditionalIncludeDirectories) + + + true + true + true + D:\lua502\lua\Release;%(AdditionalLibraryDirectories) + lcore.lib;%(AdditionalDependencies) + + + + + + + + + + + + + \ No newline at end of file diff --git a/lua/gm9_internal/gm9_internal.vcxproj.filters b/lua/gm9_internal/gm9_internal.vcxproj.filters new file mode 100644 index 0000000..a5a3cdf --- /dev/null +++ b/lua/gm9_internal/gm9_internal.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + + + Заголовочные файлы + + + \ No newline at end of file diff --git a/lua/gm9_internal/gm9_internal.vcxproj.user b/lua/gm9_internal/gm9_internal.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/lua/gm9_internal/gm9_internal.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lua/gm9_internal/main.cpp b/lua/gm9_internal/main.cpp new file mode 100644 index 0000000..8e49420 --- /dev/null +++ b/lua/gm9_internal/main.cpp @@ -0,0 +1,45 @@ +#include +#include +#include "sigscan.h" +extern "C" { +#include "lua.h" +#include "lauxlib.h" +#include "lstate.h" +} + +#define GETLUAINTERFACE_SIG "\xA1\x00\x00\x00\x00\xC3\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\x81\xEC\x00\x00\x00\x00" +#define GETLUAINTERFACE_MASK "x????xxxxxxxxxxxxx????" + +class CLuaInterface +{ +public: + lua_State* m_pL; +}; +CLuaInterface* g_pLuaInterface; +DECLARE_SIGSCAN(g_pLuaInterface,"server.dll",GETLUAINTERFACE_SIG,GETLUAINTERFACE_MASK,1,SigScan::CSigScan::SIG_VARIABLE); + +DWORD WINAPI StartThread(LPVOID lpArg) +{ + SigScan::Scan(); + const char* pLua = "Msg(string.format(\"Hello World\\n\"))"; + + lua_pushnumber(g_pLuaInterface->m_pL,sizeof(lua_State)); + lua_setglobal(g_pLuaInterface->m_pL,"lua_State__sizeof"); + + if(luaL_loadbuffer(g_pLuaInterface->m_pL,pLua,strlen(pLua),"gm9_internal")) + { + const char* pErr = lua_tostring(g_pLuaInterface->m_pL,-1); + lua_pop(g_pLuaInterface->m_pL,1); + MessageBoxA(NULL,pErr,"Lua Error",MB_ICONHAND); + } + else lua_pcall(g_pLuaInterface->m_pL,0,0,0); + + return 0; +} + +BOOL APIENTRY DllMain(HINSTANCE hDll,DWORD fdwReason,LPVOID lpArg) +{ + if(fdwReason==DLL_PROCESS_ATTACH) + CreateThread(0,0,StartThread,0,0,0); + return TRUE; +} \ No newline at end of file diff --git a/lua/gm9_internal/sigscan.cpp b/lua/gm9_internal/sigscan.cpp new file mode 100644 index 0000000..599728f --- /dev/null +++ b/lua/gm9_internal/sigscan.cpp @@ -0,0 +1,95 @@ +#include "sigscan.h" + +static SigScan::CSigScan* s_pLast; + +void SigScan_Notify(SigScan::CSigScan* pSigScan,SigScan::SigNotify_t notify) +{ + char szError[64]; + if(notify==SigScan::SIG_ERROR) + { + sprintf(szError,"%s (%p) sigscan failed!",pSigScan->m_pName,pSigScan->m_pdwDest); + MessageBoxA(NULL,szError,"SigScan",MB_ICONHAND); + ExitThread(1); + } +} + +SigScan::CSigScan::CSigScan(const char* pName,const char* pDll,const char* pSig,const char* pMask, + PDWORD pdwDest,DWORD dwOffset = 0,SigType_t type) +{ + m_pPrev = NULL; + + m_pName = pName; + m_pDll = pDll; + m_pSig = pSig; + m_pMask = pMask; + m_pdwDest = pdwDest; + m_dwOffset = dwOffset; + m_Type = type; + + Add(this); +} + +void SigScan::Add(CSigScan* pSigScan) +{ + pSigScan->m_pPrev = s_pLast; + s_pLast = pSigScan; +} + +void SigScan::Scan() +{ + CSigScan* pSigScan = s_pLast; + DWORD dwTrunk; + + do { + if(!(dwTrunk = SigScan(GetModuleHandle(pSigScan->m_pDll), + pSigScan->m_pSig,pSigScan->m_pMask))) + { + SigScan_Notify(pSigScan,SIG_ERROR); + continue; + } + + dwTrunk += pSigScan->m_dwOffset; + switch(pSigScan->m_Type) + { + case CSigScan::SIG_FUNCTION: + *pSigScan->m_pdwDest = dwTrunk; + break; + case CSigScan::SIG_PTR: + *pSigScan->m_pdwDest = *(PDWORD)(dwTrunk); + break; + case CSigScan::SIG_VARIABLE: + *pSigScan->m_pdwDest = **(PDWORD*)(dwTrunk); + break; + } + SigScan_Notify(pSigScan,SIG_LOG); + } while((pSigScan = pSigScan->m_pPrev)); +} + +size_t SigScan::GetModuleSize(HMODULE hDll) +{ + PIMAGE_DOS_HEADER DosHeader; + PIMAGE_NT_HEADERS NtHeaders; + + DosHeader = (PIMAGE_DOS_HEADER)hDll; + NtHeaders = (PIMAGE_NT_HEADERS)((LONG)hDll+DosHeader->e_lfanew); + + return NtHeaders->OptionalHeader.SizeOfImage; +} + +DWORD SigScan::SigScan(HMODULE hDll,const char* sig,const char* mask) +{ + size_t j,size = GetModuleSize(hDll),len = strlen(mask); + char* mem = (char*)hDll; + for(size_t i = 0; i < size; i++) + { + for(j = 0; j < len; j++) + { + if((mask[j] != '?') && (((char*)(mem+i))[j] != sig[j])) + break; + } + + if(j==len) + return (DWORD)(mem+i); + } + return NULL; +} \ No newline at end of file diff --git a/lua/gm9_internal/sigscan.h b/lua/gm9_internal/sigscan.h new file mode 100644 index 0000000..743d17c --- /dev/null +++ b/lua/gm9_internal/sigscan.h @@ -0,0 +1,49 @@ +#ifndef __SIGSCAN_H +#define __SIGSCAN_H + +#include +#include + +namespace SigScan +{ + class CSigScan + { + public: + typedef enum { + SIG_FUNCTION, + SIG_VARIABLE, + SIG_PTR, + } SigType_t; + + CSigScan(const char* pName,const char* pDll,const char* pSig,const char* pMask, + PDWORD pdwDest,DWORD dwOffset,SigType_t type = SIG_FUNCTION); + + CSigScan* m_pPrev; + + const char* m_pName; + const char* m_pDll; + const char* m_pSig; + const char* m_pMask; + + PDWORD m_pdwDest; + DWORD m_dwOffset; + SigType_t m_Type; + }; + + typedef enum { + SIG_LOG, + SIG_ERROR, + } SigNotify_t; + + size_t GetModuleSize(HMODULE hDll); + DWORD SigScan(HMODULE hDll,const char* pSig,const char* pMask); + + void Scan(); + void Add(CSigScan* pSigScan); + + //CSigScan* s_pLast; +} + +#define DECLARE_SIGSCAN(dst,dll,sig,mask,ofst,type) SigScan::CSigScan dst##_s(#dst,dll,sig,mask,(PDWORD)&dst,ofst,type) + +#endif \ No newline at end of file diff --git a/lua/gm9_src7/Release/CL.read.1.tlog b/lua/gm9_src7/Release/CL.read.1.tlog new file mode 100644 index 0000000..27b172c Binary files /dev/null and b/lua/gm9_src7/Release/CL.read.1.tlog differ diff --git a/lua/gm9_src7/Release/CL.write.1.tlog b/lua/gm9_src7/Release/CL.write.1.tlog new file mode 100644 index 0000000..5c53abc Binary files /dev/null and b/lua/gm9_src7/Release/CL.write.1.tlog differ diff --git a/lua/gm9_src7/Release/cl.command.1.tlog b/lua/gm9_src7/Release/cl.command.1.tlog new file mode 100644 index 0000000..76effba Binary files /dev/null and b/lua/gm9_src7/Release/cl.command.1.tlog differ diff --git a/lua/gm9_src7/Release/gm9_src7.dll.intermediate.manifest b/lua/gm9_src7/Release/gm9_src7.dll.intermediate.manifest new file mode 100644 index 0000000..ecea6f7 --- /dev/null +++ b/lua/gm9_src7/Release/gm9_src7.dll.intermediate.manifest @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/lua/gm9_src7/Release/gm9_src7.lastbuildstate b/lua/gm9_src7/Release/gm9_src7.lastbuildstate new file mode 100644 index 0000000..c2d4a05 --- /dev/null +++ b/lua/gm9_src7/Release/gm9_src7.lastbuildstate @@ -0,0 +1,2 @@ +#v4.0:v100:false +Release|Win32|D:\lua502\lua\| diff --git a/lua/gm9_src7/Release/gm9_src7.log b/lua/gm9_src7/Release/gm9_src7.log new file mode 100644 index 0000000..dbc2e99 --- /dev/null +++ b/lua/gm9_src7/Release/gm9_src7.log @@ -0,0 +1,23 @@ +Build started 20.09.2017 1:05:58. + 1>Project "D:\lua502\lua\gm9_src7\gm9_src7.vcxproj" on node 2 (build target(s)). + 1>InitializeBuildStatus: + Creating "Release\gm9_src7.unsuccessfulbuild" because "AlwaysCreate" was specified. + ClCompile: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\CL.exe /c /ID:\source2006\public\tier1 /ID:\source2006\public\tier0 /ID:\source2006\public /ID:\source2006\cl_dll /ID:\source2006\game_shared /ID:\source2006\common /Zi /nologo /W3 /WX- /O2 /Oi /Oy- /GL /D _WINDLL /D _MBCS /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Release\\" /Fd"Release\vc100.pdb" /Gd /TP /analyze- /errorReport:prompt main.cpp + main.cpp + Link: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:"D:\lua502\lua\Release\gm9_src7.dll" /NOLOGO /LIBPATH:D:\source2006\lib\public tier0.lib tier1.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NODEFAULTLIB:LIBCMT.lib /MANIFEST /ManifestFile:"Release\gm9_src7.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"D:\lua502\lua\Release\gm9_src7.pdb" /OPT:REF /OPT:ICF /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"D:\lua502\lua\Release\gm9_src7.lib" /MACHINE:X86 /DLL Release\main.obj + СоздаетÑÑ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ° D:\lua502\lua\Release\gm9_src7.lib и объект D:\lua502\lua\Release\gm9_src7.exp + Создание кода + Создание кода завершено + gm9_src7.vcxproj -> D:\lua502\lua\Release\gm9_src7.dll + Manifest: + C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe /nologo /verbose /outputresource:"D:\lua502\lua\Release\gm9_src7.dll;#2" /manifest Release\gm9_src7.dll.intermediate.manifest + FinalizeBuildStatus: + Deleting file "Release\gm9_src7.unsuccessfulbuild". + Touching "Release\gm9_src7.lastbuildstate". + 1>Done Building Project "D:\lua502\lua\gm9_src7\gm9_src7.vcxproj" (build target(s)). + +ПоÑтроение уÑпешно завершено. + +Time Elapsed 00:00:02.83 diff --git a/lua/gm9_src7/Release/gm9_src7.vcxprojResolveAssemblyReference.cache b/lua/gm9_src7/Release/gm9_src7.vcxprojResolveAssemblyReference.cache new file mode 100644 index 0000000..3f01681 Binary files /dev/null and b/lua/gm9_src7/Release/gm9_src7.vcxprojResolveAssemblyReference.cache differ diff --git a/lua/gm9_src7/Release/gm9_src7.write.1.tlog b/lua/gm9_src7/Release/gm9_src7.write.1.tlog new file mode 100644 index 0000000..c2c1f54 --- /dev/null +++ b/lua/gm9_src7/Release/gm9_src7.write.1.tlog @@ -0,0 +1,40 @@ +^D:\lua502\lua\gm9_src7\gm9_src7.vcxproj +D:\lua502\lua\Release\gm9_src7.lib +D:\lua502\lua\Release\gm9_src7.lib +D:\lua502\lua\Release\gm9_src7.exp +D:\lua502\lua\Release\gm9_src7.exp +^D:\lua502\lua\gm9_src7\gm9_src7.vcxproj +D:\lua502\lua\Release\gm9_src7.lib +D:\lua502\lua\Release\gm9_src7.lib +D:\lua502\lua\Release\gm9_src7.exp +D:\lua502\lua\Release\gm9_src7.exp +^D:\lua502\lua\gm9_src7\gm9_src7.vcxproj +D:\lua502\lua\Release\gm9_src7.lib +D:\lua502\lua\Release\gm9_src7.lib +D:\lua502\lua\Release\gm9_src7.exp +D:\lua502\lua\Release\gm9_src7.exp +^D:\lua502\lua\gm9_src7\gm9_src7.vcxproj +D:\lua502\lua\Release\gm9_src7.lib +D:\lua502\lua\Release\gm9_src7.lib +D:\lua502\lua\Release\gm9_src7.exp +D:\lua502\lua\Release\gm9_src7.exp +^D:\lua502\lua\gm9_src7\gm9_src7.vcxproj +D:\lua502\lua\Release\gm9_src7.lib +D:\lua502\lua\Release\gm9_src7.lib +D:\lua502\lua\Release\gm9_src7.exp +D:\lua502\lua\Release\gm9_src7.exp +^D:\lua502\lua\gm9_src7\gm9_src7.vcxproj +D:\lua502\lua\Release\gm9_src7.lib +D:\lua502\lua\Release\gm9_src7.lib +D:\lua502\lua\Release\gm9_src7.exp +D:\lua502\lua\Release\gm9_src7.exp +^D:\lua502\lua\gm9_src7\gm9_src7.vcxproj +D:\lua502\lua\Release\gm9_src7.lib +D:\lua502\lua\Release\gm9_src7.lib +D:\lua502\lua\Release\gm9_src7.exp +D:\lua502\lua\Release\gm9_src7.exp +^D:\lua502\lua\gm9_src7\gm9_src7.vcxproj +D:\lua502\lua\Release\gm9_src7.lib +D:\lua502\lua\Release\gm9_src7.lib +D:\lua502\lua\Release\gm9_src7.exp +D:\lua502\lua\Release\gm9_src7.exp diff --git a/lua/gm9_src7/Release/link.command.1.tlog b/lua/gm9_src7/Release/link.command.1.tlog new file mode 100644 index 0000000..96d10c6 Binary files /dev/null and b/lua/gm9_src7/Release/link.command.1.tlog differ diff --git a/lua/gm9_src7/Release/link.read.1.tlog b/lua/gm9_src7/Release/link.read.1.tlog new file mode 100644 index 0000000..9450a7b Binary files /dev/null and b/lua/gm9_src7/Release/link.read.1.tlog differ diff --git a/lua/gm9_src7/Release/link.write.1.tlog b/lua/gm9_src7/Release/link.write.1.tlog new file mode 100644 index 0000000..f0939d8 Binary files /dev/null and b/lua/gm9_src7/Release/link.write.1.tlog differ diff --git a/lua/gm9_src7/Release/main.obj b/lua/gm9_src7/Release/main.obj new file mode 100644 index 0000000..6c31c3f Binary files /dev/null and b/lua/gm9_src7/Release/main.obj differ diff --git a/lua/gm9_src7/Release/mt.command.1.tlog b/lua/gm9_src7/Release/mt.command.1.tlog new file mode 100644 index 0000000..7e4dd53 Binary files /dev/null and b/lua/gm9_src7/Release/mt.command.1.tlog differ diff --git a/lua/gm9_src7/Release/mt.read.1.tlog b/lua/gm9_src7/Release/mt.read.1.tlog new file mode 100644 index 0000000..a545780 Binary files /dev/null and b/lua/gm9_src7/Release/mt.read.1.tlog differ diff --git a/lua/gm9_src7/Release/mt.write.1.tlog b/lua/gm9_src7/Release/mt.write.1.tlog new file mode 100644 index 0000000..a5a8f1a Binary files /dev/null and b/lua/gm9_src7/Release/mt.write.1.tlog differ diff --git a/lua/gm9_src7/Release/vc100.pdb b/lua/gm9_src7/Release/vc100.pdb new file mode 100644 index 0000000..b2dcb2f Binary files /dev/null and b/lua/gm9_src7/Release/vc100.pdb differ diff --git a/lua/gm9_src7/gm9_src7.vcxproj b/lua/gm9_src7/gm9_src7.vcxproj new file mode 100644 index 0000000..cf59ab4 --- /dev/null +++ b/lua/gm9_src7/gm9_src7.vcxproj @@ -0,0 +1,72 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {D7D3053C-20B3-4398-ABE8-4F6181293795} + gm9_src7 + + + + Application + true + MultiByte + + + DynamicLibrary + false + true + MultiByte + + + + + + + + + + + + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + true + true + D:\source2006\public\tier1;D:\source2006\public\tier0;D:\source2006\public;D:\source2006\cl_dll;D:\source2006\game_shared;D:\source2006\common;%(AdditionalIncludeDirectories) + + + true + true + true + D:\source2006\lib\public;%(AdditionalLibraryDirectories) + tier0.lib;tier1.lib;%(AdditionalDependencies) + LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) + + + + + + + + + \ No newline at end of file diff --git a/lua/gm9_src7/gm9_src7.vcxproj.filters b/lua/gm9_src7/gm9_src7.vcxproj.filters new file mode 100644 index 0000000..1aa6936 --- /dev/null +++ b/lua/gm9_src7/gm9_src7.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Файлы иÑходного кода + + + \ No newline at end of file diff --git a/lua/gm9_src7/gm9_src7.vcxproj.user b/lua/gm9_src7/gm9_src7.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/lua/gm9_src7/gm9_src7.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lua/gm9_src7/main.cpp b/lua/gm9_src7/main.cpp new file mode 100644 index 0000000..ab3e065 --- /dev/null +++ b/lua/gm9_src7/main.cpp @@ -0,0 +1,30 @@ +#include +#include "tier1/interface.h" +#include "filesystem.h" + +IFileSystem* filesystem = NULL; + +DWORD WINAPI StartThread(LPVOID lpArg) +{ + CSysModule* sysFileSystemSteam = NULL,*sysTestApp = NULL; + if(!Sys_LoadInterface("filesystem_steam",FILESYSTEM_INTERFACE_VERSION, + &sysFileSystemSteam,reinterpret_cast(&filesystem))) + { + Warning("filesystem_steam "FILESYSTEM_INTERFACE_VERSION" not found!\n"); + FreeLibraryAndExitThread((HMODULE)lpArg,1); + } + + filesystem->PrintSearchPaths(); + if(!(sysTestApp = filesystem->LoadModule("gm9x_testapp","GAMEBIN",false))) + Warning("Failed loading gm9x_testapp!\n"); + filesystem->UnloadModule(sysTestApp); + FreeLibraryAndExitThread((HMODULE)lpArg,0); + return 0; +} + +BOOL APIENTRY DllMain(HINSTANCE hDll,DWORD fdwReason,LPVOID) +{ + if(fdwReason==DLL_PROCESS_ATTACH) + CreateThread(0,0,StartThread,(LPVOID)hDll,0,0); + return TRUE; +} \ No newline at end of file diff --git a/lua/gm9_workerthread/Release/CL.read.1.tlog b/lua/gm9_workerthread/Release/CL.read.1.tlog new file mode 100644 index 0000000..c666560 Binary files /dev/null and b/lua/gm9_workerthread/Release/CL.read.1.tlog differ diff --git a/lua/gm9_workerthread/Release/CL.write.1.tlog b/lua/gm9_workerthread/Release/CL.write.1.tlog new file mode 100644 index 0000000..01ab2f2 Binary files /dev/null and b/lua/gm9_workerthread/Release/CL.write.1.tlog differ diff --git a/lua/gm9_workerthread/Release/cl.command.1.tlog b/lua/gm9_workerthread/Release/cl.command.1.tlog new file mode 100644 index 0000000..f6e2e41 Binary files /dev/null and b/lua/gm9_workerthread/Release/cl.command.1.tlog differ diff --git a/lua/gm9_workerthread/Release/gm9_workerthread.dll.intermediate.manifest b/lua/gm9_workerthread/Release/gm9_workerthread.dll.intermediate.manifest new file mode 100644 index 0000000..ecea6f7 --- /dev/null +++ b/lua/gm9_workerthread/Release/gm9_workerthread.dll.intermediate.manifest @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/lua/gm9_workerthread/Release/gm9_workerthread.lastbuildstate b/lua/gm9_workerthread/Release/gm9_workerthread.lastbuildstate new file mode 100644 index 0000000..c2d4a05 --- /dev/null +++ b/lua/gm9_workerthread/Release/gm9_workerthread.lastbuildstate @@ -0,0 +1,2 @@ +#v4.0:v100:false +Release|Win32|D:\lua502\lua\| diff --git a/lua/gm9_workerthread/Release/gm9_workerthread.log b/lua/gm9_workerthread/Release/gm9_workerthread.log new file mode 100644 index 0000000..678d46b --- /dev/null +++ b/lua/gm9_workerthread/Release/gm9_workerthread.log @@ -0,0 +1,23 @@ +Build started 06.06.2018 18:58:02. + 1>Project "D:\lua502\lua\gm9_workerthread\gm9_workerthread.vcxproj" on node 2 (build target(s)). + 1>InitializeBuildStatus: + Creating "Release\gm9_workerthread.unsuccessfulbuild" because "AlwaysCreate" was specified. + ClCompile: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\CL.exe /c /ID:\source2006\common /ID:\source2006\public\tier1 /ID:\source2006\public\tier0 /ID:\source2006\public /ID:\source2006\ /Zi /nologo /W3 /WX- /O2 /Oi /Oy- /GL /D _WINDLL /D _MBCS /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Release\\" /Fd"Release\vc100.pdb" /Gd /TP /analyze- /errorReport:prompt main.cpp + main.cpp + Link: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:"D:\lua502\lua\Release\gm9_workerthread.dll" /NOLOGO /LIBPATH:D:\source2006\lib\public vstdlib.lib tier0.lib tier1.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NODEFAULTLIB:LIBCMT.lib /MANIFEST /ManifestFile:"Release\gm9_workerthread.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"D:\lua502\lua\Release\gm9_workerthread.pdb" /OPT:REF /OPT:ICF /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"D:\lua502\lua\Release\gm9_workerthread.lib" /MACHINE:X86 /DLL Release\main.obj + СоздаетÑÑ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ° D:\lua502\lua\Release\gm9_workerthread.lib и объект D:\lua502\lua\Release\gm9_workerthread.exp + Создание кода + Создание кода завершено + gm9_workerthread.vcxproj -> D:\lua502\lua\Release\gm9_workerthread.dll + Manifest: + C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe /nologo /verbose /outputresource:"D:\lua502\lua\Release\gm9_workerthread.dll;#2" /manifest Release\gm9_workerthread.dll.intermediate.manifest + FinalizeBuildStatus: + Deleting file "Release\gm9_workerthread.unsuccessfulbuild". + Touching "Release\gm9_workerthread.lastbuildstate". + 1>Done Building Project "D:\lua502\lua\gm9_workerthread\gm9_workerthread.vcxproj" (build target(s)). + +ПоÑтроение уÑпешно завершено. + +Time Elapsed 00:00:00.95 diff --git a/lua/gm9_workerthread/Release/gm9_workerthread.vcxprojResolveAssemblyReference.cache b/lua/gm9_workerthread/Release/gm9_workerthread.vcxprojResolveAssemblyReference.cache new file mode 100644 index 0000000..3f01681 Binary files /dev/null and b/lua/gm9_workerthread/Release/gm9_workerthread.vcxprojResolveAssemblyReference.cache differ diff --git a/lua/gm9_workerthread/Release/gm9_workerthread.write.1.tlog b/lua/gm9_workerthread/Release/gm9_workerthread.write.1.tlog new file mode 100644 index 0000000..85b07df --- /dev/null +++ b/lua/gm9_workerthread/Release/gm9_workerthread.write.1.tlog @@ -0,0 +1,5 @@ +^D:\lua502\lua\gm9_workerthread\gm9_workerthread.vcxproj +D:\lua502\lua\Release\gm9_workerthread.lib +D:\lua502\lua\Release\gm9_workerthread.lib +D:\lua502\lua\Release\gm9_workerthread.exp +D:\lua502\lua\Release\gm9_workerthread.exp diff --git a/lua/gm9_workerthread/Release/link.command.1.tlog b/lua/gm9_workerthread/Release/link.command.1.tlog new file mode 100644 index 0000000..7958c1f Binary files /dev/null and b/lua/gm9_workerthread/Release/link.command.1.tlog differ diff --git a/lua/gm9_workerthread/Release/link.read.1.tlog b/lua/gm9_workerthread/Release/link.read.1.tlog new file mode 100644 index 0000000..a4e2479 Binary files /dev/null and b/lua/gm9_workerthread/Release/link.read.1.tlog differ diff --git a/lua/gm9_workerthread/Release/link.write.1.tlog b/lua/gm9_workerthread/Release/link.write.1.tlog new file mode 100644 index 0000000..a5062c5 Binary files /dev/null and b/lua/gm9_workerthread/Release/link.write.1.tlog differ diff --git a/lua/gm9_workerthread/Release/main.obj b/lua/gm9_workerthread/Release/main.obj new file mode 100644 index 0000000..046f61a Binary files /dev/null and b/lua/gm9_workerthread/Release/main.obj differ diff --git a/lua/gm9_workerthread/Release/mt.command.1.tlog b/lua/gm9_workerthread/Release/mt.command.1.tlog new file mode 100644 index 0000000..caa57dd Binary files /dev/null and b/lua/gm9_workerthread/Release/mt.command.1.tlog differ diff --git a/lua/gm9_workerthread/Release/mt.read.1.tlog b/lua/gm9_workerthread/Release/mt.read.1.tlog new file mode 100644 index 0000000..211e3d2 Binary files /dev/null and b/lua/gm9_workerthread/Release/mt.read.1.tlog differ diff --git a/lua/gm9_workerthread/Release/mt.write.1.tlog b/lua/gm9_workerthread/Release/mt.write.1.tlog new file mode 100644 index 0000000..d7b7b24 Binary files /dev/null and b/lua/gm9_workerthread/Release/mt.write.1.tlog differ diff --git a/lua/gm9_workerthread/Release/vc100.pdb b/lua/gm9_workerthread/Release/vc100.pdb new file mode 100644 index 0000000..c1fc471 Binary files /dev/null and b/lua/gm9_workerthread/Release/vc100.pdb differ diff --git a/lua/gm9_workerthread/gm9_workerthread.vcxproj b/lua/gm9_workerthread/gm9_workerthread.vcxproj new file mode 100644 index 0000000..98c61c1 --- /dev/null +++ b/lua/gm9_workerthread/gm9_workerthread.vcxproj @@ -0,0 +1,72 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {CA0093A7-1AE9-4DD4-8C16-CFAB258C2AE0} + gm9_workerthread + + + + Application + true + MultiByte + + + DynamicLibrary + false + true + MultiByte + + + + + + + + + + + + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + true + true + D:\source2006\common;D:\source2006\public\tier1;D:\source2006\public\tier0;D:\source2006\public;D:\source2006\;%(AdditionalIncludeDirectories) + + + true + true + true + D:\source2006\lib\public;%(AdditionalLibraryDirectories) + vstdlib.lib;tier0.lib;tier1.lib;%(AdditionalDependencies) + LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) + + + + + + + + + \ No newline at end of file diff --git a/lua/gm9_workerthread/gm9_workerthread.vcxproj.filters b/lua/gm9_workerthread/gm9_workerthread.vcxproj.filters new file mode 100644 index 0000000..1aa6936 --- /dev/null +++ b/lua/gm9_workerthread/gm9_workerthread.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Файлы иÑходного кода + + + \ No newline at end of file diff --git a/lua/gm9_workerthread/gm9_workerthread.vcxproj.user b/lua/gm9_workerthread/gm9_workerthread.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/lua/gm9_workerthread/gm9_workerthread.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lua/gm9_workerthread/main.cpp b/lua/gm9_workerthread/main.cpp new file mode 100644 index 0000000..f9c2fd4 --- /dev/null +++ b/lua/gm9_workerthread/main.cpp @@ -0,0 +1,99 @@ +#include +#include "threadtools.h" +#include "tier1.h" +#include "dbg.h" +#include + +void PrintDebug(const char* fmt,...) +{ + char szBuf[512] = {0}; + va_list ap; + va_start(ap,fmt); + + vsnprintf(szBuf,512,fmt,ap); + va_end(ap); + + Msg("%s",szBuf); + OutputDebugString(szBuf); +} + +class CMyWorker : public CWorkerThread +{ +public: + CMyWorker() : CWorkerThread() + { + SetName("MyWorker"); + } + + enum { + CALL_FUNC, + EXIT + }; + + void AddRequest(int param) + { + m_iParam = param; + CallWorker(CALL_FUNC); + } + + int Run() + { + unsigned nCall; + while(WaitForCall(&nCall)) + { + if(nCall == EXIT) + { + Reply(1); + break; + } + + int iparam = m_iParam; + m_iParam = 0; + Reply(1); + PrintDebug("Work %d from %d\n",iparam,GetCurrentThreadId()); + } + return 0; + } + + int m_iParam; +} g_MyWorker; + +class CMyThread : public CThread +{ +public: + CMyThread() : CThread() + { + SetName("MyThread"); + } + + int Run() + { + PrintDebug("MyThread works!!!"); + return 0; + } +} g_MyThread; + +ICvar* g_pCvar = NULL; + +CON_COMMAND(thread_start,"") +{ + PrintDebug("This thread %d\n",GetCurrentThreadId()); + g_MyWorker.Start(); + g_MyThread.Start(); + for(int i = 0; i < 5; i++) + g_MyWorker.AddRequest(i); +} + +void Main() +{ + CreateInterfaceFn EngineFn = Sys_GetFactory("engine.dll"); + g_pCvar = (ICvar*)EngineFn(VENGINE_CVAR_INTERFACE_VERSION,0); + g_pCvar->RegisterConCommandBase(&thread_start_command); +} + +BOOL APIENTRY DllMain(HINSTANCE,DWORD fdw,LPVOID) +{ + if(fdw==DLL_PROCESS_ATTACH) + Main(); + return TRUE; +} \ No newline at end of file diff --git a/lua/gm9x_testapp/Release/CL.read.1.tlog b/lua/gm9x_testapp/Release/CL.read.1.tlog new file mode 100644 index 0000000..54972fa Binary files /dev/null and b/lua/gm9x_testapp/Release/CL.read.1.tlog differ diff --git a/lua/gm9x_testapp/Release/CL.write.1.tlog b/lua/gm9x_testapp/Release/CL.write.1.tlog new file mode 100644 index 0000000..30707c7 Binary files /dev/null and b/lua/gm9x_testapp/Release/CL.write.1.tlog differ diff --git a/lua/gm9x_testapp/Release/cl.command.1.tlog b/lua/gm9x_testapp/Release/cl.command.1.tlog new file mode 100644 index 0000000..a89d373 Binary files /dev/null and b/lua/gm9x_testapp/Release/cl.command.1.tlog differ diff --git a/lua/gm9x_testapp/Release/gm9x_testapp.dll.intermediate.manifest b/lua/gm9x_testapp/Release/gm9x_testapp.dll.intermediate.manifest new file mode 100644 index 0000000..ecea6f7 --- /dev/null +++ b/lua/gm9x_testapp/Release/gm9x_testapp.dll.intermediate.manifest @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/lua/gm9x_testapp/Release/gm9x_testapp.lastbuildstate b/lua/gm9x_testapp/Release/gm9x_testapp.lastbuildstate new file mode 100644 index 0000000..c2d4a05 --- /dev/null +++ b/lua/gm9x_testapp/Release/gm9x_testapp.lastbuildstate @@ -0,0 +1,2 @@ +#v4.0:v100:false +Release|Win32|D:\lua502\lua\| diff --git a/lua/gm9x_testapp/Release/gm9x_testapp.log b/lua/gm9x_testapp/Release/gm9x_testapp.log new file mode 100644 index 0000000..ffceee6 --- /dev/null +++ b/lua/gm9x_testapp/Release/gm9x_testapp.log @@ -0,0 +1,23 @@ +Build started 19.09.2017 0:41:52. + 1>Project "D:\lua502\lua\gm9x_testapp\gm9x_testapp.vcxproj" on node 2 (build target(s)). + 1>InitializeBuildStatus: + Creating "Release\gm9x_testapp.unsuccessfulbuild" because "AlwaysCreate" was specified. + ClCompile: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\CL.exe /c /Zi /nologo /W3 /WX- /O2 /Oi /Oy- /GL /D _WINDLL /D _MBCS /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Release\\" /Fd"Release\vc100.pdb" /Gd /TP /analyze- /errorReport:prompt main.cpp + main.cpp + Link: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:"D:\lua502\lua\Release\gm9x_testapp.dll" /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /MANIFEST /ManifestFile:"Release\gm9x_testapp.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"D:\lua502\lua\Release\gm9x_testapp.pdb" /OPT:REF /OPT:ICF /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"D:\lua502\lua\Release\gm9x_testapp.lib" /MACHINE:X86 /DLL Release\main.obj + СоздаетÑÑ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ° D:\lua502\lua\Release\gm9x_testapp.lib и объект D:\lua502\lua\Release\gm9x_testapp.exp + Создание кода + Создание кода завершено + gm9x_testapp.vcxproj -> D:\lua502\lua\Release\gm9x_testapp.dll + Manifest: + C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe /nologo /verbose /outputresource:"D:\lua502\lua\Release\gm9x_testapp.dll;#2" /manifest Release\gm9x_testapp.dll.intermediate.manifest + FinalizeBuildStatus: + Deleting file "Release\gm9x_testapp.unsuccessfulbuild". + Touching "Release\gm9x_testapp.lastbuildstate". + 1>Done Building Project "D:\lua502\lua\gm9x_testapp\gm9x_testapp.vcxproj" (build target(s)). + +ПоÑтроение уÑпешно завершено. + +Time Elapsed 00:00:02.32 diff --git a/lua/gm9x_testapp/Release/gm9x_testapp.write.1.tlog b/lua/gm9x_testapp/Release/gm9x_testapp.write.1.tlog new file mode 100644 index 0000000..56ccdba --- /dev/null +++ b/lua/gm9x_testapp/Release/gm9x_testapp.write.1.tlog @@ -0,0 +1,5 @@ +^D:\lua502\lua\gm9x_testapp\gm9x_testapp.vcxproj +D:\lua502\lua\Release\gm9x_testapp.lib +D:\lua502\lua\Release\gm9x_testapp.lib +D:\lua502\lua\Release\gm9x_testapp.exp +D:\lua502\lua\Release\gm9x_testapp.exp diff --git a/lua/gm9x_testapp/Release/link.command.1.tlog b/lua/gm9x_testapp/Release/link.command.1.tlog new file mode 100644 index 0000000..2d70e08 Binary files /dev/null and b/lua/gm9x_testapp/Release/link.command.1.tlog differ diff --git a/lua/gm9x_testapp/Release/link.read.1.tlog b/lua/gm9x_testapp/Release/link.read.1.tlog new file mode 100644 index 0000000..ccffbab Binary files /dev/null and b/lua/gm9x_testapp/Release/link.read.1.tlog differ diff --git a/lua/gm9x_testapp/Release/link.write.1.tlog b/lua/gm9x_testapp/Release/link.write.1.tlog new file mode 100644 index 0000000..0c5e6f9 Binary files /dev/null and b/lua/gm9x_testapp/Release/link.write.1.tlog differ diff --git a/lua/gm9x_testapp/Release/main.obj b/lua/gm9x_testapp/Release/main.obj new file mode 100644 index 0000000..3f3c126 Binary files /dev/null and b/lua/gm9x_testapp/Release/main.obj differ diff --git a/lua/gm9x_testapp/Release/mt.command.1.tlog b/lua/gm9x_testapp/Release/mt.command.1.tlog new file mode 100644 index 0000000..3787da3 Binary files /dev/null and b/lua/gm9x_testapp/Release/mt.command.1.tlog differ diff --git a/lua/gm9x_testapp/Release/mt.read.1.tlog b/lua/gm9x_testapp/Release/mt.read.1.tlog new file mode 100644 index 0000000..7df69af Binary files /dev/null and b/lua/gm9x_testapp/Release/mt.read.1.tlog differ diff --git a/lua/gm9x_testapp/Release/mt.write.1.tlog b/lua/gm9x_testapp/Release/mt.write.1.tlog new file mode 100644 index 0000000..4b227b1 Binary files /dev/null and b/lua/gm9x_testapp/Release/mt.write.1.tlog differ diff --git a/lua/gm9x_testapp/Release/vc100.pdb b/lua/gm9x_testapp/Release/vc100.pdb new file mode 100644 index 0000000..bde12ac Binary files /dev/null and b/lua/gm9x_testapp/Release/vc100.pdb differ diff --git a/lua/gm9x_testapp/gm9x_testapp.vcxproj b/lua/gm9x_testapp/gm9x_testapp.vcxproj new file mode 100644 index 0000000..42249d5 --- /dev/null +++ b/lua/gm9x_testapp/gm9x_testapp.vcxproj @@ -0,0 +1,68 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {D4315B06-CB8B-4B66-B0FF-EF78148F1EEF} + gm9x_testapp + + + + Application + true + MultiByte + + + DynamicLibrary + false + true + MultiByte + + + + + + + + + + + + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + true + true + + + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/lua/gm9x_testapp/gm9x_testapp.vcxproj.filters b/lua/gm9x_testapp/gm9x_testapp.vcxproj.filters new file mode 100644 index 0000000..1aa6936 --- /dev/null +++ b/lua/gm9x_testapp/gm9x_testapp.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Файлы иÑходного кода + + + \ No newline at end of file diff --git a/lua/gm9x_testapp/gm9x_testapp.vcxproj.user b/lua/gm9x_testapp/gm9x_testapp.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/lua/gm9x_testapp/gm9x_testapp.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lua/gm9x_testapp/main.cpp b/lua/gm9x_testapp/main.cpp new file mode 100644 index 0000000..9d8c900 --- /dev/null +++ b/lua/gm9x_testapp/main.cpp @@ -0,0 +1,12 @@ +#include + +extern "C" __declspec(dllexport) void* CreateInterface(const char*,int*) +{ + return NULL; +} + +BOOL APIENTRY DllMain(HINSTANCE,DWORD fdwReason,LPVOID) +{ + if(fdwReason==DLL_PROCESS_ATTACH) + MessageBoxA(NULL,"Loaded!","gm9x_testapp",MB_OK); +} \ No newline at end of file diff --git a/lua/gmod9_masterfix/gmod9_masterfix.vcxproj b/lua/gmod9_masterfix/gmod9_masterfix.vcxproj new file mode 100644 index 0000000..0d3ae8d --- /dev/null +++ b/lua/gmod9_masterfix/gmod9_masterfix.vcxproj @@ -0,0 +1,67 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {1249F177-C3AE-4130-8EEC-DBBA2EC84FC6} + gmod9_masterfix + + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + true + true + + + true + true + true + + + + + + + + \ No newline at end of file diff --git a/lua/gmod9_masterfix/gmod9_masterfix.vcxproj.filters b/lua/gmod9_masterfix/gmod9_masterfix.vcxproj.filters new file mode 100644 index 0000000..a967230 --- /dev/null +++ b/lua/gmod9_masterfix/gmod9_masterfix.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + \ No newline at end of file diff --git a/lua/gmod9_masterfix/gmod9_masterfix.vcxproj.user b/lua/gmod9_masterfix/gmod9_masterfix.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/lua/gmod9_masterfix/gmod9_masterfix.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lua/ipch/gm9_interface-eea82f64/gm9_interface-12929c83.ipch b/lua/ipch/gm9_interface-eea82f64/gm9_interface-12929c83.ipch new file mode 100644 index 0000000..c2c73bb Binary files /dev/null and b/lua/ipch/gm9_interface-eea82f64/gm9_interface-12929c83.ipch differ diff --git a/lua/ipch/gm9_internal-c10c741c/gm9_internal-70a9b58f.ipch b/lua/ipch/gm9_internal-c10c741c/gm9_internal-70a9b58f.ipch new file mode 100644 index 0000000..4394650 Binary files /dev/null and b/lua/ipch/gm9_internal-c10c741c/gm9_internal-70a9b58f.ipch differ diff --git a/lua/ipch/gm9_src7-bde3c8a0/gm9_src7-df7c2871.ipch b/lua/ipch/gm9_src7-bde3c8a0/gm9_src7-df7c2871.ipch new file mode 100644 index 0000000..cb679d1 Binary files /dev/null and b/lua/ipch/gm9_src7-bde3c8a0/gm9_src7-df7c2871.ipch differ diff --git a/lua/ipch/gm9_workerthread-44c7a166/gm9_workerthread-a853a2a4.ipch b/lua/ipch/gm9_workerthread-44c7a166/gm9_workerthread-a853a2a4.ipch new file mode 100644 index 0000000..e6710c6 Binary files /dev/null and b/lua/ipch/gm9_workerthread-44c7a166/gm9_workerthread-a853a2a4.ipch differ diff --git a/lua/ipch/gm9x_testapp-79a0cd54/gm9x_testapp-9ce0416b.ipch b/lua/ipch/gm9x_testapp-79a0cd54/gm9x_testapp-9ce0416b.ipch new file mode 100644 index 0000000..7d040fc Binary files /dev/null and b/lua/ipch/gm9x_testapp-79a0cd54/gm9x_testapp-9ce0416b.ipch differ diff --git a/lua/ipch/lua502-7ac7043c/lua502-b97861bf.ipch b/lua/ipch/lua502-7ac7043c/lua502-b97861bf.ipch new file mode 100644 index 0000000..59c9950 Binary files /dev/null and b/lua/ipch/lua502-7ac7043c/lua502-b97861bf.ipch differ diff --git a/lua/ipch/lua502_sdk-b4f0701e/lua502_sdk-c07033c0.ipch b/lua/ipch/lua502_sdk-b4f0701e/lua502_sdk-c07033c0.ipch new file mode 100644 index 0000000..842117f Binary files /dev/null and b/lua/ipch/lua502_sdk-b4f0701e/lua502_sdk-c07033c0.ipch differ diff --git a/lua/ipch/sdk_http-dacdd4c/sdk_http-e381fd67.ipch b/lua/ipch/sdk_http-dacdd4c/sdk_http-e381fd67.ipch new file mode 100644 index 0000000..f14de98 Binary files /dev/null and b/lua/ipch/sdk_http-dacdd4c/sdk_http-e381fd67.ipch differ diff --git a/lua/lcore/Debug/CL.read.1.tlog b/lua/lcore/Debug/CL.read.1.tlog new file mode 100644 index 0000000..61569ce Binary files /dev/null and b/lua/lcore/Debug/CL.read.1.tlog differ diff --git a/lua/lcore/Debug/CL.write.1.tlog b/lua/lcore/Debug/CL.write.1.tlog new file mode 100644 index 0000000..6e6a3e9 Binary files /dev/null and b/lua/lcore/Debug/CL.write.1.tlog differ diff --git a/lua/lcore/Debug/Lib-link.read.1.tlog b/lua/lcore/Debug/Lib-link.read.1.tlog new file mode 100644 index 0000000..46b134b --- /dev/null +++ b/lua/lcore/Debug/Lib-link.read.1.tlog @@ -0,0 +1 @@ +ÿþ \ No newline at end of file diff --git a/lua/lcore/Debug/Lib-link.write.1.tlog b/lua/lcore/Debug/Lib-link.write.1.tlog new file mode 100644 index 0000000..46b134b --- /dev/null +++ b/lua/lcore/Debug/Lib-link.write.1.tlog @@ -0,0 +1 @@ +ÿþ \ No newline at end of file diff --git a/lua/lcore/Debug/Lib.read.1.tlog b/lua/lcore/Debug/Lib.read.1.tlog new file mode 100644 index 0000000..d9e0fcd Binary files /dev/null and b/lua/lcore/Debug/Lib.read.1.tlog differ diff --git a/lua/lcore/Debug/Lib.write.1.tlog b/lua/lcore/Debug/Lib.write.1.tlog new file mode 100644 index 0000000..4430d64 Binary files /dev/null and b/lua/lcore/Debug/Lib.write.1.tlog differ diff --git a/lua/lcore/Debug/cl.command.1.tlog b/lua/lcore/Debug/cl.command.1.tlog new file mode 100644 index 0000000..0e859a4 Binary files /dev/null and b/lua/lcore/Debug/cl.command.1.tlog differ diff --git a/lua/lcore/Debug/lapi.obj b/lua/lcore/Debug/lapi.obj new file mode 100644 index 0000000..eac6377 Binary files /dev/null and b/lua/lcore/Debug/lapi.obj differ diff --git a/lua/lcore/Debug/lcode.obj b/lua/lcore/Debug/lcode.obj new file mode 100644 index 0000000..ec9921a Binary files /dev/null and b/lua/lcore/Debug/lcode.obj differ diff --git a/lua/lcore/Debug/lcore.lastbuildstate b/lua/lcore/Debug/lcore.lastbuildstate new file mode 100644 index 0000000..50c7376 --- /dev/null +++ b/lua/lcore/Debug/lcore.lastbuildstate @@ -0,0 +1,2 @@ +#v4.0:v100:false +Debug|Win32|D:\lua502\lua\| diff --git a/lua/lcore/Debug/lcore.log b/lua/lcore/Debug/lcore.log new file mode 100644 index 0000000..3303616 --- /dev/null +++ b/lua/lcore/Debug/lcore.log @@ -0,0 +1,79 @@ +Build started 15.09.2017 0:11:08. + 1>Project "D:\lua502\lua\lcore\lcore.vcxproj" on node 2 (build target(s)). + 1>PrepareForBuild: + Creating directory "D:\lua502\lua\Debug\". + InitializeBuildStatus: + Creating "Debug\lcore.unsuccessfulbuild" because "AlwaysCreate" was specified. + ClCompile: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\CL.exe /c /ID:\lua502\include\ /ID:\lua502\src\ /ZI /nologo /W3 /WX- /Od /Oy- /D _MBCS /Gm /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Debug\\" /Fd"Debug\vc100.pdb" /Gd /TC /analyze- /errorReport:prompt ..\..\src\lapi.c ..\..\src\lcode.c ..\..\src\ldebug.c ..\..\src\ldo.c ..\..\src\ldump.c ..\..\src\lfunc.c ..\..\src\lgc.c ..\..\src\llex.c ..\..\src\lmem.c ..\..\src\lobject.c ..\..\src\lopcodes.c ..\..\src\lparser.c ..\..\src\lstate.c ..\..\src\lstring.c ..\..\src\ltable.c ..\..\src\ltests.c ..\..\src\ltm.c ..\..\src\lundump.c ..\..\src\lvm.c ..\..\src\lzio.c + lzio.c + lvm.c + 1>d:\lua502\src\lvm.c(60): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. + c:\program files (x86)\microsoft visual studio 10.0\vc\include\stdio.h(371): Ñм. объÑвление "sprintf" + lundump.c + ltm.c + ltests.c + ltable.c + lstring.c + lstate.c + lparser.c + lopcodes.c + lobject.c + 1>d:\lua502\src\lobject.c(165): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. + c:\program files (x86)\microsoft visual studio 10.0\vc\include\string.h(188): Ñм. объÑвление "strncpy" + 1>d:\lua502\src\lobject.c(174): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. + c:\program files (x86)\microsoft visual studio 10.0\vc\include\string.h(105): Ñм. объÑвление "strcpy" + 1>d:\lua502\src\lobject.c(177): warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. + c:\program files (x86)\microsoft visual studio 10.0\vc\include\string.h(110): Ñм. объÑвление "strcat" + 1>d:\lua502\src\lobject.c(179): warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. + c:\program files (x86)\microsoft visual studio 10.0\vc\include\string.h(110): Ñм. объÑвление "strcat" + 1>d:\lua502\src\lobject.c(185): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. + c:\program files (x86)\microsoft visual studio 10.0\vc\include\string.h(105): Ñм. объÑвление "strcpy" + 1>d:\lua502\src\lobject.c(187): warning C4996: 'strncat': This function or variable may be unsafe. Consider using strncat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. + c:\program files (x86)\microsoft visual studio 10.0\vc\include\string.h(175): Ñм. объÑвление "strncat" + 1>d:\lua502\src\lobject.c(188): warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. + c:\program files (x86)\microsoft visual studio 10.0\vc\include\string.h(110): Ñм. объÑвление "strcat" + 1>d:\lua502\src\lobject.c(191): warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. + c:\program files (x86)\microsoft visual studio 10.0\vc\include\string.h(110): Ñм. объÑвление "strcat" + 1>d:\lua502\src\lobject.c(192): warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. + c:\program files (x86)\microsoft visual studio 10.0\vc\include\string.h(110): Ñм. объÑвление "strcat" + lmem.c + llex.c + lgc.c + lfunc.c + ldump.c + ldo.c + ldebug.c + lcode.c + lapi.c + Создание кода... + Lib: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\Lib.exe /OUT:"D:\lua502\lua\Debug\lcore.lib" /NOLOGO Debug\lapi.obj + Debug\lcode.obj + Debug\ldebug.obj + Debug\ldo.obj + Debug\ldump.obj + Debug\lfunc.obj + Debug\lgc.obj + Debug\llex.obj + Debug\lmem.obj + Debug\lobject.obj + Debug\lopcodes.obj + Debug\lparser.obj + Debug\lstate.obj + Debug\lstring.obj + Debug\ltable.obj + Debug\ltests.obj + Debug\ltm.obj + Debug\lundump.obj + Debug\lvm.obj + Debug\lzio.obj + lcore.vcxproj -> D:\lua502\lua\Debug\lcore.lib + FinalizeBuildStatus: + Deleting file "Debug\lcore.unsuccessfulbuild". + Touching "Debug\lcore.lastbuildstate". + 1>Done Building Project "D:\lua502\lua\lcore\lcore.vcxproj" (build target(s)). + +ПоÑтроение уÑпешно завершено. + +Time Elapsed 00:00:05.23 diff --git a/lua/lcore/Debug/lcore.vcxprojResolveAssemblyReference.cache b/lua/lcore/Debug/lcore.vcxprojResolveAssemblyReference.cache new file mode 100644 index 0000000..3f01681 Binary files /dev/null and b/lua/lcore/Debug/lcore.vcxprojResolveAssemblyReference.cache differ diff --git a/lua/lcore/Debug/lcore.write.1.tlog b/lua/lcore/Debug/lcore.write.1.tlog new file mode 100644 index 0000000..e69de29 diff --git a/lua/lcore/Debug/ldebug.obj b/lua/lcore/Debug/ldebug.obj new file mode 100644 index 0000000..53cd0f3 Binary files /dev/null and b/lua/lcore/Debug/ldebug.obj differ diff --git a/lua/lcore/Debug/ldo.obj b/lua/lcore/Debug/ldo.obj new file mode 100644 index 0000000..307aa98 Binary files /dev/null and b/lua/lcore/Debug/ldo.obj differ diff --git a/lua/lcore/Debug/ldump.obj b/lua/lcore/Debug/ldump.obj new file mode 100644 index 0000000..d0b0b2c Binary files /dev/null and b/lua/lcore/Debug/ldump.obj differ diff --git a/lua/lcore/Debug/lfunc.obj b/lua/lcore/Debug/lfunc.obj new file mode 100644 index 0000000..a6ab19b Binary files /dev/null and b/lua/lcore/Debug/lfunc.obj differ diff --git a/lua/lcore/Debug/lgc.obj b/lua/lcore/Debug/lgc.obj new file mode 100644 index 0000000..1c20542 Binary files /dev/null and b/lua/lcore/Debug/lgc.obj differ diff --git a/lua/lcore/Debug/lib.command.1.tlog b/lua/lcore/Debug/lib.command.1.tlog new file mode 100644 index 0000000..a06d848 Binary files /dev/null and b/lua/lcore/Debug/lib.command.1.tlog differ diff --git a/lua/lcore/Debug/llex.obj b/lua/lcore/Debug/llex.obj new file mode 100644 index 0000000..2d36afd Binary files /dev/null and b/lua/lcore/Debug/llex.obj differ diff --git a/lua/lcore/Debug/lmem.obj b/lua/lcore/Debug/lmem.obj new file mode 100644 index 0000000..a937b16 Binary files /dev/null and b/lua/lcore/Debug/lmem.obj differ diff --git a/lua/lcore/Debug/lobject.obj b/lua/lcore/Debug/lobject.obj new file mode 100644 index 0000000..dc673bd Binary files /dev/null and b/lua/lcore/Debug/lobject.obj differ diff --git a/lua/lcore/Debug/lopcodes.obj b/lua/lcore/Debug/lopcodes.obj new file mode 100644 index 0000000..7600eac Binary files /dev/null and b/lua/lcore/Debug/lopcodes.obj differ diff --git a/lua/lcore/Debug/lparser.obj b/lua/lcore/Debug/lparser.obj new file mode 100644 index 0000000..e9b7a7f Binary files /dev/null and b/lua/lcore/Debug/lparser.obj differ diff --git a/lua/lcore/Debug/lstate.obj b/lua/lcore/Debug/lstate.obj new file mode 100644 index 0000000..5b375ad Binary files /dev/null and b/lua/lcore/Debug/lstate.obj differ diff --git a/lua/lcore/Debug/lstring.obj b/lua/lcore/Debug/lstring.obj new file mode 100644 index 0000000..6346552 Binary files /dev/null and b/lua/lcore/Debug/lstring.obj differ diff --git a/lua/lcore/Debug/ltable.obj b/lua/lcore/Debug/ltable.obj new file mode 100644 index 0000000..ae63b40 Binary files /dev/null and b/lua/lcore/Debug/ltable.obj differ diff --git a/lua/lcore/Debug/ltests.obj b/lua/lcore/Debug/ltests.obj new file mode 100644 index 0000000..ada9199 Binary files /dev/null and b/lua/lcore/Debug/ltests.obj differ diff --git a/lua/lcore/Debug/ltm.obj b/lua/lcore/Debug/ltm.obj new file mode 100644 index 0000000..5d19153 Binary files /dev/null and b/lua/lcore/Debug/ltm.obj differ diff --git a/lua/lcore/Debug/lundump.obj b/lua/lcore/Debug/lundump.obj new file mode 100644 index 0000000..b565eb2 Binary files /dev/null and b/lua/lcore/Debug/lundump.obj differ diff --git a/lua/lcore/Debug/lvm.obj b/lua/lcore/Debug/lvm.obj new file mode 100644 index 0000000..5ed24f6 Binary files /dev/null and b/lua/lcore/Debug/lvm.obj differ diff --git a/lua/lcore/Debug/lzio.obj b/lua/lcore/Debug/lzio.obj new file mode 100644 index 0000000..4e075bd Binary files /dev/null and b/lua/lcore/Debug/lzio.obj differ diff --git a/lua/lcore/Debug/vc100.idb b/lua/lcore/Debug/vc100.idb new file mode 100644 index 0000000..fc0f1c2 Binary files /dev/null and b/lua/lcore/Debug/vc100.idb differ diff --git a/lua/lcore/Debug/vc100.pdb b/lua/lcore/Debug/vc100.pdb new file mode 100644 index 0000000..ef5738f Binary files /dev/null and b/lua/lcore/Debug/vc100.pdb differ diff --git a/lua/lcore/Release/CL.read.1.tlog b/lua/lcore/Release/CL.read.1.tlog new file mode 100644 index 0000000..c6791e8 Binary files /dev/null and b/lua/lcore/Release/CL.read.1.tlog differ diff --git a/lua/lcore/Release/CL.write.1.tlog b/lua/lcore/Release/CL.write.1.tlog new file mode 100644 index 0000000..c081ba2 Binary files /dev/null and b/lua/lcore/Release/CL.write.1.tlog differ diff --git a/lua/lcore/Release/Lib-link.read.1.tlog b/lua/lcore/Release/Lib-link.read.1.tlog new file mode 100644 index 0000000..46b134b --- /dev/null +++ b/lua/lcore/Release/Lib-link.read.1.tlog @@ -0,0 +1 @@ +ÿþ \ No newline at end of file diff --git a/lua/lcore/Release/Lib-link.write.1.tlog b/lua/lcore/Release/Lib-link.write.1.tlog new file mode 100644 index 0000000..46b134b --- /dev/null +++ b/lua/lcore/Release/Lib-link.write.1.tlog @@ -0,0 +1 @@ +ÿþ \ No newline at end of file diff --git a/lua/lcore/Release/Lib.read.1.tlog b/lua/lcore/Release/Lib.read.1.tlog new file mode 100644 index 0000000..3f696fa Binary files /dev/null and b/lua/lcore/Release/Lib.read.1.tlog differ diff --git a/lua/lcore/Release/Lib.write.1.tlog b/lua/lcore/Release/Lib.write.1.tlog new file mode 100644 index 0000000..3dcb902 Binary files /dev/null and b/lua/lcore/Release/Lib.write.1.tlog differ diff --git a/lua/lcore/Release/cl.command.1.tlog b/lua/lcore/Release/cl.command.1.tlog new file mode 100644 index 0000000..fd3e41c Binary files /dev/null and b/lua/lcore/Release/cl.command.1.tlog differ diff --git a/lua/lcore/Release/lapi.obj b/lua/lcore/Release/lapi.obj new file mode 100644 index 0000000..bd51a9c Binary files /dev/null and b/lua/lcore/Release/lapi.obj differ diff --git a/lua/lcore/Release/lauxlib.obj b/lua/lcore/Release/lauxlib.obj new file mode 100644 index 0000000..230f3aa Binary files /dev/null and b/lua/lcore/Release/lauxlib.obj differ diff --git a/lua/lcore/Release/lcode.obj b/lua/lcore/Release/lcode.obj new file mode 100644 index 0000000..070f5f4 Binary files /dev/null and b/lua/lcore/Release/lcode.obj differ diff --git a/lua/lcore/Release/lcore.lastbuildstate b/lua/lcore/Release/lcore.lastbuildstate new file mode 100644 index 0000000..c2d4a05 --- /dev/null +++ b/lua/lcore/Release/lcore.lastbuildstate @@ -0,0 +1,2 @@ +#v4.0:v100:false +Release|Win32|D:\lua502\lua\| diff --git a/lua/lcore/Release/lcore.log b/lua/lcore/Release/lcore.log new file mode 100644 index 0000000..dab9e06 --- /dev/null +++ b/lua/lcore/Release/lcore.log @@ -0,0 +1,44 @@ +Build started 15.09.2017 0:36:14. + 1>Project "D:\lua502\lua\lcore\lcore.vcxproj" on node 2 (build target(s)). + 1>InitializeBuildStatus: + Creating "Release\lcore.unsuccessfulbuild" because "AlwaysCreate" was specified. + ClCompile: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\CL.exe /c /ID:\lua502\include\ /ID:\lua502\src\ /Zi /nologo /W3 /WX- /O2 /Oi /Oy- /GL /D _MBCS /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Release\\" /Fd"Release\vc100.pdb" /Gd /TC /analyze- /errorReport:prompt ..\..\src\lib\lauxlib.c + lauxlib.c + 1>..\..\src\lib\lauxlib.c(480): warning C4996: 'strerror': This function or variable may be unsafe. Consider using strerror_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(157): Ñм. объÑвление "strerror" + 1>..\..\src\lib\lauxlib.c(497): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(234): Ñм. объÑвление "fopen" + 1>..\..\src\lib\lauxlib.c(503): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(234): Ñм. объÑвление "fopen" + Lib: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\Lib.exe /OUT:"D:\lua502\lua\Release\lcore.lib" /NOLOGO /LTCG Release\lapi.obj + Release\lcode.obj + Release\ldebug.obj + Release\ldo.obj + Release\ldump.obj + Release\lfunc.obj + Release\lgc.obj + Release\lauxlib.obj + Release\llex.obj + Release\lmem.obj + Release\lobject.obj + Release\lopcodes.obj + Release\lparser.obj + Release\lstate.obj + Release\lstring.obj + Release\ltable.obj + Release\ltests.obj + Release\ltm.obj + Release\lundump.obj + Release\lvm.obj + Release\lzio.obj + lcore.vcxproj -> D:\lua502\lua\Release\lcore.lib + FinalizeBuildStatus: + Deleting file "Release\lcore.unsuccessfulbuild". + Touching "Release\lcore.lastbuildstate". + 1>Done Building Project "D:\lua502\lua\lcore\lcore.vcxproj" (build target(s)). + +ПоÑтроение уÑпешно завершено. + +Time Elapsed 00:00:01.08 diff --git a/lua/lcore/Release/lcore.write.1.tlog b/lua/lcore/Release/lcore.write.1.tlog new file mode 100644 index 0000000..e69de29 diff --git a/lua/lcore/Release/ldebug.obj b/lua/lcore/Release/ldebug.obj new file mode 100644 index 0000000..3c88956 Binary files /dev/null and b/lua/lcore/Release/ldebug.obj differ diff --git a/lua/lcore/Release/ldo.obj b/lua/lcore/Release/ldo.obj new file mode 100644 index 0000000..65f31aa Binary files /dev/null and b/lua/lcore/Release/ldo.obj differ diff --git a/lua/lcore/Release/ldump.obj b/lua/lcore/Release/ldump.obj new file mode 100644 index 0000000..6ada817 Binary files /dev/null and b/lua/lcore/Release/ldump.obj differ diff --git a/lua/lcore/Release/lfunc.obj b/lua/lcore/Release/lfunc.obj new file mode 100644 index 0000000..843e76e Binary files /dev/null and b/lua/lcore/Release/lfunc.obj differ diff --git a/lua/lcore/Release/lgc.obj b/lua/lcore/Release/lgc.obj new file mode 100644 index 0000000..73150f2 Binary files /dev/null and b/lua/lcore/Release/lgc.obj differ diff --git a/lua/lcore/Release/lib.command.1.tlog b/lua/lcore/Release/lib.command.1.tlog new file mode 100644 index 0000000..72cb2b7 Binary files /dev/null and b/lua/lcore/Release/lib.command.1.tlog differ diff --git a/lua/lcore/Release/llex.obj b/lua/lcore/Release/llex.obj new file mode 100644 index 0000000..7306269 Binary files /dev/null and b/lua/lcore/Release/llex.obj differ diff --git a/lua/lcore/Release/lmem.obj b/lua/lcore/Release/lmem.obj new file mode 100644 index 0000000..98e67b4 Binary files /dev/null and b/lua/lcore/Release/lmem.obj differ diff --git a/lua/lcore/Release/lobject.obj b/lua/lcore/Release/lobject.obj new file mode 100644 index 0000000..6e4f376 Binary files /dev/null and b/lua/lcore/Release/lobject.obj differ diff --git a/lua/lcore/Release/lopcodes.obj b/lua/lcore/Release/lopcodes.obj new file mode 100644 index 0000000..ca0de3d Binary files /dev/null and b/lua/lcore/Release/lopcodes.obj differ diff --git a/lua/lcore/Release/lparser.obj b/lua/lcore/Release/lparser.obj new file mode 100644 index 0000000..b9d1a1b Binary files /dev/null and b/lua/lcore/Release/lparser.obj differ diff --git a/lua/lcore/Release/lstate.obj b/lua/lcore/Release/lstate.obj new file mode 100644 index 0000000..26d0f65 Binary files /dev/null and b/lua/lcore/Release/lstate.obj differ diff --git a/lua/lcore/Release/lstring.obj b/lua/lcore/Release/lstring.obj new file mode 100644 index 0000000..9d34221 Binary files /dev/null and b/lua/lcore/Release/lstring.obj differ diff --git a/lua/lcore/Release/ltable.obj b/lua/lcore/Release/ltable.obj new file mode 100644 index 0000000..0dd7a52 Binary files /dev/null and b/lua/lcore/Release/ltable.obj differ diff --git a/lua/lcore/Release/ltests.obj b/lua/lcore/Release/ltests.obj new file mode 100644 index 0000000..87d8dd0 Binary files /dev/null and b/lua/lcore/Release/ltests.obj differ diff --git a/lua/lcore/Release/ltm.obj b/lua/lcore/Release/ltm.obj new file mode 100644 index 0000000..f7522f9 Binary files /dev/null and b/lua/lcore/Release/ltm.obj differ diff --git a/lua/lcore/Release/lundump.obj b/lua/lcore/Release/lundump.obj new file mode 100644 index 0000000..78def68 Binary files /dev/null and b/lua/lcore/Release/lundump.obj differ diff --git a/lua/lcore/Release/lvm.obj b/lua/lcore/Release/lvm.obj new file mode 100644 index 0000000..39340dc Binary files /dev/null and b/lua/lcore/Release/lvm.obj differ diff --git a/lua/lcore/Release/lzio.obj b/lua/lcore/Release/lzio.obj new file mode 100644 index 0000000..9375660 Binary files /dev/null and b/lua/lcore/Release/lzio.obj differ diff --git a/lua/lcore/Release/vc100.pdb b/lua/lcore/Release/vc100.pdb new file mode 100644 index 0000000..773d238 Binary files /dev/null and b/lua/lcore/Release/vc100.pdb differ diff --git a/lua/lcore/lcore.vcxproj b/lua/lcore/lcore.vcxproj new file mode 100644 index 0000000..9830566 --- /dev/null +++ b/lua/lcore/lcore.vcxproj @@ -0,0 +1,67 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {BFCD74EE-6A73-4328-BDD8-99ACF14EA689} + lcore + + + + StaticLibrary + true + MultiByte + + + StaticLibrary + false + true + MultiByte + + + + + + + + + + + + + + + Level3 + Disabled + D:\lua502\include\;D:\lua502\src\;%(AdditionalIncludeDirectories) + + + true + + + + + Level3 + MaxSpeed + true + true + D:\lua502\include\;D:\lua502\src\;%(AdditionalIncludeDirectories) + + + true + true + true + + + + + + \ No newline at end of file diff --git a/lua/lcore/lcore.vcxproj.filters b/lua/lcore/lcore.vcxproj.filters new file mode 100644 index 0000000..6dc1d0b --- /dev/null +++ b/lua/lcore/lcore.vcxproj.filters @@ -0,0 +1,20 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {cc436ecf-f5bc-4bce-856b-374e7d3f610a} + + + \ No newline at end of file diff --git a/lua/lcore/lcore.vcxproj.user b/lua/lcore/lcore.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/lua/lcore/lcore.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lua/ltest/Release/CL.read.1.tlog b/lua/ltest/Release/CL.read.1.tlog new file mode 100644 index 0000000..ea29027 Binary files /dev/null and b/lua/ltest/Release/CL.read.1.tlog differ diff --git a/lua/ltest/Release/CL.write.1.tlog b/lua/ltest/Release/CL.write.1.tlog new file mode 100644 index 0000000..2d5cc94 Binary files /dev/null and b/lua/ltest/Release/CL.write.1.tlog differ diff --git a/lua/ltest/Release/cl.command.1.tlog b/lua/ltest/Release/cl.command.1.tlog new file mode 100644 index 0000000..d8c1e7c Binary files /dev/null and b/lua/ltest/Release/cl.command.1.tlog differ diff --git a/lua/ltest/Release/link.command.1.tlog b/lua/ltest/Release/link.command.1.tlog new file mode 100644 index 0000000..4753637 Binary files /dev/null and b/lua/ltest/Release/link.command.1.tlog differ diff --git a/lua/ltest/Release/link.read.1.tlog b/lua/ltest/Release/link.read.1.tlog new file mode 100644 index 0000000..4403711 Binary files /dev/null and b/lua/ltest/Release/link.read.1.tlog differ diff --git a/lua/ltest/Release/link.write.1.tlog b/lua/ltest/Release/link.write.1.tlog new file mode 100644 index 0000000..1f1b087 Binary files /dev/null and b/lua/ltest/Release/link.write.1.tlog differ diff --git a/lua/ltest/Release/ltest.exe.intermediate.manifest b/lua/ltest/Release/ltest.exe.intermediate.manifest new file mode 100644 index 0000000..ecea6f7 --- /dev/null +++ b/lua/ltest/Release/ltest.exe.intermediate.manifest @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/lua/ltest/Release/ltest.lastbuildstate b/lua/ltest/Release/ltest.lastbuildstate new file mode 100644 index 0000000..c2d4a05 --- /dev/null +++ b/lua/ltest/Release/ltest.lastbuildstate @@ -0,0 +1,2 @@ +#v4.0:v100:false +Release|Win32|D:\lua502\lua\| diff --git a/lua/ltest/Release/ltest.log b/lua/ltest/Release/ltest.log new file mode 100644 index 0000000..ca50e86 --- /dev/null +++ b/lua/ltest/Release/ltest.log @@ -0,0 +1,26 @@ +Build started 04.10.2017 23:30:44. + 1>Project "D:\lua502\lua\ltest\ltest.vcxproj" on node 2 (build target(s)). + 1>InitializeBuildStatus: + Creating "Release\ltest.unsuccessfulbuild" because "AlwaysCreate" was specified. + ClCompile: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\CL.exe /c /ID:\lua502\src /ID:\lua502\include /Zi /nologo /W3 /WX- /O2 /Oi /Oy- /GL /D _MBCS /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Release\\" /Fd"Release\vc100.pdb" /Gd /TP /analyze- /errorReport:prompt main.cpp + main.cpp + 1>main.cpp(23): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371): Ñм. объÑвление "sprintf" + 1>main.cpp(28): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(105): Ñм. объÑвление "strcpy" + Link: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:"D:\lua502\lua\Release\ltest.exe" /NOLOGO /LIBPATH:D:\lua502\lua\Release lcore.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /MANIFEST /ManifestFile:"Release\ltest.exe.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"D:\lua502\lua\Release\ltest.pdb" /OPT:REF /OPT:ICF /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"D:\lua502\lua\Release\ltest.lib" /MACHINE:X86 Release\main.obj + Создание кода + Создание кода завершено + ltest.vcxproj -> D:\lua502\lua\Release\ltest.exe + Manifest: + C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe /nologo /verbose /outputresource:"D:\lua502\lua\Release\ltest.exe;#1" /manifest Release\ltest.exe.intermediate.manifest + FinalizeBuildStatus: + Deleting file "Release\ltest.unsuccessfulbuild". + Touching "Release\ltest.lastbuildstate". + 1>Done Building Project "D:\lua502\lua\ltest\ltest.vcxproj" (build target(s)). + +ПоÑтроение уÑпешно завершено. + +Time Elapsed 00:00:05.29 diff --git a/lua/ltest/Release/ltest.write.1.tlog b/lua/ltest/Release/ltest.write.1.tlog new file mode 100644 index 0000000..e69de29 diff --git a/lua/ltest/Release/main.obj b/lua/ltest/Release/main.obj new file mode 100644 index 0000000..4d61409 Binary files /dev/null and b/lua/ltest/Release/main.obj differ diff --git a/lua/ltest/Release/mt.command.1.tlog b/lua/ltest/Release/mt.command.1.tlog new file mode 100644 index 0000000..2582855 Binary files /dev/null and b/lua/ltest/Release/mt.command.1.tlog differ diff --git a/lua/ltest/Release/mt.read.1.tlog b/lua/ltest/Release/mt.read.1.tlog new file mode 100644 index 0000000..c9c3393 Binary files /dev/null and b/lua/ltest/Release/mt.read.1.tlog differ diff --git a/lua/ltest/Release/mt.write.1.tlog b/lua/ltest/Release/mt.write.1.tlog new file mode 100644 index 0000000..157aaf2 Binary files /dev/null and b/lua/ltest/Release/mt.write.1.tlog differ diff --git a/lua/ltest/Release/vc100.pdb b/lua/ltest/Release/vc100.pdb new file mode 100644 index 0000000..19c65ab Binary files /dev/null and b/lua/ltest/Release/vc100.pdb differ diff --git a/lua/ltest/ltest.vcxproj b/lua/ltest/ltest.vcxproj new file mode 100644 index 0000000..01ad096 --- /dev/null +++ b/lua/ltest/ltest.vcxproj @@ -0,0 +1,71 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {A2BA37A3-EFB3-4E6F-B8C5-3FA4F6883A4E} + ltest + + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + true + true + D:\lua502\src;D:\lua502\include;%(AdditionalIncludeDirectories) + + + true + true + true + D:\lua502\lua\Release;%(AdditionalLibraryDirectories) + lcore.lib;%(AdditionalDependencies) + + + + + + + + + \ No newline at end of file diff --git a/lua/ltest/ltest.vcxproj.filters b/lua/ltest/ltest.vcxproj.filters new file mode 100644 index 0000000..1aa6936 --- /dev/null +++ b/lua/ltest/ltest.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Файлы иÑходного кода + + + \ No newline at end of file diff --git a/lua/ltest/ltest.vcxproj.user b/lua/ltest/ltest.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/lua/ltest/ltest.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lua/ltest/main.cpp b/lua/ltest/main.cpp new file mode 100644 index 0000000..f1a1e7f --- /dev/null +++ b/lua/ltest/main.cpp @@ -0,0 +1,121 @@ +#include +#include +#include +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" + +int lua502_err(lua_State* L) +{ + puts(lua_tostring(L,1)); + return 0; +} + +void lua502f_tostr(lua_State* L,int idx,char* szBuf) +{ + int iType; + + iType = lua_type(L,idx); + if(iType == LUA_TTABLE || iType == LUA_TUSERDATA + || iType == LUA_TTHREAD || iType == LUA_TLIGHTUSERDATA) + { + sprintf(szBuf,"%s %p",lua_typename(L,iType), + lua_topointer(L,idx)); + } + else + { + const char* pStr = lua_tostring(L,idx); + strcpy(szBuf,pStr?pStr:"(null)"); + } +} + +int lua502_print(lua_State* L) +{ + char szBuf[64] = {0}; + int iArgs = lua_gettop(L); + if(iArgs>1) + { + for(int i = 1; i <= iArgs; i++) + { + *szBuf = 0; + lua502f_tostr(L,i,szBuf); + printf("%s\t",szBuf); + } + putc('\n',stdout); + } else if(iArgs) + { + lua502f_tostr(L,1,szBuf); + printf("%s\n",lua_tostring(L,1)); + } + return 0; +} + +void lua502f_dumpstack(lua_State* L) +{ + static int s_iStep = 0; + + int iTop = lua_gettop(L); + char szName[32]; + + printf("== DUMP STACK %d ==\n",++s_iStep); + for(int i = 1; i <= iTop; i++) + { + *szName = 0; + lua502f_tostr(L,i,szName); + printf("%d: %s\n",i,szName); + } +} + +int lua502_test(lua_State* L) +{ + lua_pushliteral(L,"metatest"); + lua_newtable(L); + + lua502f_dumpstack(L); + + lua_pushliteral(L,"n"); + lua_pushnumber(L,3); + + lua502f_dumpstack(L); + + lua_settable(L,-3); + + lua502f_dumpstack(L); + + lua_settable(L,LUA_REGISTRYINDEX); + lua502f_dumpstack(L); + return 0; +} + +int main() +{ + lua_State* L; + char szBuffer[256] = {0}; + int iErrHandler; + + L = lua_open(); + lua_register(L,"test",lua502_test); + lua_register(L,"print",lua502_print); + + lua_pushvalue(L,LUA_GLOBALSINDEX); + lua_setglobal(L,"_G"); + + lua_pushvalue(L,LUA_REGISTRYINDEX); + lua_setglobal(L,"_R"); + + while(putc('>',stdout) && gets_s<256>(szBuffer)) + { + lua_pushcfunction(L,lua502_err); + if(luaL_loadbuffer(L,szBuffer,strlen(szBuffer),"promt")) + puts(lua_tostring(L,-1)); + else + { + iErrHandler = lua_gettop(L); + lua_pcall(L,0,LUA_MULTRET,iErrHandler-1); + } + lua_pop(L,1); + } + + lua_close(L); + return 0; +} \ No newline at end of file diff --git a/lua/lua.sdf b/lua/lua.sdf new file mode 100644 index 0000000..92233fa Binary files /dev/null and b/lua/lua.sdf differ diff --git a/lua/lua.sln b/lua/lua.sln new file mode 100644 index 0000000..2bd14be --- /dev/null +++ b/lua/lua.sln @@ -0,0 +1,146 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lcore", "lcore\lcore.vcxproj", "{BFCD74EE-6A73-4328-BDD8-99ACF14EA689}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gm9_internal", "gm9_internal\gm9_internal.vcxproj", "{C845B13A-C336-4529-8D3A-3B5CB9353830}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gm9_interface", "gm9_interface\gm9_interface.vcxproj", "{6F268CBD-9B5A-4260-BFC1-74A657370DAA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lua502", "lua502\lua502.vcxproj", "{C78BB0F3-3952-4F64-8DF7-2C0D16A6D03A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gm9_fsdump", "gm9_fsdump\gm9_fsdump.vcxproj", "{A183C6DC-B05F-40AC-B0DC-E1F8794F633D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gm9x_testapp", "gm9x_testapp\gm9x_testapp.vcxproj", "{D4315B06-CB8B-4B66-B0FF-EF78148F1EEF}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gm9_src7", "gm9_src7\gm9_src7.vcxproj", "{D7D3053C-20B3-4398-ABE8-4F6181293795}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "502_test", "502_test\502_test.vcxproj", "{4F4C4E60-2C90-44D8-AA4A-B01874B76A5B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lzss", "lzss\lzss.vcxproj", "{9FB2DA35-0043-485E-83F6-A2E6B36F94C0}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gm9_cvar", "gm9_cvar\gm9_cvar.vcxproj", "{AF48898D-1A3F-4E38-BC13-584E61CD0074}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ltest", "ltest\ltest.vcxproj", "{A2BA37A3-EFB3-4E6F-B8C5-3FA4F6883A4E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "502_plugin", "502_plugin\502_plugin.vcxproj", "{7159FC3C-3F14-4884-B97F-C2D80765A104}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lua502_sdk", "lua502_sdk\lua502_sdk.vcxproj", "{F71BDA01-BDD1-4EE4-85A4-FAD463C5AAED}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sdk_fixes", "sdk_fixes\sdk_fixes.vcxproj", "{B02E949C-9ADA-4A7E-ACFE-0016D3C22CC3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rw1132", "rw1132\rw1132.vcxproj", "{0D841775-B6B5-4F7D-9A8F-5CCBAC5323AD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "a2s_rules", "a2s_rules\a2s_rules.vcxproj", "{A80D0688-8E8C-46CE-ABB9-110F7076CC13}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sdk_ppcore", "sdk_ppcore\sdk_ppcore.vcxproj", "{40CB1037-BD7E-45A4-AB78-33C5E981893C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sv_a2s_fix", "sv_a2s_fix\sv_a2s_fix.vcxproj", "{9063DF3A-3CCF-497C-916F-E44CC01DE942}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "masterfix", "masterfix\masterfix.vcxproj", "{ED522CA8-61C9-470A-8E8D-C3D477DEC1A1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sdk_http", "sdk_http\sdk_http.vcxproj", "{0590CDBB-7088-4957-8FD9-64F6473041A4}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gm9_workerthread", "gm9_workerthread\gm9_workerthread.vcxproj", "{CA0093A7-1AE9-4DD4-8C16-CFAB258C2AE0}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sdk_net", "sdk_net\sdk_net.vcxproj", "{D39138E1-F689-4256-B237-33F989464123}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BFCD74EE-6A73-4328-BDD8-99ACF14EA689}.Debug|Win32.ActiveCfg = Debug|Win32 + {BFCD74EE-6A73-4328-BDD8-99ACF14EA689}.Debug|Win32.Build.0 = Debug|Win32 + {BFCD74EE-6A73-4328-BDD8-99ACF14EA689}.Release|Win32.ActiveCfg = Release|Win32 + {BFCD74EE-6A73-4328-BDD8-99ACF14EA689}.Release|Win32.Build.0 = Release|Win32 + {C845B13A-C336-4529-8D3A-3B5CB9353830}.Debug|Win32.ActiveCfg = Debug|Win32 + {C845B13A-C336-4529-8D3A-3B5CB9353830}.Debug|Win32.Build.0 = Debug|Win32 + {C845B13A-C336-4529-8D3A-3B5CB9353830}.Release|Win32.ActiveCfg = Release|Win32 + {C845B13A-C336-4529-8D3A-3B5CB9353830}.Release|Win32.Build.0 = Release|Win32 + {6F268CBD-9B5A-4260-BFC1-74A657370DAA}.Debug|Win32.ActiveCfg = Debug|Win32 + {6F268CBD-9B5A-4260-BFC1-74A657370DAA}.Debug|Win32.Build.0 = Debug|Win32 + {6F268CBD-9B5A-4260-BFC1-74A657370DAA}.Release|Win32.ActiveCfg = Release|Win32 + {6F268CBD-9B5A-4260-BFC1-74A657370DAA}.Release|Win32.Build.0 = Release|Win32 + {C78BB0F3-3952-4F64-8DF7-2C0D16A6D03A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C78BB0F3-3952-4F64-8DF7-2C0D16A6D03A}.Debug|Win32.Build.0 = Debug|Win32 + {C78BB0F3-3952-4F64-8DF7-2C0D16A6D03A}.Release|Win32.ActiveCfg = Release|Win32 + {C78BB0F3-3952-4F64-8DF7-2C0D16A6D03A}.Release|Win32.Build.0 = Release|Win32 + {A183C6DC-B05F-40AC-B0DC-E1F8794F633D}.Debug|Win32.ActiveCfg = Debug|Win32 + {A183C6DC-B05F-40AC-B0DC-E1F8794F633D}.Debug|Win32.Build.0 = Debug|Win32 + {A183C6DC-B05F-40AC-B0DC-E1F8794F633D}.Release|Win32.ActiveCfg = Release|Win32 + {A183C6DC-B05F-40AC-B0DC-E1F8794F633D}.Release|Win32.Build.0 = Release|Win32 + {D4315B06-CB8B-4B66-B0FF-EF78148F1EEF}.Debug|Win32.ActiveCfg = Debug|Win32 + {D4315B06-CB8B-4B66-B0FF-EF78148F1EEF}.Debug|Win32.Build.0 = Debug|Win32 + {D4315B06-CB8B-4B66-B0FF-EF78148F1EEF}.Release|Win32.ActiveCfg = Release|Win32 + {D4315B06-CB8B-4B66-B0FF-EF78148F1EEF}.Release|Win32.Build.0 = Release|Win32 + {D7D3053C-20B3-4398-ABE8-4F6181293795}.Debug|Win32.ActiveCfg = Debug|Win32 + {D7D3053C-20B3-4398-ABE8-4F6181293795}.Debug|Win32.Build.0 = Debug|Win32 + {D7D3053C-20B3-4398-ABE8-4F6181293795}.Release|Win32.ActiveCfg = Release|Win32 + {D7D3053C-20B3-4398-ABE8-4F6181293795}.Release|Win32.Build.0 = Release|Win32 + {4F4C4E60-2C90-44D8-AA4A-B01874B76A5B}.Debug|Win32.ActiveCfg = Debug|Win32 + {4F4C4E60-2C90-44D8-AA4A-B01874B76A5B}.Debug|Win32.Build.0 = Debug|Win32 + {4F4C4E60-2C90-44D8-AA4A-B01874B76A5B}.Release|Win32.ActiveCfg = Release|Win32 + {4F4C4E60-2C90-44D8-AA4A-B01874B76A5B}.Release|Win32.Build.0 = Release|Win32 + {9FB2DA35-0043-485E-83F6-A2E6B36F94C0}.Debug|Win32.ActiveCfg = Debug|Win32 + {9FB2DA35-0043-485E-83F6-A2E6B36F94C0}.Debug|Win32.Build.0 = Debug|Win32 + {9FB2DA35-0043-485E-83F6-A2E6B36F94C0}.Release|Win32.ActiveCfg = Release|Win32 + {9FB2DA35-0043-485E-83F6-A2E6B36F94C0}.Release|Win32.Build.0 = Release|Win32 + {AF48898D-1A3F-4E38-BC13-584E61CD0074}.Debug|Win32.ActiveCfg = Debug|Win32 + {AF48898D-1A3F-4E38-BC13-584E61CD0074}.Debug|Win32.Build.0 = Debug|Win32 + {AF48898D-1A3F-4E38-BC13-584E61CD0074}.Release|Win32.ActiveCfg = Release|Win32 + {AF48898D-1A3F-4E38-BC13-584E61CD0074}.Release|Win32.Build.0 = Release|Win32 + {A2BA37A3-EFB3-4E6F-B8C5-3FA4F6883A4E}.Debug|Win32.ActiveCfg = Debug|Win32 + {A2BA37A3-EFB3-4E6F-B8C5-3FA4F6883A4E}.Debug|Win32.Build.0 = Debug|Win32 + {A2BA37A3-EFB3-4E6F-B8C5-3FA4F6883A4E}.Release|Win32.ActiveCfg = Release|Win32 + {A2BA37A3-EFB3-4E6F-B8C5-3FA4F6883A4E}.Release|Win32.Build.0 = Release|Win32 + {7159FC3C-3F14-4884-B97F-C2D80765A104}.Debug|Win32.ActiveCfg = Debug|Win32 + {7159FC3C-3F14-4884-B97F-C2D80765A104}.Debug|Win32.Build.0 = Debug|Win32 + {7159FC3C-3F14-4884-B97F-C2D80765A104}.Release|Win32.ActiveCfg = Release|Win32 + {7159FC3C-3F14-4884-B97F-C2D80765A104}.Release|Win32.Build.0 = Release|Win32 + {F71BDA01-BDD1-4EE4-85A4-FAD463C5AAED}.Debug|Win32.ActiveCfg = Debug|Win32 + {F71BDA01-BDD1-4EE4-85A4-FAD463C5AAED}.Debug|Win32.Build.0 = Debug|Win32 + {F71BDA01-BDD1-4EE4-85A4-FAD463C5AAED}.Release|Win32.ActiveCfg = Release|Win32 + {F71BDA01-BDD1-4EE4-85A4-FAD463C5AAED}.Release|Win32.Build.0 = Release|Win32 + {B02E949C-9ADA-4A7E-ACFE-0016D3C22CC3}.Debug|Win32.ActiveCfg = Debug|Win32 + {B02E949C-9ADA-4A7E-ACFE-0016D3C22CC3}.Debug|Win32.Build.0 = Debug|Win32 + {B02E949C-9ADA-4A7E-ACFE-0016D3C22CC3}.Release|Win32.ActiveCfg = Release|Win32 + {B02E949C-9ADA-4A7E-ACFE-0016D3C22CC3}.Release|Win32.Build.0 = Release|Win32 + {0D841775-B6B5-4F7D-9A8F-5CCBAC5323AD}.Debug|Win32.ActiveCfg = Debug|Win32 + {0D841775-B6B5-4F7D-9A8F-5CCBAC5323AD}.Debug|Win32.Build.0 = Debug|Win32 + {0D841775-B6B5-4F7D-9A8F-5CCBAC5323AD}.Release|Win32.ActiveCfg = Release|Win32 + {0D841775-B6B5-4F7D-9A8F-5CCBAC5323AD}.Release|Win32.Build.0 = Release|Win32 + {A80D0688-8E8C-46CE-ABB9-110F7076CC13}.Debug|Win32.ActiveCfg = Debug|Win32 + {A80D0688-8E8C-46CE-ABB9-110F7076CC13}.Debug|Win32.Build.0 = Debug|Win32 + {A80D0688-8E8C-46CE-ABB9-110F7076CC13}.Release|Win32.ActiveCfg = Release|Win32 + {A80D0688-8E8C-46CE-ABB9-110F7076CC13}.Release|Win32.Build.0 = Release|Win32 + {40CB1037-BD7E-45A4-AB78-33C5E981893C}.Debug|Win32.ActiveCfg = Debug|Win32 + {40CB1037-BD7E-45A4-AB78-33C5E981893C}.Debug|Win32.Build.0 = Debug|Win32 + {40CB1037-BD7E-45A4-AB78-33C5E981893C}.Release|Win32.ActiveCfg = Release|Win32 + {40CB1037-BD7E-45A4-AB78-33C5E981893C}.Release|Win32.Build.0 = Release|Win32 + {9063DF3A-3CCF-497C-916F-E44CC01DE942}.Debug|Win32.ActiveCfg = Debug|Win32 + {9063DF3A-3CCF-497C-916F-E44CC01DE942}.Debug|Win32.Build.0 = Debug|Win32 + {9063DF3A-3CCF-497C-916F-E44CC01DE942}.Release|Win32.ActiveCfg = Release|Win32 + {9063DF3A-3CCF-497C-916F-E44CC01DE942}.Release|Win32.Build.0 = Release|Win32 + {ED522CA8-61C9-470A-8E8D-C3D477DEC1A1}.Debug|Win32.ActiveCfg = Debug|Win32 + {ED522CA8-61C9-470A-8E8D-C3D477DEC1A1}.Debug|Win32.Build.0 = Debug|Win32 + {ED522CA8-61C9-470A-8E8D-C3D477DEC1A1}.Release|Win32.ActiveCfg = Release|Win32 + {ED522CA8-61C9-470A-8E8D-C3D477DEC1A1}.Release|Win32.Build.0 = Release|Win32 + {0590CDBB-7088-4957-8FD9-64F6473041A4}.Debug|Win32.ActiveCfg = Debug|Win32 + {0590CDBB-7088-4957-8FD9-64F6473041A4}.Debug|Win32.Build.0 = Debug|Win32 + {0590CDBB-7088-4957-8FD9-64F6473041A4}.Release|Win32.ActiveCfg = Release|Win32 + {0590CDBB-7088-4957-8FD9-64F6473041A4}.Release|Win32.Build.0 = Release|Win32 + {CA0093A7-1AE9-4DD4-8C16-CFAB258C2AE0}.Debug|Win32.ActiveCfg = Debug|Win32 + {CA0093A7-1AE9-4DD4-8C16-CFAB258C2AE0}.Debug|Win32.Build.0 = Debug|Win32 + {CA0093A7-1AE9-4DD4-8C16-CFAB258C2AE0}.Release|Win32.ActiveCfg = Release|Win32 + {CA0093A7-1AE9-4DD4-8C16-CFAB258C2AE0}.Release|Win32.Build.0 = Release|Win32 + {D39138E1-F689-4256-B237-33F989464123}.Debug|Win32.ActiveCfg = Debug|Win32 + {D39138E1-F689-4256-B237-33F989464123}.Debug|Win32.Build.0 = Debug|Win32 + {D39138E1-F689-4256-B237-33F989464123}.Release|Win32.ActiveCfg = Release|Win32 + {D39138E1-F689-4256-B237-33F989464123}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/lua/lua.suo b/lua/lua.suo new file mode 100644 index 0000000..053c239 Binary files /dev/null and b/lua/lua.suo differ diff --git a/lua/lua.v12.suo b/lua/lua.v12.suo new file mode 100644 index 0000000..e770ead Binary files /dev/null and b/lua/lua.v12.suo differ diff --git a/lua/lua502/Release/CL.read.1.tlog b/lua/lua502/Release/CL.read.1.tlog new file mode 100644 index 0000000..dcde326 Binary files /dev/null and b/lua/lua502/Release/CL.read.1.tlog differ diff --git a/lua/lua502/Release/CL.write.1.tlog b/lua/lua502/Release/CL.write.1.tlog new file mode 100644 index 0000000..6025218 Binary files /dev/null and b/lua/lua502/Release/CL.write.1.tlog differ diff --git a/lua/lua502/Release/baselib.obj b/lua/lua502/Release/baselib.obj new file mode 100644 index 0000000..1b35144 Binary files /dev/null and b/lua/lua502/Release/baselib.obj differ diff --git a/lua/lua502/Release/bitlib.obj b/lua/lua502/Release/bitlib.obj new file mode 100644 index 0000000..579cb00 Binary files /dev/null and b/lua/lua502/Release/bitlib.obj differ diff --git a/lua/lua502/Release/chook.obj b/lua/lua502/Release/chook.obj new file mode 100644 index 0000000..876c260 Binary files /dev/null and b/lua/lua502/Release/chook.obj differ diff --git a/lua/lua502/Release/cl.command.1.tlog b/lua/lua502/Release/cl.command.1.tlog new file mode 100644 index 0000000..e2757fd Binary files /dev/null and b/lua/lua502/Release/cl.command.1.tlog differ diff --git a/lua/lua502/Release/console.obj b/lua/lua502/Release/console.obj new file mode 100644 index 0000000..d7fb5b5 Binary files /dev/null and b/lua/lua502/Release/console.obj differ diff --git a/lua/lua502/Release/cvarlib.obj b/lua/lua502/Release/cvarlib.obj new file mode 100644 index 0000000..b912d2e Binary files /dev/null and b/lua/lua502/Release/cvarlib.obj differ diff --git a/lua/lua502/Release/keyvalues.obj b/lua/lua502/Release/keyvalues.obj new file mode 100644 index 0000000..e6c636f Binary files /dev/null and b/lua/lua502/Release/keyvalues.obj differ diff --git a/lua/lua502/Release/lapi.obj b/lua/lua502/Release/lapi.obj new file mode 100644 index 0000000..e829d9e Binary files /dev/null and b/lua/lua502/Release/lapi.obj differ diff --git a/lua/lua502/Release/lauxlib.obj b/lua/lua502/Release/lauxlib.obj new file mode 100644 index 0000000..1c281fe Binary files /dev/null and b/lua/lua502/Release/lauxlib.obj differ diff --git a/lua/lua502/Release/lcode.obj b/lua/lua502/Release/lcode.obj new file mode 100644 index 0000000..84d0852 Binary files /dev/null and b/lua/lua502/Release/lcode.obj differ diff --git a/lua/lua502/Release/ldebug.obj b/lua/lua502/Release/ldebug.obj new file mode 100644 index 0000000..5ee77c0 Binary files /dev/null and b/lua/lua502/Release/ldebug.obj differ diff --git a/lua/lua502/Release/ldo.obj b/lua/lua502/Release/ldo.obj new file mode 100644 index 0000000..cfaddc0 Binary files /dev/null and b/lua/lua502/Release/ldo.obj differ diff --git a/lua/lua502/Release/ldump.obj b/lua/lua502/Release/ldump.obj new file mode 100644 index 0000000..bdf6b87 Binary files /dev/null and b/lua/lua502/Release/ldump.obj differ diff --git a/lua/lua502/Release/lfunc.obj b/lua/lua502/Release/lfunc.obj new file mode 100644 index 0000000..e759d47 Binary files /dev/null and b/lua/lua502/Release/lfunc.obj differ diff --git a/lua/lua502/Release/lgc.obj b/lua/lua502/Release/lgc.obj new file mode 100644 index 0000000..d87d211 Binary files /dev/null and b/lua/lua502/Release/lgc.obj differ diff --git a/lua/lua502/Release/link.command.1.tlog b/lua/lua502/Release/link.command.1.tlog new file mode 100644 index 0000000..140d793 Binary files /dev/null and b/lua/lua502/Release/link.command.1.tlog differ diff --git a/lua/lua502/Release/link.read.1.tlog b/lua/lua502/Release/link.read.1.tlog new file mode 100644 index 0000000..bd4d329 Binary files /dev/null and b/lua/lua502/Release/link.read.1.tlog differ diff --git a/lua/lua502/Release/link.write.1.tlog b/lua/lua502/Release/link.write.1.tlog new file mode 100644 index 0000000..e2784a0 Binary files /dev/null and b/lua/lua502/Release/link.write.1.tlog differ diff --git a/lua/lua502/Release/llex.obj b/lua/lua502/Release/llex.obj new file mode 100644 index 0000000..c171be0 Binary files /dev/null and b/lua/lua502/Release/llex.obj differ diff --git a/lua/lua502/Release/lmem.obj b/lua/lua502/Release/lmem.obj new file mode 100644 index 0000000..dc5b54c Binary files /dev/null and b/lua/lua502/Release/lmem.obj differ diff --git a/lua/lua502/Release/lobject.obj b/lua/lua502/Release/lobject.obj new file mode 100644 index 0000000..06fa05e Binary files /dev/null and b/lua/lua502/Release/lobject.obj differ diff --git a/lua/lua502/Release/lopcodes.obj b/lua/lua502/Release/lopcodes.obj new file mode 100644 index 0000000..261ed4c Binary files /dev/null and b/lua/lua502/Release/lopcodes.obj differ diff --git a/lua/lua502/Release/lparser.obj b/lua/lua502/Release/lparser.obj new file mode 100644 index 0000000..fce768a Binary files /dev/null and b/lua/lua502/Release/lparser.obj differ diff --git a/lua/lua502/Release/lstate.obj b/lua/lua502/Release/lstate.obj new file mode 100644 index 0000000..3a50bab Binary files /dev/null and b/lua/lua502/Release/lstate.obj differ diff --git a/lua/lua502/Release/lstring.obj b/lua/lua502/Release/lstring.obj new file mode 100644 index 0000000..f2bdbf5 Binary files /dev/null and b/lua/lua502/Release/lstring.obj differ diff --git a/lua/lua502/Release/ltable.obj b/lua/lua502/Release/ltable.obj new file mode 100644 index 0000000..dae4567 Binary files /dev/null and b/lua/lua502/Release/ltable.obj differ diff --git a/lua/lua502/Release/ltests.obj b/lua/lua502/Release/ltests.obj new file mode 100644 index 0000000..5912b49 Binary files /dev/null and b/lua/lua502/Release/ltests.obj differ diff --git a/lua/lua502/Release/ltm.obj b/lua/lua502/Release/ltm.obj new file mode 100644 index 0000000..aafd34a Binary files /dev/null and b/lua/lua502/Release/ltm.obj differ diff --git a/lua/lua502/Release/lua502.Build.CppClean.log b/lua/lua502/Release/lua502.Build.CppClean.log new file mode 100644 index 0000000..72468da --- /dev/null +++ b/lua/lua502/Release/lua502.Build.CppClean.log @@ -0,0 +1,51 @@ +..\..\..\GMod9Dev_Server\gmod9\addons\lua502.pdb +D:\GMOD9DEV_SERVER\GMOD9\ADDONS\LUA502.DLL +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMOD9DEV_SERVER\GMOD9\ADDONS\LUA502.PDB +D:\lua502\lua\lua502\..\..\..\GMod9Dev_Server\gmod9\addons\lua502.dll +D:\LUA502\LUA\LUA502\RELEASE\BASELIB.OBJ +D:\LUA502\LUA\LUA502\RELEASE\CHOOK.OBJ +D:\lua502\lua\lua502\Release\cl.command.1.tlog +D:\lua502\lua\lua502\Release\CL.read.1.tlog +D:\lua502\lua\lua502\Release\CL.write.1.tlog +D:\LUA502\LUA\LUA502\RELEASE\CONSOLE.OBJ +D:\LUA502\LUA\LUA502\RELEASE\CVARLIB.OBJ +D:\LUA502\LUA\LUA502\RELEASE\LAPI.OBJ +D:\LUA502\LUA\LUA502\RELEASE\LAUXLIB.OBJ +D:\LUA502\LUA\LUA502\RELEASE\LCODE.OBJ +D:\LUA502\LUA\LUA502\RELEASE\LDEBUG.OBJ +D:\LUA502\LUA\LUA502\RELEASE\LDO.OBJ +D:\LUA502\LUA\LUA502\RELEASE\LDUMP.OBJ +D:\LUA502\LUA\LUA502\RELEASE\LFUNC.OBJ +D:\LUA502\LUA\LUA502\RELEASE\LGC.OBJ +D:\lua502\lua\lua502\Release\link.command.1.tlog +D:\lua502\lua\lua502\Release\link.read.1.tlog +D:\lua502\lua\lua502\Release\link.write.1.tlog +D:\LUA502\LUA\LUA502\RELEASE\LLEX.OBJ +D:\LUA502\LUA\LUA502\RELEASE\LMEM.OBJ +D:\LUA502\LUA\LUA502\RELEASE\LOBJECT.OBJ +D:\LUA502\LUA\LUA502\RELEASE\LOPCODES.OBJ +D:\LUA502\LUA\LUA502\RELEASE\LPARSER.OBJ +D:\LUA502\LUA\LUA502\RELEASE\LSTATE.OBJ +D:\LUA502\LUA\LUA502\RELEASE\LSTRING.OBJ +D:\LUA502\LUA\LUA502\RELEASE\LTABLE.OBJ +D:\LUA502\LUA\LUA502\RELEASE\LTESTS.OBJ +D:\LUA502\LUA\LUA502\RELEASE\LTM.OBJ +D:\LUA502\LUA\LUA502\RELEASE\LUA502.DLL.INTERMEDIATE.MANIFEST +D:\lua502\lua\lua502\Release\lua502.write.1.tlog +D:\LUA502\LUA\LUA502\RELEASE\LUAFILE.OBJ +D:\LUA502\LUA\LUA502\RELEASE\LUAPOINTER.OBJ +D:\LUA502\LUA\LUA502\RELEASE\LUNDUMP.OBJ +D:\LUA502\LUA\LUA502\RELEASE\LVM.OBJ +D:\LUA502\LUA\LUA502\RELEASE\LZIO.OBJ +D:\LUA502\LUA\LUA502\RELEASE\LZMALIB.OBJ +D:\LUA502\LUA\LUA502\RELEASE\MAINLIB.OBJ +D:\lua502\lua\lua502\Release\mt.command.1.tlog +D:\lua502\lua\lua502\Release\mt.read.1.tlog +D:\lua502\lua\lua502\Release\mt.write.1.tlog +D:\LUA502\LUA\LUA502\RELEASE\PLUGIN.OBJ +D:\LUA502\LUA\LUA502\RELEASE\SIGSCAN.OBJ +D:\LUA502\LUA\LUA502\RELEASE\SVAR.OBJ +D:\LUA502\LUA\LUA502\RELEASE\TYPES.OBJ +D:\LUA502\LUA\LUA502\RELEASE\VC100.PDB diff --git a/lua/lua502/Release/lua502.dll.intermediate.manifest b/lua/lua502/Release/lua502.dll.intermediate.manifest new file mode 100644 index 0000000..ecea6f7 --- /dev/null +++ b/lua/lua502/Release/lua502.dll.intermediate.manifest @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/lua/lua502/Release/lua502.lastbuildstate b/lua/lua502/Release/lua502.lastbuildstate new file mode 100644 index 0000000..c2d4a05 --- /dev/null +++ b/lua/lua502/Release/lua502.lastbuildstate @@ -0,0 +1,2 @@ +#v4.0:v100:false +Release|Win32|D:\lua502\lua\| diff --git a/lua/lua502/Release/lua502.log b/lua/lua502/Release/lua502.log new file mode 100644 index 0000000..f9bb3d4 --- /dev/null +++ b/lua/lua502/Release/lua502.log @@ -0,0 +1,70 @@ +Build started 23.07.2018 16:03:04. + 1>Project "D:\lua502\lua\lua502\lua502.vcxproj" on node 2 (build target(s)). + 1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppBuild.targets(299,5): warning MSB8004: каталог Output заканчиваетÑÑ Ð½Ðµ коÑой чертой. Этот ÑкземплÑÑ€ поÑÑ‚Ñ€Ð¾ÐµÐ½Ð¸Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ‚ коÑую черту, поÑкольку она необходима Ð´Ð»Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ð¾Ð³Ð¾ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð° Output. + 1>InitializeBuildStatus: + Touching "Release\lua502.unsuccessfulbuild". + ClCompile: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\CL.exe /c /ID:\source2006\utils\lzma\ /ID:\source2006\common\lzma /ID:\lua502\src /ID:\lua502\include /ID:\source2006\public\tier1 /ID:\source2006\public\tier0 /ID:\source2006\public /ID:\source2006\cl_dll /ID:\source2006\game_shared /ID:\source2006\common /Zi /nologo /W3 /WX- /O2 /Oi /Oy- /GL /D LUA_DLL /D _WINDLL /D _MBCS /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Release\\" /Fd"Release\vc100.pdb" /Gd /TP /analyze- /errorReport:prompt console.cpp + console.cpp + 1>C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\winnt.h(1140): warning C4005: ARRAYSIZE: изменение Ð¼Ð°ÐºÑ€Ð¾Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ + d:\source2006\public\tier0\commonmacros.h(35): Ñм. предыдущее определение "ARRAYSIZE" + Link: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:"..\..\..\GMod9Dev_Server\gmod9\addons\lua502.dll" /NOLOGO /LIBPATH:D:\source2006\lib\common /LIBPATH:D:\source2006\lib\public vstdlib.lib tier0.lib tier1.lib lzma.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NODEFAULTLIB:LIBCMT.lib /MANIFEST /ManifestFile:"Release\lua502.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"D:\GMod9Dev_Server\gmod9\addons\lua502.pdb" /OPT:REF /OPT:ICF /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"..\..\..\GMod9Dev_Server\gmod9\addons\lua502.lib" /MACHINE:X86 /DLL Release\lapi.obj + Release\lcode.obj + Release\ldebug.obj + Release\ldo.obj + Release\ldump.obj + Release\lfunc.obj + Release\lgc.obj + Release\lauxlib.obj + Release\llex.obj + Release\lmem.obj + Release\lobject.obj + Release\lopcodes.obj + Release\lparser.obj + Release\lstate.obj + Release\lstring.obj + Release\ltable.obj + Release\ltests.obj + Release\ltm.obj + Release\lundump.obj + Release\lvm.obj + Release\lzio.obj + Release\bitlib.obj + Release\chook.obj + Release\console.obj + Release\cvarlib.obj + Release\keyvalues.obj + Release\luafile.obj + Release\baselib.obj + Release\luapointer.obj + Release\lzmalib.obj + Release\mainlib.obj + Release\plugin.obj + Release\sigscan.obj + Release\svar.obj + Release\types.obj /FORCE:MULTIPLE + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: __malloc_crt уже определен в tier1.lib(memoverride.obj); второе определение пропущено + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: _free уже определен в tier1.lib(memoverride.obj); второе определение пропущено + СоздаетÑÑ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ° ..\..\..\GMod9Dev_Server\gmod9\addons\lua502.lib и объект ..\..\..\GMod9Dev_Server\gmod9\addons\lua502.exp + 1>..\..\..\GMod9Dev_Server\gmod9\addons\lua502.dll : warning LNK4088: образ ÑоздаетÑÑ Ð¸Ð·-за параметра /FORCE; образ Ð½ÐµÐ»ÑŒÐ·Ñ Ð·Ð°Ð¿ÑƒÑтить + Создание кода + Создание кода завершено + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: __malloc_crt уже определен в tier1.lib(memoverride.obj); второе определение пропущено + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: _free уже определен в tier1.lib(memoverride.obj); второе определение пропущено + 1>..\..\..\GMod9Dev_Server\gmod9\addons\lua502.dll : warning LNK4088: образ ÑоздаетÑÑ Ð¸Ð·-за параметра /FORCE; образ Ð½ÐµÐ»ÑŒÐ·Ñ Ð·Ð°Ð¿ÑƒÑтить + lua502.vcxproj -> D:\lua502\lua\lua502\..\..\..\GMod9Dev_Server\gmod9\addons\lua502.dll + Manifest: + C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe /nologo /verbose /outputresource:"..\..\..\GMod9Dev_Server\gmod9\addons\lua502.dll;#2" /manifest Release\lua502.dll.intermediate.manifest + PostBuildEvent: + copy "..\..\..\GMod9Dev_Server\gmod9\addons\lua502.lib" "..\Release\lua502.lib" + :VCEnd + Скопировано файлов: 1. + FinalizeBuildStatus: + Deleting file "Release\lua502.unsuccessfulbuild". + Touching "Release\lua502.lastbuildstate". + 1>Done Building Project "D:\lua502\lua\lua502\lua502.vcxproj" (build target(s)). + +ПоÑтроение уÑпешно завершено. + +Time Elapsed 00:00:03.30 diff --git a/lua/lua502/Release/lua502.vcxprojResolveAssemblyReference.cache b/lua/lua502/Release/lua502.vcxprojResolveAssemblyReference.cache new file mode 100644 index 0000000..3f01681 Binary files /dev/null and b/lua/lua502/Release/lua502.vcxprojResolveAssemblyReference.cache differ diff --git a/lua/lua502/Release/lua502.write.1.tlog b/lua/lua502/Release/lua502.write.1.tlog new file mode 100644 index 0000000..417f345 --- /dev/null +++ b/lua/lua502/Release/lua502.write.1.tlog @@ -0,0 +1,555 @@ +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +^D:\lua502\lua\lua502\lua502.vcxproj +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.lib +D:\GMod9Dev_Server\gmod9\addons\lua502.exp +D:\GMod9Dev_Server\gmod9\addons\lua502.exp diff --git a/lua/lua502/Release/luafile.obj b/lua/lua502/Release/luafile.obj new file mode 100644 index 0000000..e58a39f Binary files /dev/null and b/lua/lua502/Release/luafile.obj differ diff --git a/lua/lua502/Release/luapointer.obj b/lua/lua502/Release/luapointer.obj new file mode 100644 index 0000000..4ba29fb Binary files /dev/null and b/lua/lua502/Release/luapointer.obj differ diff --git a/lua/lua502/Release/lundump.obj b/lua/lua502/Release/lundump.obj new file mode 100644 index 0000000..41ddffe Binary files /dev/null and b/lua/lua502/Release/lundump.obj differ diff --git a/lua/lua502/Release/lvm.obj b/lua/lua502/Release/lvm.obj new file mode 100644 index 0000000..00b8a45 Binary files /dev/null and b/lua/lua502/Release/lvm.obj differ diff --git a/lua/lua502/Release/lzio.obj b/lua/lua502/Release/lzio.obj new file mode 100644 index 0000000..1fce51a Binary files /dev/null and b/lua/lua502/Release/lzio.obj differ diff --git a/lua/lua502/Release/lzmalib.obj b/lua/lua502/Release/lzmalib.obj new file mode 100644 index 0000000..3679dbc Binary files /dev/null and b/lua/lua502/Release/lzmalib.obj differ diff --git a/lua/lua502/Release/mainlib.obj b/lua/lua502/Release/mainlib.obj new file mode 100644 index 0000000..ea2d68f Binary files /dev/null and b/lua/lua502/Release/mainlib.obj differ diff --git a/lua/lua502/Release/mt.command.1.tlog b/lua/lua502/Release/mt.command.1.tlog new file mode 100644 index 0000000..e3a453d Binary files /dev/null and b/lua/lua502/Release/mt.command.1.tlog differ diff --git a/lua/lua502/Release/mt.read.1.tlog b/lua/lua502/Release/mt.read.1.tlog new file mode 100644 index 0000000..111d5fb Binary files /dev/null and b/lua/lua502/Release/mt.read.1.tlog differ diff --git a/lua/lua502/Release/mt.write.1.tlog b/lua/lua502/Release/mt.write.1.tlog new file mode 100644 index 0000000..30dfff8 Binary files /dev/null and b/lua/lua502/Release/mt.write.1.tlog differ diff --git a/lua/lua502/Release/plugin.obj b/lua/lua502/Release/plugin.obj new file mode 100644 index 0000000..83dc88e Binary files /dev/null and b/lua/lua502/Release/plugin.obj differ diff --git a/lua/lua502/Release/sigscan.obj b/lua/lua502/Release/sigscan.obj new file mode 100644 index 0000000..039fde0 Binary files /dev/null and b/lua/lua502/Release/sigscan.obj differ diff --git a/lua/lua502/Release/svar.obj b/lua/lua502/Release/svar.obj new file mode 100644 index 0000000..7e355b8 Binary files /dev/null and b/lua/lua502/Release/svar.obj differ diff --git a/lua/lua502/Release/types.obj b/lua/lua502/Release/types.obj new file mode 100644 index 0000000..4b32325 Binary files /dev/null and b/lua/lua502/Release/types.obj differ diff --git a/lua/lua502/Release/vc100.pdb b/lua/lua502/Release/vc100.pdb new file mode 100644 index 0000000..23c643b Binary files /dev/null and b/lua/lua502/Release/vc100.pdb differ diff --git a/lua/lua502/baselib.cpp b/lua/lua502/baselib.cpp new file mode 100644 index 0000000..217003e --- /dev/null +++ b/lua/lua502/baselib.cpp @@ -0,0 +1,323 @@ +#define __BASELIB_INTERNAL_H +#include +#include "tier1/strtools.h" +#include "tier0/dbg.h" +#include "baselib.h" +#include "types.h" + +/*LUA_API userdata_t* luaL_createuserdata(lua_State* L, + unsigned short type,void* pData) +{ + userdata_t* pUserData = (userdata_t*)lua_newuserdata(L,sizeof(userdata_t)); + pUserData->m_nType = type; + pUserData->m_pData = pData; + + lua_pushref(L,type); //Notice that type is reference id! + lua_setmetatable(L,-2); + + return pUserData; +}*/ + +LUA_API void* luaL_createuserdata(lua_State* L,size_t sz,CLuaMetaTable* pMeta) +{ + void* pUserData = lua_newuserdata(L,sz+sizeof(unsigned short)); + *(unsigned short*)pUserData = pMeta->m_iTypeID; + + pMeta->PushToStack(L); + lua_setmetatable(L,-2); + + return (char*)pUserData+sizeof(unsigned short); +} + +LUA_API void* luaL_multicheckuserdata(lua_State* L,int idx,int nTypes,...) +{ + void* pUserData = lua_touserdata(L,1); + int type = *(unsigned short*)pUserData; + pUserData = (char*)pUserData+sizeof(unsigned short); + + va_list ap; + va_start(ap,nTypes); + for(int i = 0; i < nTypes; i++) + { + if(type == va_arg(ap,int)) + { + va_end(ap); + return pUserData; + } + } + va_end(ap); + luaL_argerror(L,idx,"Wrong userdata"); + return NULL; +} + +LUA_API void luaL_pushfstring(lua_State* L,const char* pFmt,...) +{ + char szBuf[MAX_PATH]; + va_list ap; + + va_start(ap,pFmt); + V_vsnprintf(szBuf,MAX_PATH,pFmt,ap); + va_end(ap); + + lua_pushstring(L,szBuf); +} + +LUA_API int lua_refobj(lua_State* L) +{ + char szName[16]; + static int iID = 0; + sprintf(szName,"lua502ref_%04x",++iID); + lua_pushstring(L,szName); + lua_pushvalue(L,-2); + lua_settable(L,LUA_REGISTRYINDEX); + lua_pop(L,1); + return iID; +} + +LUA_API void lua_unrefobj(lua_State* L,int id) +{ + char szName[16]; + sprintf(szName,"lua502ref_%04x",id); + lua_pushstring(L,szName); + lua_pushnil(L); + lua_settable(L,LUA_REGISTRYINDEX); +} + +LUA_API void lua_pushref(lua_State* L,int id) +{ + char szName[16]; + sprintf(szName,"lua502ref_%04x",id); + lua_pushstring(L,szName); + lua_gettable(L,LUA_REGISTRYINDEX); +} + +CLuaFunction::CLuaFunction(CLuaTable* pTable,const char* pName, + lua_CFunction fnFunc) +{ + m_pName = pName; + m_fnFunc = fnFunc; + pTable->Add(this); +} + +CLuaTable::CLuaTable(CLuaLibrary* pLib,const char* pName, + bool bRegister) +{ + m_pName = pName; + m_bRegister = bRegister; + pLib->Add(this); +} + +int luaf_unk_tostring(lua_State* L) +{ + luaL_checktype(L,1,LUA_TUSERDATA); + UInt16* pUserData = (UInt16*)lua_touserdata(L,1); + luaL_pushfstring(L,"%s %p",luaf_typename(*pUserData), + (char*)pUserData+sizeof(UInt16)); + return 1; +} + +void CLuaTable::Add(CLuaFunction* pFunc) +{ + pFunc->m_pNext = m_pLast; + m_pLast = pFunc; +} + +//Still work +void CLuaTable::Register(lua_State* L) +{ + CLuaFunction* pFunc; + if(!(pFunc = m_pLast)) return; + + if(!V_strcmp(m_pName,"_G")) + { + do { + lua_register(L,pFunc->m_pName, + pFunc->m_fnFunc); + } while((pFunc=pFunc->m_pNext)); + } + else + { + lua_pushstring(L,m_pName); + lua_newtable(L); + do { + lua_pushstring(L,pFunc->m_pName); + lua_pushcfunction(L,pFunc->m_fnFunc); + lua_settable(L,-3); + } while((pFunc=pFunc->m_pNext)); + lua_settable(L,LUA_GLOBALSINDEX); + } +} + +void CLuaTable::Unregister(lua_State* L) +{ + CLuaFunction* pFunc = m_pLast; + if(!V_strcmp(m_pName,"_G")) + { + while(pFunc) + { + lua_pushstring(L,pFunc->m_pName); + lua_pushnil(L); + lua_settable(L,LUA_GLOBALSINDEX); + pFunc = pFunc->m_pNext; + } + } + else + { + lua_pushstring(L,m_pName); + lua_pushnil(L); + lua_settable(L,LUA_GLOBALSINDEX); + } +} + +CLuaMetaTable::CLuaMetaTable(CLuaLibrary* pLib, + unsigned short nTypeID,CLuaTable* pParent) + : CLuaTable(pLib,NULL) +{ + m_iTypeID = (int)nTypeID; + m_pParent = pParent; +} + +void CLuaMetaTable::Register(lua_State* L) +{ + CLuaFunction* pFunc; + bool bHasIndex = false,bHasToString = false; + if(!(pFunc = m_pLast)) return; + + sprintf(m_szMetaName,"metatable_%04d",m_iTypeID); + + lua_pushstring(L,m_szMetaName); + lua_newtable(L); + do { + if(!V_strcmp(pFunc->m_pName,"__index")) + bHasIndex = true; + if(!V_strcmp(pFunc->m_pName,"__tostring")) + bHasToString = true; + lua_pushstring(L,pFunc->m_pName); + lua_pushcfunction(L,pFunc->m_fnFunc); + lua_settable(L,-3); + } while((pFunc=pFunc->m_pNext)); + if(m_pParent) + { + pFunc = m_pParent->m_pLast; + while(pFunc) + { + if(!V_strcmp(pFunc->m_pName,"__index")) + bHasIndex = true; + if(!V_strcmp(pFunc->m_pName,"__tostring")) + bHasToString = true; + lua_pushstring(L,pFunc->m_pName); + lua_pushcfunction(L,pFunc->m_fnFunc); + lua_settable(L,-3); + pFunc = pFunc->m_pNext; + } + } + if(!bHasIndex) + { + lua_pushstring(L,"__index"); + lua_pushvalue(L,-2); + lua_settable(L,-3); + } + if(!bHasToString) + { + lua_pushstring(L,"__tostring"); + lua_pushcfunction(L,luaf_unk_tostring); + lua_settable(L,-3); + } + lua_settable(L,LUA_REGISTRYINDEX); +} + +void CLuaMetaTable::Unregister(lua_State* L) +{ + lua_pushstring(L,m_szMetaName); + lua_pushnil(L); + lua_settable(L,LUA_REGISTRYINDEX); +} + +void CLuaMetaTable::PushToStack(lua_State* L) +{ + lua_pushstring(L,m_szMetaName); + lua_gettable(L,LUA_REGISTRYINDEX); +} + +CLuaLibrary* CLuaLibrary::s_pLast = NULL; + +CLuaLibrary::CLuaLibrary(const char* pName) +{ + m_pName = pName; + m_pLastTable = NULL; + + m_pNextLibrary = s_pLast; + s_pLast = this; +} + +void CLuaLibrary::Add(CLuaTable* pTable) +{ + pTable->m_pNext = m_pLastTable; + m_pLastTable = pTable; +} + +void CLuaLibrary::Register(lua_State* L) +{ + CLuaTable* pTable; + if(!(pTable = m_pLastTable)) return; + do { + if(!pTable->m_bRegister) continue; + pTable->Register(L); + } while((pTable=pTable->m_pNext)); +} + +void CLuaLibrary::Unregister(lua_State* L) +{ + CLuaTable* pTable; + if(!(pTable = m_pLastTable)) return; + do { + if(!pTable->m_bRegister) continue; + pTable->Unregister(L); + } while((pTable=pTable->m_pNext)); +} + +void CLuaLibrary::Init(lua_State* L) +{ + CLuaLibrary* pLib; + if(!(pLib = s_pLast)) return; + do { + pLib->Register(L); + } while((pLib=pLib->m_pNextLibrary)); +} + +void CLuaLibrary::Exit(lua_State* L) +{ + CLuaLibrary* pLib; + if(!(pLib = s_pLast)) return; + do { + pLib->Unregister(L); + } while((pLib=pLib->m_pNextLibrary)); +} + +void CLuaLibrary::Dump() +{ + CLuaLibrary* pLib; + CLuaTable* pTable; + CLuaFunction* pFunc; + + pLib = s_pLast; + while(pLib) + { + Msg("library %s\n",pLib->m_pName); + pTable = pLib->m_pLastTable; + while(pTable) + { + Msg("\ttable %s\n",pTable->m_iTypeID>1024 + ? pTable->m_pName:"(metatable)"); + pFunc = pTable->m_pLast; + while(pFunc) + { + Msg("\t\tfunction %s %p\n",pFunc->m_pName, + pFunc->m_fnFunc); + pFunc = pFunc->m_pNext; + } + pTable = pTable->m_pNext; + } + pLib = pLib->m_pNextLibrary; + } +} \ No newline at end of file diff --git a/lua/lua502/baselib.h b/lua/lua502/baselib.h new file mode 100644 index 0000000..33b2018 --- /dev/null +++ b/lua/lua502/baselib.h @@ -0,0 +1,131 @@ +#ifndef __BASELIB_H +#define __BASELIB_H + +#include "lua.h" +#include "lauxlib.h" +#include "ltable.h" +#include "lapi.h" + +class CLuaLibrary; +class CLuaFunction; +class CLuaTable +{ +public: + CLuaTable(CLuaLibrary* pLib, + const char* pName, bool bRegister = true); + + void Add(CLuaFunction* pFunc); + virtual void Register(lua_State* L); + virtual void Unregister(lua_State* L); + + union { + const char* m_pName; + int m_iTypeID; + }; + bool m_bRegister; + + CLuaFunction* m_pLast; + CLuaTable* m_pNext; +}; + +class CLuaMetaTable : public CLuaTable +{ +public: + CLuaMetaTable(CLuaLibrary* pLib, + unsigned short nTypeID, + CLuaTable* pParent = NULL); + + virtual void Register(lua_State* L); + virtual void Unregister(lua_State* L); + virtual void PushToStack(lua_State* L); + + CLuaTable* m_pParent; + char m_szMetaName[16]; +}; + +class CLuaFunction +{ +public: + CLuaFunction(CLuaTable* pTable,const char* pName, + lua_CFunction fnFunc); + + const char* m_pName; + lua_CFunction m_fnFunc; + CLuaFunction* m_pNext; +}; + +class CLuaLibrary +{ +public: + CLuaLibrary(const char* pName); + + virtual void Register(lua_State* L); + virtual void Unregister(lua_State* L); + + void Add(CLuaTable* pTable); + + const char* m_pName; + + CLuaTable* m_pLastTable; + CLuaLibrary* m_pNextLibrary; + + static void Init(lua_State* L); + static void Exit(lua_State* L); + + static void Dump(); + + static CLuaLibrary* s_pLast; +}; + +typedef unsigned short UInt16; + +typedef struct { + UInt16 m_nType; + void* m_pData; +} userdata_t; + +LUA_API void* luaL_createuserdata(lua_State* L,size_t sz, + CLuaMetaTable* pMeta); +LUA_API void luaL_pushfstring(lua_State* L,const char* pFmt,...); +inline void* luaf_checkuserdata(lua_State* L,int idx, + CLuaMetaTable* pMeta) +{ + luaL_checktype(L,idx,LUA_TUSERDATA); + void* pUD = lua_touserdata(L,idx); + if(*(unsigned char*)pUD != pMeta->m_iTypeID) + luaL_argerror(L,idx,"Wrong userdata"); + else return (char*)pUD+sizeof(unsigned short); + return NULL; +} +LUA_API void* luaL_multicheckuserdata(lua_State* L,int idx, + int nTypes,...); + +//Eats object at top of stack +LUA_API int lua_refobj(lua_State* L); +LUA_API void lua_unrefobj(lua_State* L,int id); +LUA_API void lua_pushref(lua_State* L,int id); + +//#undef __BASELIB_INTERNAL_H +#ifndef __BASELIB_INTERNAL_H +#define DECLARE_LIBRARY(name) \ + static CLuaLibrary g_LuaLibrary(name); + +#define DECLARE_TABLE(tablename) \ + static CLuaTable g_LuaTable_##tablename(&g_LuaLibrary,#tablename); + +#define DECLARE_TABLE_DUMMY(tablename) \ + static CLuaTable g_LuaTable_##tablename(&g_LuaLibrary,#tablename,false); + +#define DECLARE_METATABLE(tablename,type) \ + static CLuaMetaTable g_LuaTable_##tablename(&g_LuaLibrary,type); + +#define DECLARE_METATABLE_INHERITOR(tablename,type,parent) \ + static CLuaMetaTable g_LuaTable_##tablename(&g_LuaLibrary,type,&g_LuaTable_##parent); + +#define DECLARE_FUNCTION(tablename,funcname) \ + static int luaf_##tablename##funcname(lua_State*); \ + static CLuaFunction g_##tablename##funcname(&g_LuaTable_##tablename,#funcname,luaf_##tablename##funcname); \ + static int luaf_##tablename##funcname(lua_State* L) +#endif + +#endif \ No newline at end of file diff --git a/lua/lua502/bitlib.cpp b/lua/lua502/bitlib.cpp new file mode 100644 index 0000000..3470420 --- /dev/null +++ b/lua/lua502/bitlib.cpp @@ -0,0 +1,154 @@ +#include "baselib.h" + +DECLARE_LIBRARY("bit") +DECLARE_TABLE(bit) + +typedef unsigned long lua_Unsigned; + +inline lua_Unsigned toU(lua_State* L,int idx) +{ + return (lua_Unsigned)lua_tonumber(L,idx); +} + +inline void pushU(lua_State* L,lua_Unsigned U) +{ + lua_pushnumber(L,(lua_Number)U); +} + +DECLARE_FUNCTION(bit,lsh) +{ + luaL_checktype(L,1,LUA_TNUMBER); + luaL_checktype(L,2,LUA_TNUMBER); + pushU(L,(toU(L,1) << toU(L,2))); + return 1; +} + +DECLARE_FUNCTION(bit,rsh) +{ + luaL_checktype(L,1,LUA_TNUMBER); + luaL_checktype(L,2,LUA_TNUMBER); + pushU(L,(toU(L,1) >> toU(L,2))); + return 1; +} + +DECLARE_FUNCTION(bit,bor) +{ + luaL_checktype(L,1,LUA_TNUMBER); + luaL_checktype(L,2,LUA_TNUMBER); + pushU(L,(toU(L,1) | toU(L,2))); + return 1; +} + +DECLARE_FUNCTION(bit,band) +{ + luaL_checktype(L,1,LUA_TNUMBER); + luaL_checktype(L,2,LUA_TNUMBER); + pushU(L,(toU(L,1) & toU(L,2))); + return 1; +} + +DECLARE_FUNCTION(bit,bnot) +{ + luaL_checktype(L,1,LUA_TNUMBER); + pushU(L,~toU(L,1)); + return 1; +} + +inline int bitmask(unsigned int n) +{ + return (1<>bits); +} + +inline unsigned int rol(unsigned int num,unsigned int bits) +{ + return ((num&~bitmask(bits))>>(32-bits))|(num< +#include +#include + +class CHook +{ +public: + CHook(DWORD Func,SIZE_T Size); + ~CHook(); + + DWORD HookFunction(DWORD Hook); + DWORD UnHookFunction(); +private: + bool hooked; + DWORD pFunc; + DWORD pHook; + DWORD pOrig; + SIZE_T DetourSize; + PBYTE OrigBytes; +}; + +#endif \ No newline at end of file diff --git a/lua/lua502/console.cpp b/lua/lua502/console.cpp new file mode 100644 index 0000000..44aa8ad --- /dev/null +++ b/lua/lua502/console.cpp @@ -0,0 +1,234 @@ +#define GAME_DLL +#include "eiface.h" +#include "convar.h" +#include "glua.h" +#include "plugin.h" +#include "luafile.h" +#include "tier0/icommandline.h" + +extern IVEngineServer* engine; +static ConVar lua502_luapath("lua502_luapath","MOD"); + +CON_COMMAND(lua502_plugin,"Lua502 Plugin Interfae") +{ + if(engine->Cmd_Argc() < 1) return; + const char* pCmd = engine->Cmd_Argv(1); + if(!V_stricmp(pCmd,"load")) + { + int iPlug; + const char* pName = engine->Cmd_Argv(2); + if(!g_pLua502->LoadPlugin(pName,&iPlug)) + g_pLua502->Print("Failed load plugin %s\n", + pName); + else + g_pLua502->Print("Plugin %s successfully loaded!\n",iPlug); + } + else if(!V_stricmp(pCmd,"unload")) + g_pLua502->UnloadPlugin(V_atoi( + engine->Cmd_Argv(2))); + else if(!V_stricmp(pCmd,"list")) + { + luaplugin_t* pPlug = NULL; + for(int i = 0; (pPlug = g_pLua502 + ->GetPlugin(i++));) + Msg("%d: %s (%d %p)\n",(i-1), + pPlug->m_szName,pPlug->m_iVersion, + pPlug->m_pCallbacks); + } +} + +CON_COMMAND(lua502_run,"Run lua") +{ + const char* pErr,*pCode = engine->Cmd_Args(); + int iLen = strlen(pCode); + if(iLen<1) return; + if((pErr=g_pLua502->RunString(pCode,iLen,"lua502_run"))) + Msg("%s\n",pErr); +} + +CON_COMMAND(lua502_runfile,"Run lua file") +{ + if(engine->Cmd_Argc()<2) return; + if(g_pLua502->RunFile(engine->Cmd_Args())) + Warning("ILua502::RunFile failed!\n"); +} + +CON_COMMAND(lua502_cache,"Cache Interface") +{ + if(engine->Cmd_Argc() < 1) return; + const char* pCmd = engine->Cmd_Argv(1); + if(!V_stricmp(pCmd,"list")) + { + Msg("name size time\n"); + for(int i = 0; i < CLuaFile::s_Cache.Size(); i++) + { + CLuaFile::cachenode_t& cache = CLuaFile::s_Cache[i]; + Msg("%s %d %d\n",cache.m_szName,cache.m_uSize, + cache.m_lTime); + } + } + else if(!V_stricmp(pCmd,"forceupdate")) + CLuaFile::UpdateCacheFile(); + else if(!V_stricmp(pCmd,"clear")) + CLuaFile::ClearCache(); +} + +void DebugMsg(const char* pFmt,...) +{ + char szBuffer[128]; + va_list ap; + + va_start(ap,pFmt); + V_vsnprintf(szBuffer,128,pFmt,ap); + va_end(ap); + + OutputDebugString(szBuffer); +} + +static void value2string(lua_State* L,char* pBuffer) +{ + const char* pValue; + switch(lua_type(L,-1)) + { + case LUA_TFUNCTION: + sprintf(pBuffer,"function 0x%08X",lua_tocfunction(L,-1)); + break; + case LUA_TBOOLEAN: + sprintf(pBuffer,lua_toboolean(L,-1)?"true":"false"); + break; + case LUA_TLIGHTUSERDATA: + sprintf(pBuffer,"userdata 0x%08X",lua_touserdata(L,-1)); + break; + default: + if((pValue = lua_tostring(L,-1))) V_strcpy(pBuffer,pValue); + else V_strcpy(pBuffer,"(null)"); + break; + } +} + +static void DumpTable(lua_State* L,FileHandle_t fLog,int iLevel, + int iMaxLevel = 2) +{ + char szValue[128] = {0}; + const char* pKey; + + if(iLevel==iMaxLevel) return; + if(!iLevel) + { + for(int i = 0; i < iLevel; i++) + filesystem->FPrintf(fLog,"\t"); + filesystem->FPrintf(fLog,"(root)\n"); + } + else + { + const char* pKey = lua_tostring(L,-2); + filesystem->FPrintf(fLog,"|"); + for(int i = 0; i < iLevel; i++) + filesystem->FPrintf(fLog,"\t"); + filesystem->FPrintf(fLog,"%s\n",pKey?pKey:"(null)"); + } + + lua_pushnil(L); //Nil key + while(lua_next(L,-2)!=0) + { + //if(lua_tostring(L,-2)=="_G") continue; + if(!(pKey = lua_tostring(L,-2))) pKey = "(null)"; + if(*pKey == '0') + { + lua_pop(L,1); + Msg("Possibly error detected\n"); + return; + } + + if(*(unsigned short*)pKey == 0x455F + || *(unsigned short*)pKey == 0x475F + || *(unsigned short*)pKey == 0x525F + || *(unsigned int*)pKey == 0x5F544341 + || !V_strcmp(pKey,"g_EvenHooks") + || !V_strcmp(pKey,"gLuaThinkFunctions") + || *pKey == 'g') + { + lua_pop(L,1); + continue; + } + + if(lua_type(L,-1) == LUA_TTABLE) + { + DebugMsg("Recursive table %s\n",pKey); + DumpTable(L,fLog,iLevel+1,iMaxLevel); + } + else + { + value2string(L,szValue); + for(int i = 0; i < (iLevel); i++) + filesystem->FPrintf(fLog,"\t"); + filesystem->FPrintf(fLog,"|\t"); + DebugMsg("[%s] = %s\n",pKey,szValue); + filesystem->FPrintf(fLog,"[%s] = %s\n", + pKey,szValue); + } + lua_pop(L,1); //Pop value + } +} + +CON_COMMAND(lua502_gdump,"Dump _G table, levels specified") +{ + FileHandle_t fLog = filesystem->Open("gdump.log","wb","MOD"); + int iMaxLevel = atoi(engine->Cmd_Argv(1)); + if(!iMaxLevel) iMaxLevel = 2; + lua_State* L = g_pLua502->GetLuaInterface()->m_pL; + + lua_pushvalue(L,LUA_GLOBALSINDEX); + DumpTable(L,fLog,0,iMaxLevel); + lua_pop(L,1); + filesystem->Close(fLog); +} + +CON_COMMAND(lua502_kdump,"Dump KeyValues") +{ + KeyValues* kv = new KeyValues("kdump"); + kv->LoadFromFile(filesystem,"kval.txt","MOD"); + KeyValues* pIter = kv->GetFirstSubKey(); + if(!pIter) return; + do { + Msg("%s %s\n",pIter->GetName(),pIter->GetString()); + } while((pIter=pIter->GetNextKey())); + kv->deleteThis(); +} + +CON_COMMAND(lua502_ndump,"Make KeyValue dump") +{ + KeyValues* kv = new KeyValues("root"); + + KeyValues* pSub1 = new KeyValues("group1"); + KeyValues* pSub2 = new KeyValues("group2"); + + KeyValues* pKey1 = pSub1->CreateNewKey(); + KeyValues* pKey2 = pSub2->CreateNewKey(); + + pKey1->SetName("Name1"); + pKey1->SetStringValue("Value1"); + + pKey2->SetName("Name1"); + pKey2->SetStringValue("Value1"); + + kv->AddSubKey(pSub1); + kv->AddSubKey(pSub2); + + kv->SaveToFile(filesystem,"ndump.txt","MOD"); + kv->deleteThis(); +} + +CON_COMMAND(crashme,"") +{ + PDWORD pdwVal = NULL; + *pdwVal = 0xDEADBEEF; +} + +CON_COMMAND(whileloop,"") +{ + while(1) + { + __asm nop; + } +} \ No newline at end of file diff --git a/lua/lua502/cvarlib.cpp b/lua/lua502/cvarlib.cpp new file mode 100644 index 0000000..5e49da9 --- /dev/null +++ b/lua/lua502/cvarlib.cpp @@ -0,0 +1,371 @@ +#include "tier1/convar.h" +#include "icvar.h" +#include "types.h" +#include "plugin.h" +#include "baselib.h" +#include "cvarlib.h" + +DECLARE_LIBRARY("cvar"); +DECLARE_TABLE_DUMMY(concommandbase); + +DECLARE_FUNCTION(concommandbase,__tostring) +{ + cmdbase_ud_t* ud = (cmdbase_ud_t*)luaL_multicheckuserdata(L,1, + 2,CONVAR,COMMAND); + if(!ud) return 0; + luaL_pushfstring(L,"%s %s (%p)",ud->m_pBase->IsCommand()?"ConCommand":"ConVar", + ud->m_pBase->GetName(),ud->m_pBase); + return 1; +} + +DECLARE_FUNCTION(concommandbase,__gc) +{ + cmdbase_ud_t* ud = (cmdbase_ud_t*)luaL_multicheckuserdata(L,1, + 2,CONVAR,COMMAND); + if(!ud) return 0; + if(ud->m_bCustom) + { + if(ud->m_pBase->IsCommand()) + delete (CLuaConCommand*)ud->m_pCmd; + else delete ud->m_pConVar; + } + return 0; +} + +DECLARE_FUNCTION(concommandbase,GetName) +{ + //ConCommandBase** ppBase = (ConCommandBase**)luaL_multicheckuserdata(L,1,3, + //CONVAR,COMMAND),*pBase; + cmdbase_ud_t* ud = (cmdbase_ud_t*)luaL_multicheckuserdata(L,1,2, + CONVAR,COMMAND); + if(!ud) return 0; + lua_pushstring(L,ud->m_pBase->GetName()); + return 1; +} + +DECLARE_FUNCTION(concommandbase,GetHelpText) +{ + cmdbase_ud_t* ud = (cmdbase_ud_t*)luaL_multicheckuserdata(L,1,2, + CONVAR,COMMAND); + if(!ud) return 0; + + lua_pushstring(L,ud->m_pBase->GetHelpText()); + return 1; +} + +DECLARE_FUNCTION(concommandbase,GetNext) +{ + cmdbase_ud_t* ud = (cmdbase_ud_t*)luaL_multicheckuserdata(L,1,2, + CONVAR,COMMAND); + ConCommandBase* pNext; + if(!ud) return 0; + + if((pNext = (ConCommandBase*)ud->m_pBase->GetNext())) + luaf_makecmdbase(L,ud->m_pBase); + else lua_pushnil(L); + return 1; +} + +DECLARE_FUNCTION(concommandbase,IsCommand) +{ + cmdbase_ud_t* ud = (cmdbase_ud_t*)luaL_multicheckuserdata(L,1,2, + CONVAR,COMMAND); + if(!ud) return 0; + + lua_pushboolean(L,ud->m_pBase->IsCommand()); + return 1; +} + +DECLARE_FUNCTION(concommandbase,IsRegistered) +{ + cmdbase_ud_t* ud = (cmdbase_ud_t*)luaL_multicheckuserdata(L,1,2, + CONVAR,COMMAND); + if(!ud) return 0; + + lua_pushboolean(L,ud->m_pBase->IsRegistered()); + return 1; +} + +DECLARE_FUNCTION(concommandbase,IsBitSet) +{ + cmdbase_ud_t* ud = (cmdbase_ud_t*)luaL_multicheckuserdata(L,1,2, + CONVAR,COMMAND); + if(!ud) return 0; + + lua_pushboolean(L,ud->m_pBase->IsBitSet(lua_tonumber(L,2))); + return 1; +} + +DECLARE_FUNCTION(concommandbase,AddFlags) +{ + cmdbase_ud_t* ud = (cmdbase_ud_t*)luaL_multicheckuserdata(L,1,2, + CONVAR,COMMAND); + if(!ud) return 0; + + ud->m_pBase->AddFlags(lua_tonumber(L,2)); + return 0; +} + +DECLARE_METATABLE_INHERITOR(convar,CONVAR,concommandbase); + +DECLARE_FUNCTION(convar,GetValue) +{ + cmdbase_ud_t* ud = (cmdbase_ud_t*)luaf_checkuserdata(L,1,&g_LuaTable_convar); + if(!ud) return 0; + + lua_pushstring(L,ud->m_pConVar->GetString()); + return 1; +} + +DECLARE_FUNCTION(convar,SetValue) +{ + cmdbase_ud_t* ud = (cmdbase_ud_t*)luaf_checkuserdata(L,1,&g_LuaTable_convar); + if(!ud) return 0; + + ud->m_pConVar->SetValue(lua_tostring(L,2)); + return 0; +} + +DECLARE_FUNCTION(convar,SetBool) +{ + cmdbase_ud_t* ud = (cmdbase_ud_t*)luaL_multicheckuserdata(L,1,2, + CONVAR,COMMAND); + if(!ud) return 0; + + ud->m_pConVar->SetValue(!!lua_toboolean(L,2)); + return 0; +} + +DECLARE_FUNCTION(convar,SetInt) +{ + cmdbase_ud_t* ud = (cmdbase_ud_t*)luaf_checkuserdata(L,1,&g_LuaTable_convar); + if(!ud) return 0; + + ud->m_pConVar->SetValue((int)lua_tonumber(L,2)); + return 0; +} + +DECLARE_FUNCTION(convar,SetFloat) +{ + cmdbase_ud_t* ud = (cmdbase_ud_t*)luaf_checkuserdata(L,1,&g_LuaTable_convar); + if(!ud) return 0; + + ud->m_pConVar->SetValue((float)lua_tonumber(L,2)); + return 0; +} + +DECLARE_FUNCTION(convar,GetBool) +{ + cmdbase_ud_t* ud = (cmdbase_ud_t*)luaf_checkuserdata(L,1,&g_LuaTable_convar); + if(!ud) return 0; + + lua_pushboolean(L,ud->m_pConVar->GetBool()); + return 1; +} + +DECLARE_FUNCTION(convar,GetInt) +{ + cmdbase_ud_t* ud = (cmdbase_ud_t*)luaf_checkuserdata(L,1,&g_LuaTable_convar); + if(!ud) return 0; + + lua_pushnumber(L,ud->m_pConVar->GetInt()); + return 1; +} + +DECLARE_FUNCTION(convar,GetFloat) +{ + cmdbase_ud_t* ud = (cmdbase_ud_t*)luaf_checkuserdata(L,1,&g_LuaTable_convar); + if(!ud) return 0; + + lua_pushnumber(L,ud->m_pConVar->GetFloat()); + return 1; +} + +DECLARE_FUNCTION(convar,GetDefault) +{ + cmdbase_ud_t* ud = (cmdbase_ud_t*)luaf_checkuserdata(L,1,&g_LuaTable_convar); + if(!ud) return 0; + + lua_pushstring(L,ud->m_pConVar->GetDefault()); + return 1; +} + +DECLARE_METATABLE_INHERITOR(concommand,COMMAND,concommandbase); + +DECLARE_FUNCTION(concommand,Dispatch) +{ + char szCommand[MAX_PATH] = {0}; + cmdbase_ud_t* ud = (cmdbase_ud_t*)luaf_checkuserdata(L,1,&g_LuaTable_concommand); + luaL_checktype(L,2,LUA_TSTRING); + if(!ud) return 0; + + sprintf(szCommand,"%s %s\n",ud->m_pCmd->GetName(),lua_tostring(L,2)); + engine->ServerCommand(szCommand); + engine->ServerExecute(); + + return 0; +} + +DECLARE_TABLE(cvar); + +DECLARE_FUNCTION(cvar,GetCommands) +{ + ConCommandBase* pBase; + if((pBase = cvar->GetCommands())) + lua_pushnil(L); + else luaf_makecmdbase(L,pBase); + return 1; +} + +DECLARE_FUNCTION(cvar,Find) +{ + ConCommandBase* pBase; + const char* pName; + luaL_checktype(L,1,LUA_TSTRING); + pName = lua_tostring(L,1); + + pBase = cvar->GetCommands(); + while(pBase) + { + if(!V_strcmp(pBase->GetName(),pName)) + { + luaf_makecmdbase(L,pBase); + return 1; + } + pBase = (ConCommandBase*)pBase->GetNext(); + } + + lua_pushnil(L); + return 1; +} + +DECLARE_FUNCTION(cvar,RegisterConCommandBase) +{ + ConCommandBase** ppBase = (ConCommandBase**)luaL_multicheckuserdata(L, + 1,2,CONVAR,COMMAND); + if(!ppBase) return 0; + else cvar->RegisterConCommandBase(*ppBase); + return 0; +} + +DECLARE_FUNCTION(cvar,CreateConVar) +{ + int iArgs,iFlags = 0; + const char* pHelpText = ""; + cmdbase_ud_t* ud; + + luaL_checktype(L,1,LUA_TSTRING); + luaL_checktype(L,2,LUA_TSTRING); + iArgs = lua_gettop(L); + + if(iArgs>2) + pHelpText = lua_tostring(L,3); + if(iArgs>3) + iFlags = lua_tonumber(L,4); + + ConVar* pConVar = new ConVar(lua_tostring(L,1),lua_tostring(L,2), + iFlags,pHelpText); + ud = luaf_makeconvar(L,pConVar); + if(ud) ud->m_bCustom = true; + else lua_pushnil(L); + return 1; +} + +DECLARE_FUNCTION(cvar,CreateConCommand) +{ + int iArgs,iRefID,iFlags = 0; + const char* pHelpText = ""; + cmdbase_ud_t* ud; + + luaL_checktype(L,1,LUA_TSTRING); + luaL_checktype(L,2,LUA_TFUNCTION); + iArgs = lua_gettop(L); + + if(iArgs>2) pHelpText = lua_tostring(L,3); + if(iArgs>3) iFlags = lua_tonumber(L,4); + + if(!(ud = luaf_makecommand(L,NULL))) + lua_pushnil(L); + else + { + lua_pushvalue(L,2); + iRefID = lua_refobj(L); + + ud->m_pCmd = new CLuaConCommand(lua_tostring(L,1),L,iRefID,pHelpText,iFlags); + ud->m_bCustom = true; + } + return 1; +} + +DECLARE_TABLE(cmd); + +DECLARE_FUNCTION(cmd,Argc) +{ + lua_pushnumber(L,engine->Cmd_Argc()); + return 1; +} + +DECLARE_FUNCTION(cmd,Argv) +{ + const char* pStr; + + luaL_checktype(L,1,LUA_TNUMBER); + pStr = engine->Cmd_Argv(lua_tonumber(L,1)); + + lua_pushstring(L,pStr?pStr:"(null)"); + return 1; +} + +DECLARE_FUNCTION(cmd,Args) +{ + const char* pStr = engine->Cmd_Args(); + + lua_pushstring(L,pStr?pStr:"(null)"); + return 1; +} + +cmdbase_ud_t* luaf_makecmdbase(lua_State* L,ConCommandBase* pBase) +{ + if(pBase->IsCommand()) + return luaf_makecommand(L,(ConCommand*)pBase); + return luaf_makeconvar(L,(ConVar*)pBase); +} + +cmdbase_ud_t* luaf_makeconvar(lua_State* L,ConVar* pConVar) +{ + cmdbase_ud_t* ud = (cmdbase_ud_t*)luaL_createuserdata(L, + sizeof(cmdbase_ud_t),&g_LuaTable_convar); + ud->m_pConVar = pConVar; + return ud; +} + +cmdbase_ud_t* luaf_makecommand(lua_State* L,ConCommand* pCmd) +{ + cmdbase_ud_t* ud = (cmdbase_ud_t*)luaL_createuserdata(L, + sizeof(cmdbase_ud_t),&g_LuaTable_convar); + ud->m_pCmd = pCmd; + return ud; +} + +CLuaConCommand::CLuaConCommand(char const *pName, lua_State* pL, int iRefID, + char const *pHelpString,int flags,FnCommandCompletionCallback completionFunc) + : ConCommand(pName,NULL,pHelpString,flags,completionFunc) +{ + m_pL = pL; + m_iRefID = iRefID; +} + +void CLuaConCommand::Dispatch(void) +{ + if(m_iRefID == -1) return; + + lua_pushref(m_pL,m_iRefID); + if(lua_isnil(m_pL,-1)) + { + Warning("CLuaConCommand %s is unreferenced!\n",GetName()); + m_iRefID = -1; + return; + } + + lua_call(m_pL,0,0); +} \ No newline at end of file diff --git a/lua/lua502/cvarlib.h b/lua/lua502/cvarlib.h new file mode 100644 index 0000000..c0ba297 --- /dev/null +++ b/lua/lua502/cvarlib.h @@ -0,0 +1,32 @@ +#ifndef __CVARLIB_H +#define __CVARLIB_H + +#include "glua.h" +#include "tier1/convar.h" + +typedef struct { + union { + ConCommandBase* m_pBase; + ConVar* m_pConVar; + ConCommand* m_pCmd; + }; + bool m_bCustom; +} cmdbase_ud_t; + +cmdbase_ud_t* luaf_makeconvar(lua_State* L,ConVar* pConVar); +cmdbase_ud_t* luaf_makecommand(lua_State* L,ConCommand* pCommand); +cmdbase_ud_t* luaf_makecmdbase(lua_State* L,ConCommandBase* pBase); + +class CLuaConCommand : public ConCommand +{ +public: + CLuaConCommand(char const *pName, lua_State* L, int iRefID, + char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0); + + virtual void Dispatch(void); +private: + lua_State* m_pL; + int m_iRefID; +}; + +#endif \ No newline at end of file diff --git a/lua/lua502/deprecated/depr.txt b/lua/lua502/deprecated/depr.txt new file mode 100644 index 0000000..019cfa7 --- /dev/null +++ b/lua/lua502/deprecated/depr.txt @@ -0,0 +1,236 @@ +#define INTERFACEVERSION_ISERVERPLUGINCALLBACKS "ISERVERPLUGINCALLBACKS003" +typedef int edict_t; +typedef int EQueryCvarValueStatus; +typedef int QueryCvarCookie_t; +typedef enum { + PLUGIN_CONTINUE, + PLUGIN_OVERRIDE, + PLUGIN_STOP, +} PLUGIN_RESULT; + +class IServerPluginCallbacks +{ +public: + virtual bool Load( CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory ) = 0; + virtual void Unload( void ) = 0; + virtual void Pause( void ) = 0; + virtual void UnPause( void ) = 0; + virtual const char* GetPluginDescription( void ) = 0; + virtual void LevelInit( const char* pMapName ) = 0; + virtual void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax ) = 0; + virtual void GameFrame( bool simulating ) = 0; + virtual void LevelShutdown( void ) = 0; + virtual void ClientActive( edict_t *pEntity ) = 0; + virtual void ClientDisconnect( edict_t *pEntity ) = 0; + virtual void ClientPutInServer( edict_t *pEntity, char const *playername ) = 0; + virtual void SetCommandClient( int index ) = 0; + virtual void ClientSettingsChanged( edict_t *pEdict ) = 0; + virtual PLUGIN_RESULT ClientConnect( bool *bAllowConnect, edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen ) = 0; + virtual PLUGIN_RESULT ClientCommand( edict_t *pEntity, void* args ) = 0; + virtual PLUGIN_RESULT NetworkIDValidated( const char *pszUserName, const char *pszNetworkID ) = 0; + virtual void OnQueryCvarValueFinished( QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue ) = 0; + virtual void OnEdictAllocated( edict_t *edict ) = 0; + virtual void OnEdictFreed( edict_t *edict ) = 0; +}; + +typedef int (*GM9EntryFn)(lua_State*); +typedef struct luaplugin_s { + GM9EntryFn m_fnInit; + GM9EntryFn m_fnExit; + unsigned int m_iPluginAPI; + //Place holders + const char* m_pName; + CreateInterfaceFn m_fnAppFactory; + CreateInterfaceFn m_fnGameFactory; + HMODULE m_hModule; + luaplugin_s* m_pNext; //Linked list, useful +} luaplugin_t; + +typedef luaplugin_t* (*GM9PluginInfoFn)(ILua502*); + +#define LUAPLUGIN_INFO_FN "gmod9_info" +#define LUAPLUGIN_API 0x1B565D55 + +typedef enum { + PLUGIN_OK, + PLUGIN_LLAFAIL, + PLUGIN_ABIMISM, + PLUGIN_DENIED, +} plugerr_t; + +plugerr_t CLua502Plugin::LoadPlugin(const char* pName,const char* pGameID,luaplugin_t** ppPlugin,int* pRet) +{ + HMODULE hMod; + luaplugin_t* pPlugin,*pIter; + GM9PluginInfoFn InfoFn; + int iRet,iTop[2]; + if((V_strlen(pName)+sizeof("lua/bin/%s"))>256) return PLUGIN_LLAFAIL; + + char szPath[256] = {0}; + sprintf(szPath,"lua/bin/%s",pName); + + //if(!(hMod = LoadLibrary(pPath))) return PLUGIN_LLAFAIL; + if(!(hMod = (HMODULE)filesystem->LoadModule(szPath,pGameID,false))) return PLUGIN_LLAFAIL; + + if(!(InfoFn = (GM9PluginInfoFn)GetProcAddress(hMod,LUAPLUGIN_INFO_FN))) + { + filesystem->UnloadModule((CSysModule*)hMod); + Print("gmod9_info not found!\n"); + return PLUGIN_ABIMISM; + } + if(!(pPlugin = InfoFn(g_pLua502))){ + filesystem->UnloadModule((CSysModule*)hMod); + Print("gmod9_info returned null\n"); + return PLUGIN_ABIMISM; + } + if(pPlugin->m_iPluginAPI != LUAPLUGIN_API){ + filesystem->UnloadModule((CSysModule*)hMod); + Print("Plugin API version mismatch!\n"); + return PLUGIN_ABIMISM; + } + if(!pPlugin->m_fnInit || !pPlugin->m_fnExit){ + filesystem->UnloadModule((CSysModule*)hMod); + Print("init & exit funcs not declared!\n"); + return PLUGIN_ABIMISM; + } + + pPlugin->m_hModule = hMod; + pPlugin->m_fnAppFactory = m_fnAppFactory; + pPlugin->m_fnGameFactory = m_fnGameFactory; + + if(!pPlugin->m_pName) + { + char* pLocalName = (char*)strrchr(pName,'/'); + if(!pLocalName) pLocalName = (char*)strrchr(pName,'\\'); + + if(!pLocalName) + { + static int s_iUnnamed = 0; + char szName[64]; + sprintf(szName,"unnamed_%03d",s_iUnnamed++); + pPlugin->m_pName = strdup(szName); + Print("Plugin %p doesn't have name!\n",pPlugin); + } + else pPlugin->m_pName = strdup((const char*)(pLocalName+1)); + } + else pPlugin->m_pName = strdup(pPlugin->m_pName); + + if((pIter=m_pFirstPlugin)) + { + do { + if(!V_stricmp(pIter->m_pName,pPlugin->m_pName)) + { + Print("Attempt to load same plugin!\n"); + return PLUGIN_DENIED; + } + } while((pIter=pIter->m_pNext)); + } + + iTop[0] = lua_gettop(m_pLuaInterface->m_pL); + iRet = pPlugin->m_fnInit(m_pLuaInterface->m_pL); + iTop[1] = lua_gettop(m_pLuaInterface->m_pL); + lua_settop(m_pLuaInterface->m_pL,iTop[0]); + if(iTop[0] != iTop[1]) Print("Possible lua stack leak: %d %d\n",iTop[0],iTop[1]); + + if(pRet) *pRet = iRet; + + pPlugin->m_pNext = m_pFirstPlugin; + m_pFirstPlugin = pPlugin; + if(ppPlugin) *ppPlugin = pPlugin; + return PLUGIN_OK; +} + +plugerr_t CLua502Plugin::UnloadPlugin(luaplugin_t* pPlugin,int* pRet) +{ + int iTop[2],iRet; + luaplugin_t* pIter; + //Check if name starts as [unna]med_XXX + //if(*(unsigned int*)pPlugin->m_pName != 0x616E6E75) + free((void*)pPlugin->m_pName); + if((pIter = m_pFirstPlugin)) + { + if(m_pFirstPlugin==pPlugin) + m_pFirstPlugin = pPlugin->m_pNext; + else + { + do { + if(pIter->m_pNext == pPlugin) + { + pIter->m_pNext = pPlugin->m_pNext; + break; + } + } while((pIter=pIter->m_pNext)); + } + } + + iTop[0] = lua_gettop(m_pLuaInterface->m_pL); + iRet = pPlugin->m_fnExit(m_pLuaInterface->m_pL); + iTop[1] = lua_gettop(m_pLuaInterface->m_pL); + lua_settop(m_pLuaInterface->m_pL,iTop[0]); + if(iTop[0] != iTop[1]) Print("Possible lua stack leak: %d %d\n",iTop[0],iTop[1]); + + if(pRet) *pRet = iRet; + + //FreeLibrary(pPlugin->m_hModule); + filesystem->UnloadModule((CSysModule*)(pPlugin->m_hModule)); + return PLUGIN_OK; +} + +if(!V_stricmp(pCmd,"list")) + { + luaplugin_t* pPlugin = g_pLua502->FirstPlugin(); + Msg("== Lua 502 Plugins (version %X) ==\n",LUAPLUGIN_API); + if(!pPlugin) + { + Msg("No plugins loaded\n"); + return; + } + do { + Msg("%p %x %s\n",pPlugin,pPlugin->m_hModule,pPlugin->m_pName?pPlugin->m_pName:"(null)"); + } while((pPlugin=pPlugin->m_pNext)); + } + else if(!V_stricmp(pCmd,"load")) + { + int iErr = 0,iRet = 0; + luaplugin_t* pPlugin = 0; + if(engine->Cmd_Argc() < 2) return; + const char* pPath = engine->Cmd_Argv(2); + if(!CLua502Plugin::IsPathSecure(pPath)) + { + g_pLua502->Print("Path contains banned symbols."); + return; + } + if((iErr=g_pLua502->LoadPlugin(pPath, + lua502_luapath.GetString(),&pPlugin,&iRet))) + Warning("Error %d occured when loading lua plugin!\n",iErr); + else Msg("Plugin %s loaded with code %d\n",pPlugin->m_pName?pPlugin->m_pName:"unnamed",iRet); + } + else if(!V_stricmp(pCmd,"unload")) + { + int iRet = 0; + const char* pName; + if(engine->Cmd_Argc() < 2) return; + pName = engine->Cmd_Argv(2); + + luaplugin_t* pSelect=NULL,*pPlugin = g_pLua502->FirstPlugin(); + do { + if(!V_stricmp(pPlugin->m_pName,pName)){ + pSelect = pPlugin; + break; + } + } while((pPlugin=pPlugin->m_pNext)); + if(!pSelect) Msg("Plugin not found!\n"); + else + { + char* pModName = strdup(pPlugin->m_pName); + g_pLua502->UnloadPlugin(pPlugin,&iRet); + Msg("Plugin %s unloaded with code %d\n",pModName,iRet); + free(pModName); + } + } + else if(!V_stricmp(pCmd,"debug")) + { + luaplugin_t* pPlugin = g_pLua502->FirstPlugin(); + Msg("m_pFirstPlugin %p m_pNext %p\n",pPlugin, + pPlugin?pPlugin->m_pNext:(luaplugin_t*)0xDEADBEEF); + } \ No newline at end of file diff --git a/lua/lua502/deprecated/filesystem.cpp b/lua/lua502/deprecated/filesystem.cpp new file mode 100644 index 0000000..8567996 --- /dev/null +++ b/lua/lua502/deprecated/filesystem.cpp @@ -0,0 +1,25 @@ +#include "filesystem.h" +#include + +typedef struct { + HMODULE m_hMod; + CreateInterfaceFn m_fnFactory; +} factory_t; + +void* Sys_GetInterface(const char* pModule,const char* pInterface) +{ + HMODULE hMod = NULL; + factory_t ft; + + static std::map s_FactoryList; + if(s_FactoryList.find(pModule)==s_FactoryList.end()) + { + if(!(ft.m_hMod = GetModuleHandle(pModule))) return NULL; + if(!(ft.m_fnFactory = (CreateInterfaceFn)GetProcAddress( + ft.m_hMod,"CreateInterface"))) return NULL; + } + else ft = s_FactoryList[pInterface]; + + if(ft.m_fnFactory) return ft.m_fnFactory(pInterface,NULL); + return NULL; +} \ No newline at end of file diff --git a/lua/lua502/deprecated/filesystem.h b/lua/lua502/deprecated/filesystem.h new file mode 100644 index 0000000..b87dad3 --- /dev/null +++ b/lua/lua502/deprecated/filesystem.h @@ -0,0 +1,65 @@ +#ifndef __FILESYSTEM_H +#define __FILESYSTEM_H + +#include + +typedef int CSysModule; +typedef int FileFindHandle_t; + +#define FILESYSTEM_INTERFACEVERSION "VFileSystem017" +#define FILESYSTEM_MODULE "filesystem_steam.dll" + +typedef void* (*CreateInterfaceFn)(const char*,int*); + +class IFileSystem +{ +public: + virtual void stub_000() = 0; + virtual void stub_001() = 0; + virtual void stub_002() = 0; + virtual void stub_003() = 0; + virtual void stub_004() = 0; + virtual void stub_005() = 0; + virtual void stub_006() = 0; + virtual void stub_007() = 0; + virtual void stub_008() = 0; + virtual void stub_009() = 0; + virtual void stub_010() = 0; + virtual void stub_011() = 0; + virtual void stub_012() = 0; + virtual void stub_013() = 0; + virtual void stub_014() = 0; + virtual void stub_015() = 0; + virtual void stub_016() = 0; + virtual void stub_017() = 0; + virtual void stub_018() = 0; + virtual void stub_019() = 0; + virtual void stub_020() = 0; + virtual void stub_021() = 0; + virtual void stub_022() = 0; + virtual void stub_023() = 0; + virtual void stub_024() = 0; + virtual void stub_025() = 0; + virtual void stub_026() = 0; + virtual void stub_027() = 0; + virtual void stub_028() = 0; + virtual CSysModule* LoadModule(const char *pFileName, + const char *pPathID = 0, bool bValidatedDllOnly = true) = 0; + virtual void UnloadModule(CSysModule* pModule) = 0; + /*virtual CSysModule* LoadModule(const char *pFileName, + const char *pPathID = 0, bool bValidatedDllOnly = true) = 0; + virtual void UnloadModule(CSysModule* pModule) = 0; + virtual const char *FindFirst( const char *pWildCard, FileFindHandle_t *pHandle ) = 0; + virtual const char *FindNext( FileFindHandle_t handle ) = 0; + virtual bool FindIsDirectory( FileFindHandle_t handle ) = 0; + virtual void FindClose( FileFindHandle_t handle ) = 0; + virtual const char *FindFirstEx( + const char *pWildCard, + const char *pPathID, + FileFindHandle_t *pHandle + ) = 0;*/ +}; + +void* Sys_GetInterface(const char* pModule,const char* pInterface); + +#endif \ No newline at end of file diff --git a/lua/lua502/deprecated/interface.cpp b/lua/lua502/deprecated/interface.cpp new file mode 100644 index 0000000..622d515 --- /dev/null +++ b/lua/lua502/deprecated/interface.cpp @@ -0,0 +1,22 @@ +#include "interface.h" + +CInterfaceReg* CInterfaceReg::s_pLast = NULL; + +CInterfaceReg::CInterfaceReg(void* pDst,const char* pName) +{ + m_pDst = pDst; + m_pName = pName; + + m_pNext = s_pLast; + s_pLast = this; +} + +void* CreateInterface(const char* pName,int* pStatus) +{ + CInterfaceReg* pInterfaceReg = CInterfaceReg::s_pLast; + do { + if(!strcmp(pInterfaceReg->m_pName,pName)) + return pInterfaceReg->m_pDst; + } while(pInterfaceReg = pInterfaceReg->s_pLast); + return NULL; +} \ No newline at end of file diff --git a/lua/lua502/deprecated/interface.h b/lua/lua502/deprecated/interface.h new file mode 100644 index 0000000..da9444b --- /dev/null +++ b/lua/lua502/deprecated/interface.h @@ -0,0 +1,23 @@ +#ifndef __INTERFACE_H +#define __INTERFACE_H + +#include +#include + +class CInterfaceReg +{ +public: + CInterfaceReg(void* pDst,const char* pName); + + void* m_pDst; + const char* m_pName; + CInterfaceReg* m_pNext; + + static CInterfaceReg* s_pLast; +}; + +extern "C" __declspec(dllexport) void* CreateInterface(const char* pName,int* pStatus); + +#define EXPORT_INTERFACE(dst,name) CInterfaceReg dst##_Reg(&dst,name) + +#endif \ No newline at end of file diff --git a/lua/lua502/glua.h b/lua/lua502/glua.h new file mode 100644 index 0000000..982473a --- /dev/null +++ b/lua/lua502/glua.h @@ -0,0 +1,97 @@ +#ifndef __GLUA_H +#define __GLUA_H + +#include +#include "tier1/interface.h" +#include "engine/iserverplugin.h" +#define SRCDS + +extern "C" +{ + #include "lua.h" + #include "lauxlib.h" +} + +#ifdef SRCDS +#define GETLUAINTERFACE_SIG "\x68\x00\x00\x00\x00\xFF\xD3\xA1\x00\x00\x00\x00\x83\xC4\x04\x5F\x5E\x5B\x81\xC4\x00\x00\x00\x00" +#define GETLUAINTERFACE_MASK "x????xxx????xxxxxxxx????" +#define GETLUAINTERFACE_OFFSET 0x08 +#else +#define GETLUAINTERFACE_SIG "\xA1\x00\x00\x00\x00\xC3\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\x81\xEC\x00\x00\x00\x00" +#define GETLUAINTERFACE_MASK "x????xxxxxxxxxxxxx????" +#define GETLUAINTERFACE_OFFSET 0x01 +#endif + +#define CREATEGLUA_SIG "\x81\xEC\x00\x00\x00\x00\x53\x56\x8B\x35\x00\x00\x00\x00\x57\x33\xFF\x3B\xF7\x74\x49" +#define CREATEGLUA_MASK "xx????xxxx????xxxxxxx" +#define CREATEGLUA_OFFSET 0x0A +#define CREATEGLUA_HOOKSIZE 0x06 + +class ILua502; +class ILuaPluginCallbacks : public IServerPluginCallbacks +{ +public: + virtual bool GlobalInit(ILua502*) = 0; + virtual bool LuaInit(lua_State*) = 0; + virtual void OnSWEPLuaCreate(lua_State*) = 0; +}; + +class CLuaInterface +{ +public: + lua_State* m_pL; +}; + +typedef enum { + LUAFILE_OK = 0, + LUAFILE_MEM_FAULT, + LUAFILE_LUA_ERROR, + LUAFILE_DUMP_FAULT, + LUAFILE_LFC_FAULT, +} luafile_err_t; + +typedef struct { + char m_szName[128]; + bool m_bDisabled; + ILuaPluginCallbacks* m_pCallbacks; + int m_iVersion; + CSysModule* m_pModule; +} luaplugin_t; + +class ILua502Callbacks +{ +public: + virtual int OnLuaPanic(lua_State* L) = 0; + virtual int OnLuaError(lua_State* L) = 0; + + virtual void OnPluginLoad(luaplugin_t* pPlug) = 0; + virtual void OnPluginUnload(luaplugin_t* pPlug) = 0; + + virtual void OnLuaCreate(CLuaInterface*) = 0; + virtual void OnSWEPLuaCreate(CLuaInterface*) = 0; +}; + +class ILua502 +{ +public: + virtual bool LoadPlugin(const char* pName,int* pPlugin) = 0; + virtual void UnloadPlugin(int iPlugin) = 0; + + virtual luaplugin_t* GetPlugin(int iPlugin) = 0; + virtual const char* RunString(const char* pCode,size_t len,const char* pName) = 0; + + virtual CLuaInterface* GetLuaInterface() = 0; + virtual void Print(const char* fmt,...) = 0; + + virtual luafile_err_t RunFile(const char* pFile,const char** ppErr = NULL, + lua_State* pL = NULL) = 0; + + virtual void SetLuaCallbacks(ILua502Callbacks* pCallbacks) = 0; + virtual ILua502Callbacks* GetLuaCallbacks() = 0; + + virtual void Lock() = 0; + virtual void Unlock() = 0; +}; +#define INTERFACEVERSION_LUA502 "LUA502_001" + +#endif \ No newline at end of file diff --git a/lua/lua502/keyvalues.cpp b/lua/lua502/keyvalues.cpp new file mode 100644 index 0000000..37fef7f --- /dev/null +++ b/lua/lua502/keyvalues.cpp @@ -0,0 +1,149 @@ +#include "baselib.h" +#include "keyvalues.h" +#include "filesystem.h" + +DECLARE_LIBRARY("keyvalues") +DECLARE_TABLE(keyvalues) +extern IFileSystem* filesystem; + +//void print_stack(lua_State* L) +//{ +// for(int i = lua_gettop(L); i > 0; i--) +// Msg("%d: %s (%s)\n",i,lua_tostring(L,i),lua_typename(L,lua_type(L,i))); +//} + +void KeyValuesFromTable(lua_State* L,int idx,KeyValues* pKV) +{ + lua_pushvalue(L,idx); + lua_pushnil(L); + while(lua_next(L,-2)) + { + int iKeyType = lua_type(L,-2); + if(iKeyType != LUA_TSTRING && iKeyType != LUA_TNUMBER && iKeyType != LUA_TTABLE) + { + lua_pop(L,1); + continue; + } + + lua_pushvalue(L,-2); + //Key -1, Value -2, Old Key -3, Table -4 + int iType = lua_type(L,-2); + + char* pKey; + char cSwap = ' '; + if(iKeyType == LUA_TTABLE) + { + cSwap = 'T'; + lua_insert(L,-2); + iKeyType = lua_type(L,-1); + iType = lua_type(L,-2); + } + + if(iKeyType == LUA_TSTRING) + { + int iLen = lua_strlen(L,-1)+4; + pKey = new char[iLen]; + sprintf(pKey,"S%c%s",cSwap,lua_tostring(L,-1)); + } + else if(iKeyType == LUA_TNUMBER) + { + pKey = new char[32]; + memset(pKey,'\0',32); + sprintf(pKey,"N%c%lf",cSwap,lua_tonumber(L,-1)); + } + + KeyValues* pSub = NULL; + switch(iType) + { + case LUA_TBOOLEAN: + pKV->SetInt(pKey,lua_tonumber(L,-2)); + break; + case LUA_TNUMBER: + pKV->SetFloat(pKey,lua_tonumber(L,-2)); + break; + case LUA_TFUNCTION: + /*sprintf(szBuf,"0x%p",lua_tocfunction(L,-2)); + pKV->SetString(pKey,szBuf); + break;*/ + case LUA_TTHREAD: + case LUA_TUSERDATA: + case LUA_TSTRING: + pKV->SetString(pKey,lua_tostring(L,-2)); + break; + case LUA_TTABLE: + if(!lua_rawequal(L,-2,-4)) + { + pSub = pKV->FindKey(pKey,true); + KeyValuesFromTable(L,-2,pSub); + } + break; + } + delete[] pKey; + lua_pop(L,2); + } + lua_pop(L,1); +} + +DECLARE_FUNCTION(keyvalues,SaveTable) +{ + luaL_checktype(L,1,LUA_TTABLE); + luaL_checktype(L,2,LUA_TSTRING); + luaL_checktype(L,3,LUA_TSTRING); + KeyValues* pKV = new KeyValues(lua_tostring(L,2)); + KeyValuesFromTable(L,1,pKV); + pKV->SaveToFile(filesystem,lua_tostring(L,3),"MOD"); + pKV->deleteThis(); + return 0; +} + +void KeyValuesToTable(lua_State* L,KeyValues* pKV) +{ + lua_newtable(L); + for(KeyValues* sub = pKV->GetFirstSubKey(); sub; sub = sub->GetNextKey()) + { + const char* pName0 = sub->GetName(); + const char* pName = pName0+2; + bool bSwap = false; + if(pName0[0] == 'S') + lua_pushstring(L,pName); + else if(pName0[0] == 'N') + lua_pushnumber(L,atof(pName)); + bSwap = (pName0[1] == 'T'); + + if(sub->GetFirstSubKey()) + KeyValuesToTable(L,sub); + else + { + switch(pKV->GetDataType(pName0)) + { + case KeyValues::TYPE_STRING: + lua_pushstring(L,sub->GetString()); + break; + case KeyValues::TYPE_INT: + lua_pushnumber(L,sub->GetInt()); + break; + case KeyValues::TYPE_UINT64: + lua_pushnumber(L,sub->GetUint64()); + break; + case KeyValues::TYPE_FLOAT: + lua_pushnumber(L,sub->GetFloat()); + break; + default: + lua_pushnil(L); + } + } + if(bSwap) lua_insert(L,-2); + lua_settable(L,-3); + } +} + +DECLARE_FUNCTION(keyvalues,LoadTable) +{ + luaL_checktype(L,1,LUA_TSTRING); + luaL_checktype(L,2,LUA_TSTRING); + KeyValues* pKV = new KeyValues(lua_tostring(L,1)); + pKV->LoadFromFile(filesystem,lua_tostring(L,2),"MOD"); + KeyValuesToTable(L,pKV); + pKV->deleteThis(); + return 1; +} \ No newline at end of file diff --git a/lua/lua502/lua502.vcxproj b/lua/lua502/lua502.vcxproj new file mode 100644 index 0000000..bf19a6b --- /dev/null +++ b/lua/lua502/lua502.vcxproj @@ -0,0 +1,143 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {C78BB0F3-3952-4F64-8DF7-2C0D16A6D03A} + lua502 + + + + Application + true + MultiByte + + + DynamicLibrary + false + true + MultiByte + + + + + + + + + + + + + ..\..\..\GMod9Dev_Server\gmod9\addons + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + true + true + ..\..\..\source2006\utils\lzma\;..\..\..\source2006\common\lzma;..\..\..\lua502\src;..\..\..\lua502\include;..\..\..\source2006\public\tier1;..\..\..\source2006\public\tier0;..\..\..\source2006\public;..\..\..\source2006\cl_dll;..\..\..\source2006\game_shared;..\..\..\source2006\common;%(AdditionalIncludeDirectories) + LUA_DLL;%(PreprocessorDefinitions) + + + true + true + true + ..\..\..\source2006\lib\common;..\..\..\source2006\lib\public;%(AdditionalLibraryDirectories) + vstdlib.lib;tier0.lib;tier1.lib;lzma.lib;%(AdditionalDependencies) + LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) + /FORCE:MULTIPLE %(AdditionalOptions) + + + copy "..\..\..\GMod9Dev_Server\gmod9\addons\lua502.lib" "..\Release\lua502.lib" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lua/lua502/lua502.vcxproj.filters b/lua/lua502/lua502.vcxproj.filters new file mode 100644 index 0000000..f7e8a55 --- /dev/null +++ b/lua/lua502/lua502.vcxproj.filters @@ -0,0 +1,225 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {92fe988e-bec3-412f-a518-ccecb06bbe74} + + + {eb0cbb39-3151-415e-af4e-acbd54aa93a7} + + + {c0fcb113-4e1e-4b35-a3f4-428f3f96b8b0} + + + {9cd203b9-2b96-436d-b3a3-2752ebe9c5ef} + + + {d77027e6-f3e9-4b27-92b0-850e1670c5e3} + + + + + sdk + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + interface + + + Файлы иÑходного кода + + + lualib + + + lua\lib + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lualib + + + lualib + + + lualib + + + lualib + + + lualib + + + sdk + + + lualib + + + lualib + + + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + lua + + + sdk + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + lualib + + + lualib + + + lualib + + + lualib + + + sdk + + + \ No newline at end of file diff --git a/lua/lua502/lua502.vcxproj.user b/lua/lua502/lua502.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/lua/lua502/lua502.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lua/lua502/luafile.cpp b/lua/lua502/luafile.cpp new file mode 100644 index 0000000..1b5180a --- /dev/null +++ b/lua/lua502/luafile.cpp @@ -0,0 +1,380 @@ +#include "luafile.h" +#include "plugin.h" +#include "tier1/bitbuf.h" +#include "tier0/memdbgon.h" + +const char* g_pLuaFileErrors[] = { + "LUAFILE_OK", + "LUAFILE_MEM_FAULT", + "LUAFILE_LUA_ERROR", + "LUAFILE_DUMP_FAULT", + "LUAFILE_LFC_FAULT" +}; + +CUtlVector CLuaFile::s_Cache; + +bool CLuaFile::Init() +{ + if(!filesystem->FileExists("cache/",CACHE_PATHID)) + filesystem->CreateDirHierarchy("cache/",CACHE_PATHID); + if(filesystem->FileExists(CACHE_INDEX,CACHE_PATHID)) + { + FileHandle_t fCache; + unsigned int uSize; + unsigned short nNum; + void* pMem; + + if(!(fCache = filesystem->Open(CACHE_INDEX,"rb",CACHE_PATHID))) + { + Warning("Failed to open " CACHE_INDEX "\n"); + return false; + } + if(!(uSize = filesystem->Size(fCache))) return true; + if(!(pMem = malloc(uSize))) return false; + + filesystem->Read(pMem,uSize,fCache); + filesystem->Close(fCache); + + bf_read bf = bf_read(pMem,uSize); + nNum = bf.ReadShort(); + if(!nNum) + { + free(pMem); + Msg("Cache file is empty o.0\n"); + return true; + } + + for(unsigned short i = 0; i < nNum; i++) + { + cachenode_t cache; + + bf.ReadString(cache.m_szName,MAX_PATH); + cache.m_uSize = bf.ReadLong(); + cache.m_lTime = bf.ReadLong(); + + s_Cache.AddToTail(cache); + } + + free(pMem); + } + return true; +} + +void CLuaFile::ClearCache() +{ + char szFileName[MAX_PATH]; + for(int i = 0; i < s_Cache.Size(); i++) + { + sprintf(szFileName,CACHE_FORMAT,s_Cache[i].m_lTime); + if(filesystem->FileExists(szFileName,CACHE_PATHID)) + filesystem->RemoveFile(szFileName,CACHE_PATHID); + } + s_Cache.RemoveAll(); + filesystem->RemoveFile(CACHE_INDEX,CACHE_PATHID); +} + +/*unsigned long CLuaFile::Hash(unsigned char* pData,size_t iLen) +{ + unsigned long h = 5381; + while(iLen--) + h+=(h<<5)+*pData++; + return h; +}*/ + +CLuaFile::CLuaFile(lua_State* pL,const char* pPath) +{ + if(!filesystem->FileExists(pPath,CACHE_PATHID)) return; + V_strncpy(m_CacheNode.m_szName,pPath,MAX_PATH); + this->L = pL; + m_bCached = false; +} + +void CLuaFile::LoadFromFile() +{ + FileHandle_t fFile; + if(!filesystem->FileExists(m_CacheNode.m_szName)) + { + Warning("File %s doesn't exists!\n",m_CacheNode.m_szName); + return; + } + + m_pMem = (unsigned char*)malloc(m_CacheNode.m_uSize+1); + m_pMem[m_CacheNode.m_uSize] = 0; + if(!m_pMem) + { + Warning("Not enough memory for lua file!\n"); + return; + } + if(!(fFile = filesystem->Open(m_CacheNode.m_szName,"rb",CACHE_PATHID))) + { + Warning("Failed to open lua file!\n"); + free(m_pMem); + return; + } + + filesystem->Read(m_pMem,m_CacheNode.m_uSize,fFile); + //m_CacheNode.m_ulHash = Hash(m_pMem,m_CacheNode.m_uSize); + filesystem->Close(fFile); +} + +luafile_err_t CLuaFile::Load(const char** ppErr) +{ + char szFileName[MAX_PATH]; + m_pMem = NULL; + m_bCached = false; + m_iOldCacheNode = -1; + + //It must be initialized here, not in LoadFromFile + m_CacheNode.m_uSize = filesystem->Size( + m_CacheNode.m_szName,CACHE_PATHID); + m_CacheNode.m_lTime = filesystem->GetFileTime( + m_CacheNode.m_szName,CACHE_PATHID); + sprintf(szFileName,CACHE_FORMAT,m_CacheNode.m_lTime); + if(s_Cache.Size()) + { + for(int i = 0; i < s_Cache.Size(); i++) + { + cachenode_t& cache = s_Cache[i]; + /*if(!V_strcmp(cache.m_szName,m_CacheNode.m_szName) + && cache.m_lTime == m_CacheNode.m_lTime) + m_bCached = true;*/ + if(!V_strcmp(cache.m_szName,m_CacheNode.m_szName)) + { + m_bCached = true; + m_iOldCacheNode = ((cache.m_lTime==m_CacheNode.m_lTime) + &&(cache.m_uSize==m_CacheNode.m_uSize))?-1:i; + break; + } + } + } + else m_bCached = false; + /*if(!m_pMem) LoadFromFile(); + m_bCached = (cache.m_ulHash == m_CacheNode.m_ulHash);*/ + + //if m_Cached = false or need update of cached + if(!m_bCached||m_iOldCacheNode!=-1) + { + memarea_t luaCp; + LoadFromFile(); + if(!m_pMem) + { + Warning("FATAL: m_pMem = NULL!\n"); + return LUAFILE_MEM_FAULT; + } + luaCp.m_pMem = NULL; + luaCp.m_iLen = 0; + const char* pErr = Compile(&luaCp); //In m_pMem must be lua code! + free(m_pMem); //Free lua code, 'cuz we have compiled lua + if(pErr) + { + Warning("Lua Error: %s\n",pErr); + return LUAFILE_LUA_ERROR; + } + if(!luaCp.m_pMem) + { + Warning("lua_dump FATAL ERROR!!!!!\n"); + return LUAFILE_DUMP_FAULT; + } + DumpCache(&luaCp); + free(luaCp.m_pMem); + //We ready to launch code + } + else if(m_iOldCacheNode==-1) //Run from cache if EXACLY same file + { + Msg("Found in cache!\n"); + if(!LoadFromCache(ppErr)) + { + Warning("LoadFromCache failed\n"); + return LUAFILE_LFC_FAULT; + } + } + return LUAFILE_OK; +} + +bool CLuaFile::LoadFromCache(const char** pErr) +{ + FileHandle_t fLua; + char szFileName[MAX_PATH]= {0}; + //sprintf(szFileName,CACHE_FORMAT,m_CacheNode.m_lTime); + sprintf_s(szFileName,CACHE_FORMAT,m_CacheNode.m_lTime); + size_t uSize; + if(!filesystem->FileExists(szFileName,CACHE_PATHID)) + { + Warning("Cache file %s not found\n",szFileName); + return false; + } + if(!(uSize = filesystem->Size(szFileName,CACHE_PATHID))) + { + Warning("Lua cache file is empty!\n"); + return false; + } + if(!(m_pMem = (unsigned char*)malloc(uSize))) + { + Warning("Allocate memory for lua cache failed!\n"); + return false; + } + if(!(fLua = filesystem->Open(szFileName,"rb",CACHE_PATHID))) + { + Warning("Failed to open file %s!\n",szFileName); + return false; + } + filesystem->Read(m_pMem,uSize,fLua); + filesystem->Close(fLua); + + if(!Uncompress(&uSize)) + { + Warning("Uncompress failed!\n"); + return false; + } + //m_pMem holds lua bytecode + if(luaL_loadbuffer(L,(const char*)m_pMem,uSize,"CLuaFileCached")) + { + if(pErr) *pErr = lua_tostring(L,-1); + lua_pop(L,1); + free(m_pMem); + return false; + } + + free(m_pMem); + return true; +} + +void CLuaFile::Compress(memarea_t* pMemArea) +{ + //We don't need compression for small files + if(pMemArea->m_iLen<1024) return; + if(!pMemArea->m_pMem) return; + size_t uLen; + unsigned char* pCompressed; + if((pCompressed=LZMA_Compress((unsigned char*)pMemArea->m_pMem,pMemArea->m_iLen, + &uLen))) + { + free(pMemArea->m_pMem); + pMemArea->m_pMem = pCompressed; + pMemArea->m_iLen = uLen; + } +} + +bool CLuaFile::Uncompress(size_t* uLen) +{ + //m_pMem holds compressed stuff + if(!LZMA_IsCompressed(m_pMem)) return true; + unsigned char* pMem; + if(!LZMA_Uncompress(m_pMem,&pMem,uLen)) + return false; + else + { + free(m_pMem); + m_pMem = pMem; + } + return true; +} + +void CLuaFile::DumpCache(memarea_t* pMemArea) +{ + char szFileName[MAX_PATH]; + sprintf(szFileName,CACHE_FORMAT,m_CacheNode.m_lTime); + + FileHandle_t fCacheFile; + if(!(fCacheFile = filesystem->Open(szFileName,"wb",CACHE_PATHID))) + { + Warning("Failed to open %s!\n",szFileName); + return; + } + + Compress(pMemArea); + filesystem->Write(pMemArea->m_pMem,pMemArea->m_iLen,fCacheFile); + filesystem->Close(fCacheFile); + + if(m_iOldCacheNode!=-1) + { + Msg("Updating %s...\n",s_Cache[m_iOldCacheNode].m_szName); + ReUpdate(); + } + s_Cache.AddToTail(m_CacheNode); + if(!UpdateCacheFile()) + Warning("Failed to update "CACHE_INDEX,"\n"); +} + +static int writer(lua_State* L, const void* p, size_t size, void* u) +{ + UNUSED(L); + memarea_t* pMemArea = (memarea_t*)u; + if(!pMemArea->m_pMem) pMemArea->m_pMem = malloc(size); + else pMemArea->m_pMem = realloc(pMemArea->m_pMem,pMemArea->m_iLen+size); + memcpy(((char*)pMemArea->m_pMem+pMemArea->m_iLen),p,size); + pMemArea->m_iLen += size; + return size != 0; +} + +/* +static Proto* toproto(lua_State* L, int i) +{ + const Closure* c=(const Closure*)lua_topointer(L,i); + return c->l.p; +}*/ + +const char* CLuaFile::Compile(memarea_t* pMemArea) +{ + //m_pMem holds lua code + const char* pErr = NULL; + + if(luaL_loadbuffer(L,(const char*)m_pMem,V_strlen((const char*)m_pMem),"CLuaFile")) + { + pErr = lua_tostring(L,-1); + lua_pop(L,1); + return pErr; + } + + /*Proto* f = toproto(L,-1); + luaU_dump(L,f,writer,pMemArea);*/ + lua_dump(L,writer,pMemArea); + return pErr; +} + +bool CLuaFile::UpdateCacheFile() +{ + int iSize; + if(!(iSize=s_Cache.Size())) return true; + FileHandle_t fCache; + if(!(fCache = filesystem->Open(CACHE_INDEX,"wb",CACHE_PATHID))) + { + Warning("CLuaFile::UpdateCacheFile file "CACHE_INDEX" unavaible\n"); + return false; + } + + //cachenode_t* pCacheNode = (cachenode_t*)malloc(sizeof(cachenode_t)); + size_t uMaxSize = s_Cache.Size()*sizeof(cachenode_t); + cachenode_t* pCacheNodes = (cachenode_t*)malloc(uMaxSize); + bf_write bf = bf_write(pCacheNodes,uMaxSize); + bf.WriteShort(iSize); + for(int i = 0; i < iSize; i++) + { + cachenode_t& cache = s_Cache[i]; + bf.WriteString(cache.m_szName); + bf.WriteLong(cache.m_uSize); + bf.WriteLong(cache.m_lTime); + } + + filesystem->Write(bf.GetData(),bf.GetNumBytesWritten(),fCache); + filesystem->Close(fCache); + free(pCacheNodes); + return true; +} + +void CLuaFile::ReUpdate() +{ + char szFileName[MAX_PATH]; + sprintf(szFileName,CACHE_FORMAT,s_Cache[m_iOldCacheNode].m_lTime); + if(filesystem->FileExists(szFileName,CACHE_PATHID)) + filesystem->RemoveFile(szFileName,CACHE_PATHID); + s_Cache.Remove(m_iOldCacheNode); +} + +void CLuaFile::Execute() +{ + lua_pushcfunction(L,lua502_aterror); + lua_insert(L,-2); + lua_pcall(L,0,LUA_MULTRET,lua_gettop(L)-1); + lua_pop(L,1); +} \ No newline at end of file diff --git a/lua/lua502/luafile.h b/lua/lua502/luafile.h new file mode 100644 index 0000000..ac184d3 --- /dev/null +++ b/lua/lua502/luafile.h @@ -0,0 +1,69 @@ +#ifndef __LUAFILE_H +#define __LUAFILE_H + +#include "glua.h" +#include "filesystem.h" +#include "tier1/utlvector.h" +#include "lzma/lzma.h" + +#include "lapi.h" +#include "lfunc.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstring.h" +#include "lundump.h" + +#define CACHE_INDEX "cache/index.dat" +#define CACHE_PATHID "MOD" +#define CACHE_FORMAT "cache/%08X.dat" + +typedef struct { + void* m_pMem; + size_t m_iLen; +} memarea_t; + +class CLuaFile +{ +public: + enum luasrc_e { + LUA_INTERPRET, + LUA_CACHE, + }; + + typedef struct { + char m_szName[MAX_PATH]; + unsigned int m_uSize; + long m_lTime; + //unsigned long m_ulHash; + } cachenode_t; + + CLuaFile(lua_State* L,const char* pPath); + + luafile_err_t Load(const char** ppErr); + void LoadFromFile(); + bool LoadFromCache(const char** pErr); + const char* Compile(memarea_t* pMemArea); + bool IsCached(); + void Compress(memarea_t* pMemArea); + bool Uncompress(size_t* uLen); + void DumpCache(memarea_t* pMemArea); + void ReUpdate(); + void Execute(); + + cachenode_t m_CacheNode; + unsigned char* m_pMem; + lua_State* L; + int m_iOldCacheNode; + bool m_bCached; + + //static unsigned long Hash(unsigned char* pData,size_t iLen); + static bool Init(); + static void ClearCache(); + static bool UpdateCacheFile(); + static CUtlVector s_Cache; +}; + +extern const char* g_pLuaFileErrors[]; + +#endif \ No newline at end of file diff --git a/lua/lua502/luapointer.cpp b/lua/lua502/luapointer.cpp new file mode 100644 index 0000000..67b2f02 --- /dev/null +++ b/lua/lua502/luapointer.cpp @@ -0,0 +1,57 @@ +#include "luapointer.h" +#include "baselib.h" +#include "types.h" + +DECLARE_LIBRARY("ptrlib"); +DECLARE_METATABLE(ptrmeta,POINTER); + +/*void luaf_makepointer(lua_State* L,void* pPtr) +{ + luaL_createuserdata(L,s_iType,pPtr); +}*/ + +void luaf_makepointer(lua_State* L,void* pPtr) +{ + void** ppPtr = (void**)luaL_createuserdata(L,sizeof(void*), + &g_LuaTable_ptrmeta); + *ppPtr = pPtr; +} + +DECLARE_FUNCTION(ptrmeta,__tostring) +{ + void** ppPtr; + if((ppPtr=(void**)luaf_checkuserdata(L,1,&g_LuaTable_ptrmeta))) + luaL_pushfstring(L,"Pointer %p",*ppPtr); + else lua_pushnil(L); + return 1; +} + +DECLARE_FUNCTION(ptrmeta,__add) +{ + void** pOne = (void**)luaf_checkuserdata(L,1,&g_LuaTable_ptrmeta), + **pTwo = (void**)luaf_checkuserdata(L,2,&g_LuaTable_ptrmeta); + if(!pOne || !pTwo) lua_pushnil(L); + else + luaf_makepointer(L,((char*)*pOne+(int)*pTwo)); + return 1; +} + +DECLARE_FUNCTION(ptrmeta,__sub) +{ + void** pOne = (void**)luaf_checkuserdata(L,1,&g_LuaTable_ptrmeta), + **pTwo = (void**)luaf_checkuserdata(L,2,&g_LuaTable_ptrmeta); + if(!pOne || !pTwo) lua_pushnil(L); + else + luaf_makepointer(L,((char*)*pOne-(int)*pTwo)); + return 1; +} + +DECLARE_FUNCTION(ptrmeta,__eq) +{ + void** pOne = (void**)luaf_checkuserdata(L,1,&g_LuaTable_ptrmeta), + **pTwo = (void**)luaf_checkuserdata(L,2,&g_LuaTable_ptrmeta); + if(!pOne || !pTwo) lua_pushboolean(L,false); + else + lua_pushboolean(L,(*pOne==*pTwo)); + return 1; +} \ No newline at end of file diff --git a/lua/lua502/luapointer.h b/lua/lua502/luapointer.h new file mode 100644 index 0000000..ae59f09 --- /dev/null +++ b/lua/lua502/luapointer.h @@ -0,0 +1,8 @@ +#ifndef __LUAPOINTER_H +#define __LUAPOINTER_H + +#include "glua.h" + +void luaf_makepointer(lua_State* L,void* pPtr); + +#endif \ No newline at end of file diff --git a/lua/lua502/lzmalib.cpp b/lua/lua502/lzmalib.cpp new file mode 100644 index 0000000..dd5448f --- /dev/null +++ b/lua/lua502/lzmalib.cpp @@ -0,0 +1,65 @@ +#include "baselib.h" +#include "lzma/lzma.h" +#include "tier0/memdbgon.h" + +DECLARE_LIBRARY("LzmaLib"); +DECLARE_TABLE(lzma); + +size_t g_uDictSize = 18U; + +DECLARE_FUNCTION(lzma,SetDictionarySize) +{ + luaL_checktype(L,1,LUA_TNUMBER); + g_uDictSize = (size_t)lua_tonumber(L,1); + return 0; +} + +DECLARE_FUNCTION(lzma,Compress) +{ + luaL_checktype(L,1,LUA_TSTRING); + + const char* pStr = lua_tostring(L,1); + size_t iLen = lua_strlen(L,1),uLen = 0; + if(!iLen) return 0; + + unsigned char* pCompressed; + if(!(pCompressed = LZMA_Compress((unsigned char*)pStr,iLen,&uLen,g_uDictSize))) + lua_pushnil(L); + else + { + lua_pushlstring(L,(const char*)pCompressed,uLen); + lua_pushnumber(L,uLen); + free(pCompressed); + return 2; + } + return 1; +} + +DECLARE_FUNCTION(lzma,IsCompressed) +{ + luaL_checktype(L,1,LUA_TSTRING); + unsigned char* pBuf = (unsigned char*)lua_tostring(L,1); + lua_pushboolean(L,LZMA_IsCompressed(pBuf)); + return 1; +} + +DECLARE_FUNCTION(lzma,Uncompress) +{ + luaL_checktype(L,1,LUA_TSTRING); + size_t uLen = 0; + unsigned char* pOut,*pBuf = (unsigned char*)lua_tostring(L,1); + if(!LZMA_IsCompressed(pBuf)) + lua_pushnil(L); + else + { + if(!LZMA_Uncompress(pBuf,&pOut,&uLen)) lua_pushnil(L); + else + { + lua_pushlstring(L,(const char*)pOut,uLen); + lua_pushnumber(L,uLen); + free(pOut); + return 2; + } + } + return 1; +} \ No newline at end of file diff --git a/lua/lua502/mainlib.cpp b/lua/lua502/mainlib.cpp new file mode 100644 index 0000000..198dbf1 --- /dev/null +++ b/lua/lua502/mainlib.cpp @@ -0,0 +1,270 @@ +#include "glua.h" +#include "plugin.h" +#include "baselib.h" +#include "types.h" +#include "luapointer.h" + +static int s_iType = LUAPLUGIN; + +DECLARE_LIBRARY("mainlib"); +/*DECLARE_METATABLE(metaplugin,s_iType); + +static luaplugin_t* luaf_makeplugin(lua_State* L,luaplugin_t* pPlug) +{ + luaplugin_t* pPlug2 = (luaplugin_t*)luaL_createuserdata(L,sizeof(luaplugin_t), + &g_LuaTable_metaplugin); + V_memcpy(pPlug2,pPlug,sizeof(luaplugin_t)); //Protect plugin + return pPlug2; +} + +DECLARE_FUNCTION(metaplugin,__tostring) +{ + luaplugin_t* pPlug = (luaplugin_t*)luaf_checkuserdata(L,1,&g_LuaTable_metaplugin); + if(!pPlug) lua_pushnil(L); + else luaL_pushfstring(L,"luaplugin_t %s",pPlug->m_pName); + return 1; +} + +DECLARE_FUNCTION(metaplugin,__eq) +{ + luaplugin_t* pOne,*pTwo; + if(!(pOne = (luaplugin_t*)luaf_checkuserdata(L,1,&g_LuaTable_metaplugin)) + || (pTwo = (luaplugin_t*)luaf_checkuserdata(L,2,&g_LuaTable_metaplugin))) + lua_pushboolean(L,false); + else lua_pushboolean(L,(pOne->m_hModule==pTwo->m_hModule)); + return 1; +} + +DECLARE_FUNCTION(metaplugin,__gc) +{ + return 0; +} + +DECLARE_FUNCTION(metaplugin,GetName) +{ + luaplugin_t* pPlug = (luaplugin_t*)luaf_checkuserdata(L,1, + &g_LuaTable_metaplugin); + if(!pPlug) lua_pushnil(L); + else lua_pushstring(L,pPlug->m_pName); + return 1; +} + +DECLARE_FUNCTION(metaplugin,GetAPIVersion) +{ + luaplugin_t* pPlug = (luaplugin_t*)luaf_checkuserdata(L,1, + &g_LuaTable_metaplugin); + if(!pPlug) lua_pushnil(L); + else lua_pushnumber(L,pPlug->m_iPluginAPI); + return 1; +} + +DECLARE_FUNCTION(metaplugin,GetInitExit) +{ + luaplugin_t* pPlug = (luaplugin_t*)luaf_checkuserdata(L,1, + &g_LuaTable_metaplugin); + if(!pPlug) + { + lua_pushnil(L); + lua_pushnil(L); + } + else + { + luaf_makepointer(L,pPlug->m_fnInit); + luaf_makepointer(L,pPlug->m_fnExit); + } + return 2; +} + +DECLARE_FUNCTION(metaplugin,GetNext) +{ + luaplugin_t* pPlug = (luaplugin_t*)luaf_checkuserdata(L,1, + &g_LuaTable_metaplugin); + if(!pPlug) + { + lua_pushnil(L); + lua_pushnil(L); + } + else + { + if(!pPlug->m_pNext) + { + lua_pushnil(L); + lua_pushboolean(L,false); + } + else + { + luaf_makeplugin(L,pPlug->m_pNext); + lua_pushboolean(L,true); + } + } + return 2; +} + +DECLARE_FUNCTION(metaplugin,Unload) +{ + luaplugin_t* pPlug = (luaplugin_t*)luaf_checkuserdata(L,1, + &g_LuaTable_metaplugin); + luaplugin_t* pIter = NULL,*pTarget = NULL; + int iRet = 0; + if(!pPlug) + { + lua_pushnil(L); + lua_pushnil(L); + return 2; + } + + pIter = g_pLua502->FirstPlugin(); + while(pIter) + { + if(pPlug->m_fnInit == pIter->m_fnInit + && pPlug->m_fnExit == pIter->m_fnExit + && !V_strcmp(pPlug->m_pName,pIter->m_pName)) + { + pTarget = pIter; + break; + } + pIter = pIter->m_pNext; + } + + if(!pTarget) + { + lua_pushnil(L); + lua_pushnil(L); + return 2; + } + + lua_pushboolean(L,(!g_pLua502->UnloadPlugin(pTarget,&iRet))); + lua_pushnumber(L,iRet); + return 2; +}*/ + +DECLARE_TABLE(lua502); + +//DECLARE_FUNCTION(lua502,GetAPIVersion) +//{ +// lua_pushnumber(L,LUAPLUGIN_API); +// return 1; +//} + +DECLARE_FUNCTION(lua502,Print) +{ + g_pLua502->Print("%s\n",lua_tostring(L,1)); + return 0; +} + +DECLARE_FUNCTION(lua502,RunString) +{ + const char* pErr = NULL,*pCode; + size_t uLen; + luaL_checktype(L,1,LUA_TSTRING); + + pCode = lua_tostring(L,1); + uLen = lua_strlen(L,1); + + if((pErr=g_pLua502->RunString(pCode,uLen,"LUA"))) + lua_pushstring(L,pErr); + else lua_pushnil(L); + return 1; +} + +DECLARE_FUNCTION(lua502,RunFile) +{ + luaL_checktype(L,1,LUA_TSTRING); + luafile_err_t iErr; + const char* pErr; + char szLuaPath[MAX_PATH]; + + sprintf(szLuaPath,"lua/%s",lua_tostring(L,1)); + if(!CLua502Plugin::IsPathSecure(szLuaPath)) + { + luaL_error(L,"Path may not contain specific symbols!"); + lua_pushnil(L); + lua_pushnil(L); + return 2; + } + + if((iErr = g_pLua502->RunFile(szLuaPath,&pErr))) + { + lua_pushnumber(L,iErr); + if(iErr == LUAFILE_LUA_ERROR) + lua_pushstring(L,pErr); + else lua_pushnil(L); + return 2; + } + + lua_pushnil(L); + lua_pushnil(L); + return 2; +} + +DECLARE_FUNCTION(lua502,GetLuaInterface) +{ + luaf_makepointer(L,g_pLua502->GetLuaInterface()); + return 1; +} + +DECLARE_FUNCTION(lua502,LoadPlugin) +{ + int iPlugin = 0; + luaL_checktype(L,1,LUA_TSTRING); + if(g_pLua502->LoadPlugin(lua_tostring(L,1), + &iPlugin)) + lua_pushnumber(L,iPlugin); + else lua_pushnil(L); + return 1; +} + +DECLARE_FUNCTION(lua502,UnloadPlugin) +{ + luaL_checktype(L,1,LUA_TNUMBER); + g_pLua502->UnloadPlugin( + lua_tonumber(L,1)); + return 0; +} + +DECLARE_FUNCTION(lua502,GetRegistry) +{ + lua_pushvalue(L,LUA_REGISTRYINDEX); + return 1; +} + +/*class CMainLibrary : public CLuaLibrary +{ +public: + CMainLibrary() : CLuaLibrary("main") + { + m_iRefOpenScript = 0; + } + + virtual void Register(lua_State* L) + { + lua_pushstring(L,"_OpenScript"); + lua_rawget(L,LUA_GLOBALSINDEX); + m_iRefOpenScript = lua_refobj(L); + + lua_pushstring(L,"print"); + lua_pushcfunction(L,g_lua502Print.m_fnFunc); + lua_rawset(L,LUA_GLOBALSINDEX); + + lua_pushstring(L,"_OpenScript"); + lua_pushcfunction(L,g_lua502RunFile.m_fnFunc); + lua_rawset(L,LUA_GLOBALSINDEX); + } + + virtual void Unregister(lua_State* L) + { + lua_pushstring(L,"_OpenSript"); + lua_pushref(L,m_iRefOpenScript); + lua_rawset(L,LUA_GLOBALSINDEX); + + lua_pushstring(L,"print"); + lua_pushnil(L); + lua_rawset(L,LUA_GLOBALSINDEX); + + lua_unrefobj(L,m_iRefOpenScript); + } + + int m_iRefOpenScript; +}; + +static CMainLibrary g_MainLibrary;*/ \ No newline at end of file diff --git a/lua/lua502/plugin.cpp b/lua/lua502/plugin.cpp new file mode 100644 index 0000000..5c76c7b --- /dev/null +++ b/lua/lua502/plugin.cpp @@ -0,0 +1,563 @@ +#include +#include +#include +#include +#include +#include "plugin.h" +#include "sigscan.h" +#include "svar.h" +#include "luafile.h" +#include "baselib.h" +#include "eiface.h" +#include "tier1/interface.h" +#include "tier0/dbg.h" +#include "tier0/memdbgon.h" + +CLua502Plugin g_Lua502Plugin; +ILua502* g_pLua502 = (ILua502*)&g_Lua502Plugin; +IFileSystem* filesystem = NULL; +IVEngineServer* engine = NULL; +pluginhelpers_t* pluginhelpers = NULL; +EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CLua502Plugin,IServerPluginCallbacks, + INTERFACEVERSION_ISERVERPLUGINCALLBACKS,g_Lua502Plugin); +EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CLua502Plugin,ILua502,INTERFACEVERSION_LUA502,g_Lua502Plugin); + +bool __fastcall RunFileHook(CLuaInterface*,void*,const char*); +int __fastcall SetScriptHook(void*,void*,const char*); +int CreateGlobalLuaHook(); +static FnRunFile s_fnRunFile; +static CLuaInterface** s_ppLuaInterface; +static DWORD s_dwCreateGLUA; + +FnPluginLoad CLua502Plugin::s_fnPluginLoad = NULL; +FnPluginUnload CLua502Plugin::s_fnPluginUnload = NULL; + +CLua502Plugin::CLua502Plugin() : m_Plugins(DefLessFunc(int)) +{ + m_pLuaInterface = NULL; + m_pRunFileHook = NULL; +} + +bool CLua502Plugin::Load(CreateInterfaceFn InterFn,CreateInterfaceFn GameFn) +{ + DWORD dwSetScript; + /*CSysModule* sysFileSystemSteam = NULL; + if(!Sys_LoadInterface("filesystem_steam",FILESYSTEM_INTERFACE_VERSION, + &sysFileSystemSteam,(void**)&filesystem)) + { + Warning("filesystem not found!\n"); + return false; + }*/ + m_fnAppFactory = InterFn; + m_fnGameFactory = GameFn; + + ConnectTier1Libraries(&m_fnAppFactory,1); + + if(!(filesystem = (IFileSystem*)m_fnAppFactory(FILESYSTEM_INTERFACE_VERSION,0))) + { + Print(FILESYSTEM_INTERFACE_VERSION " not found!\n"); + Unlock(); + return false; + } + + if(!(engine = (IVEngineServer*)m_fnAppFactory(INTERFACEVERSION_VENGINESERVER,0))) + { + Print("IVEngineServer not found!\n"); + Unlock(); + return false; + } + + if(!(pluginhelpers = (pluginhelpers_t*)m_fnAppFactory( + INTERFACEVERSION_ISERVERPLUGINHELPERS,0))) + { + Print("IServerPluginHelpers not found!\n"); + Unlock(); + return false; + } + + /*DECLARE_SIGSCAN(m_pLuaInterface,"server.dll",GETLUAINTERFACE_SIG,GETLUAINTERFACE_MASK, + GETLUAINTERFACE_OFFSET,SigScan::CSigScan::SIG_VARIABLE);*/ + /*DECLARE_SIGSCAN(s_ppLuaInterface,"server.dll",CREATEGLUA_SIG,CREATEGLUA_MASK, + CREATEGLUA_OFFSET,SigScan::CSigScan::SIG_PTR);*/ + DECLARE_SIGSCAN(s_dwCreateGLUA,"server.dll",CREATEGLUA_SIG,CREATEGLUA_MASK, + 0,SigScan::CSigScan::SIG_FUNCTION); + DECLARE_SIGSCAN(s_fnRunFile,"server.dll",RUNFILE_SIG,RUNFILE_MASK,0, + SigScan::CSigScan::SIG_FUNCTION); + DECLARE_SIGSCAN(dwSetScript,"server.dll",SETSCRIPT_SIG,SETSCRIPT_MASK,0, + SigScan::CSigScan::SIG_FUNCTION); + DECLARE_SIGSCAN(s_fnPluginLoad,"engine.dll",PLUGINLOAD_SIG, + PLUGINLOAD_MASK,0,SigScan::CSigScan::SIG_FUNCTION); + DECLARE_SIGSCAN(s_fnPluginUnload,"engine.dll",PLUGINUNLOAD_SIG, + PLUGINUNLOAD_MASK,0,SigScan::CSigScan::SIG_FUNCTION); + SigScan::Scan(); + + s_ppLuaInterface = *(CLuaInterface***)((char*)s_dwCreateGLUA+CREATEGLUA_OFFSET); + + m_pCreateGlobalLua = new CHook(s_dwCreateGLUA,CREATEGLUA_HOOKSIZE); + m_fnCreateGlobalLua = (FnCreateGlobalLua) + m_pCreateGlobalLua->HookFunction((DWORD)CreateGlobalLuaHook); + m_pSetScript = new CHook(dwSetScript,SETSCRIPT_HOOKSIZE); + m_fnSetScript = (FnSetScript)m_pSetScript + ->HookFunction((DWORD)SetScriptHook); + + ConVar_Register(); + LoadConfigs(); + LoadPlugins(); + return true; +} + +void CLua502Plugin::Load2() +{ + m_pLuaInterface = *s_ppLuaInterface; + Lock(); + SetLuaCallbacks(this); + //CLuaFile::ClearCache(); + if(!CLuaFile::Init()) + { + Warning("Lua cache initialization failed!\n"); + Unlock(); + return; + } + m_fnOldPanic = lua_atpanic(m_pLuaInterface->m_pL,lua502_atpanic); + + int iNewTop,iTop = lua_gettop(m_pLuaInterface->m_pL); + CLuaLibrary::Init(m_pLuaInterface->m_pL); + iNewTop = lua_gettop(m_pLuaInterface->m_pL); + + Print("iTop %d iNewTop %d\n",iTop,iNewTop); + //MessageBox(NULL,m_pLuaInterface ? "m_pLuaInterface OK" : "m_pLuaInterface FAIL","Lua502",MB_OK); + Print("Loaded\nm_pLuaInterface %p lua_State %p\n", + m_pLuaInterface,m_pLuaInterface->m_pL); + + CLuaLibrary::Dump(); + + if(!m_pRunFileHook) + { + m_pRunFileHook = new CHook((DWORD)s_fnRunFile,RUNFILE_HOOKSIZE); + m_pRunFileHook->HookFunction((DWORD)RunFileHook); + } + + Unlock(); +} + +void CLua502Plugin::LoadConfigs() +{ + KeyValues* pKV = new KeyValues("Settings"); + if(!filesystem->FileExists("cfg/lua502.cfg","MOD")) + { + m_bLuaUseCache = true; + + pKV->SetInt("LuaUseCache",m_bLuaUseCache); + pKV->SaveToFile(filesystem,"cfg/lua502.cfg","MOD"); + } + else + { + pKV->LoadFromFile(filesystem,"cfg/lua502.cfg","MOD"); + m_bLuaUseCache = !!pKV->GetInt("LuaUseCache"); + } +} + +void CLua502Plugin::LoadPlugins() +{ + FileFindHandle_t fFind; + const char* pPath = NULL; + char szBuff[MAX_PATH]; + + if((pPath=filesystem->FindFirstEx("lua/bin/*.dll","MOD",&fFind))) + { + do { + sprintf(szBuff,"gmod9/lua/bin/%s",pPath); + Print("Plugin %s\n",pPath); + LoadPlugin(szBuff,NULL); + } while((pPath=filesystem->FindNext(fFind))); + filesystem->FindClose(fFind); + } +} + +void CLua502Plugin::LoadScripts() +{ + FileFindHandle_t fFind; + const char* pFile,*pErr; + char szFile[MAX_PATH]; + if((pFile = filesystem->FindFirstEx("lua/lua502/*.lua","MOD",&fFind))) + { + do { + sprintf(szFile,"lua/lua502/%s",pFile); + if(RunFile(szFile,&pErr)) + Warning("Failed run scripts %s: %s\n",szFile,pErr?pErr:"no-error"); + } while((pFile = filesystem->FindNext(fFind))); + filesystem->FindClose(fFind); + } +} + +void CLua502Plugin::Unload() +{ + CLuaLibrary::Exit(m_pLuaInterface->m_pL); + + for(size_t i = 0; i < m_Plugins.Count(); i++) + UnloadPlugin(i); + lua_atpanic(m_pLuaInterface->m_pL,m_fnOldPanic); + delete m_pRunFileHook; + delete m_pCreateGlobalLua; + delete m_pSetScript; +} + +void CLua502Plugin::Pause() +{ +} + +void CLua502Plugin::UnPause() +{ +} + +const char* CLua502Plugin::GetPluginDescription() +{ + return "GLua9 Interface"; +} + +void CLua502Plugin::LevelInit(const char*) +{ +} + +void CLua502Plugin::ServerActivate(edict_t*,int,int) +{ +} + +void CLua502Plugin::GameFrame(bool) +{ +} + +void CLua502Plugin::LevelShutdown() +{ +} + +void CLua502Plugin::ClientActive(edict_t*) +{ +} + +void CLua502Plugin::ClientDisconnect(edict_t*) +{ +} + +void CLua502Plugin::ClientPutInServer(edict_t*,const char*) +{ +} + +void CLua502Plugin::SetCommandClient(int) +{ +} + +void CLua502Plugin::ClientSettingsChanged(edict_t*) +{ +} + +PLUGIN_RESULT CLua502Plugin::ClientConnect(bool*,edict_t*,const char*,const char*, char*,int) +{ + return PLUGIN_CONTINUE; +} + +PLUGIN_RESULT CLua502Plugin::ClientCommand(edict_t* /*,void**/) +{ + return PLUGIN_CONTINUE; +} + +PLUGIN_RESULT CLua502Plugin::NetworkIDValidated(const char*,const char*) +{ + return PLUGIN_CONTINUE; +} + +/*void CLua502Plugin::OnQueryCvarValueFinished(QueryCvarCookie_t,edict_t*,EQueryCvarValueStatus,const char*,const char*) +{ +} + +void CLua502Plugin::OnEdictAllocated(edict_t*) +{ +} + +void CLua502Plugin::OnEdictFreed(edict_t*) +{ +}*/ + +bool CLua502Plugin::LoadPlugin(const char* pName, + int* pPlugin) +{ + luaplugin_t* pPlug = new luaplugin_t; + V_memset(pPlug,'\0',sizeof(luaplugin_t)); + if(!IsPathSecure(pName)) + { + delete pPlug; + return false; + } + if(!s_fnPluginLoad(pPlug,pName)) + { + delete pPlug; + return false; + } + if(!pPlug->m_pCallbacks) + { + Print("%s wrong callbacks\n",pName); + delete pPlug; + return false; + } + if(!pPlug->m_pCallbacks->GlobalInit(this)) + { + Print("%s GlobalInit failed!\n", + pPlug->m_szName); + s_fnPluginUnload(this); + delete pPlug; + return false; + } + + int iIndex = pluginhelpers->m_pPlugins.AddToTail(pPlug); + int iID = m_Plugins.Insert(iIndex,pPlug); //Crash + if(pPlugin) *pPlugin = iID; + OnPluginLoad(pPlug); + return true; +} + +void CLua502Plugin::UnloadPlugin(int iPlugin) +{ + luaplugin_t* pPlug; + if(!(pPlug = GetPlugin(iPlugin))) + return; + OnPluginUnload(pPlug); + s_fnPluginUnload(pPlug); + + int iID = pluginhelpers->m_pPlugins.Find(pPlug); + if(pluginhelpers->m_pPlugins.IsValidIndex(iID)) + pluginhelpers->m_pPlugins.Remove(iID); + + m_Plugins.Remove(iPlugin); + delete pPlug; +} + +luaplugin_t* CLua502Plugin::GetPlugin(int iPlugin) +{ + if(m_Plugins.IsValidIndex(iPlugin)) + return m_Plugins[iPlugin]; + return NULL; +} + +const char* CLua502Plugin::RunString(const char* pCode,size_t len,const char* pName) +{ + const char* pRet = NULL; + lua_State* L = m_pLuaInterface->m_pL; + Lock(); + + lua_pushcfunction(L,lua502_aterror); + if(luaL_loadbuffer(L,pCode,len,pName)) + pRet = lua_tostring(L,-1); + else + lua_pcall(L,0,LUA_MULTRET,lua_gettop(L)-1); + + lua_pop(L,1); + Unlock(); + return pRet; +} + +const char* CLua502Plugin::RunStringEx(lua_State* _L,const char* pCode,size_t len,const char* pName) +{ + const char* pRet = NULL; + Lock(); + + lua_pushcfunction(_L,lua502_aterror); + if(luaL_loadbuffer(_L,pCode,len,pName)) + { + pRet = lua_tostring(_L,-1); + lua_pop(_L,1); + } + else + lua_pcall(_L,0,LUA_MULTRET,lua_gettop(_L)-1); + + lua_pop(_L,1); + Unlock(); + return pRet; +} + +CLuaInterface* CLua502Plugin::GetLuaInterface() +{ + return m_pLuaInterface; +} + +void CLua502Plugin::Print(const char* pFmt,...) +{ + char szBuf[256] = {0}; + char szFormat[256] = {0}; + va_list ap; + + Lock(); + + va_start(ap,pFmt); + V_vsnprintf(szBuf,256,pFmt,ap); + va_end(ap); + sprintf(szFormat,"[Lua502] %s",szBuf); + + Msg(szFormat); + if(engine) engine->LogPrint(szFormat); + Unlock(); +} + +//lua/file.lua +luafile_err_t CLua502Plugin::RunFile(const char* pFile,const char** ppErr, + lua_State* pL) +{ + luafile_err_t iErr; + const char* pErr = NULL; + + if(m_bLuaUseCache) + { + Lock(); + CLuaFile luafile((pL?pL:m_pLuaInterface->m_pL),pFile); + if((iErr = luafile.Load(&pErr))) + { + Warning("CLuaFile::Load error %s\n",g_pLuaFileErrors[iErr]); + if(iErr == LUAFILE_LUA_ERROR) + Warning("%s\n",pErr?pErr:"error-error"); + } else luafile.Execute(); + if(ppErr) *ppErr = pErr; + Unlock(); + } + else + { + Lock(); + FileHandle_t fLua = filesystem->Open(pFile,"rb","MOD"); + if(!fLua) + { + Warning("File not found!\n"); + *ppErr = "File not found!"; + Unlock(); + return LUAFILE_LFC_FAULT; + } + uint32 uSize = filesystem->Size(fLua); + char* pBuf = new char[uSize]; + filesystem->Read(pBuf,uSize,fLua); + filesystem->Close(fLua); + if((pErr=RunStringEx((pL?pL:m_pLuaInterface->m_pL),pBuf,uSize,"CLuaFile"))) + { + Warning("%s\n",pErr?pErr:"error-error"); + if(ppErr) *ppErr = pErr; + delete[] pBuf; + Unlock(); + return LUAFILE_LUA_ERROR; + } + delete[] pBuf; + Unlock(); + return LUAFILE_OK; + } + return iErr; +} + +void CLua502Plugin::SetLuaCallbacks(ILua502Callbacks* pCallbacks) +{ + Lock(); + m_pCallbacks = pCallbacks; + Unlock(); +} + +ILua502Callbacks* CLua502Plugin::GetLuaCallbacks() +{ + return m_pCallbacks; +} + +void CLua502Plugin::Lock() +{ + m_LuaMutex.Lock(); +} + +void CLua502Plugin::Unlock() +{ + m_LuaMutex.Unlock(); +} + +//ILua502Callbacks + +int CLua502Plugin::OnLuaPanic(lua_State* L) +{ + const char* pStr = lua_tostring(L,1); + Error("Lua Panic!\n%s",pStr?pStr:"(null)"); + return 0; +} + +int CLua502Plugin::OnLuaError(lua_State* L) +{ + const char* pStr = lua_tostring(L,1); + Warning("%s\n",pStr?pStr:"(null)\n"); + return 0; +} + +void CLua502Plugin::OnPluginLoad(luaplugin_t* pPlug) +{ + Msg("Plugin %s (%p) loaded\n",pPlug->m_szName, + pPlug); +} + +void CLua502Plugin::OnPluginUnload(luaplugin_t* pPlug) +{ + Msg("Plugin %s (%p) unloaded\n",pPlug->m_szName, + pPlug); +} + +void CLua502Plugin::OnLuaCreate(CLuaInterface* pLua) +{ + for(int i = m_Plugins.FirstInorder(); + m_Plugins.IsValidIndex(i); i = m_Plugins.NextInorder(i)) + m_Plugins[i]->m_pCallbacks->LuaInit(pLua->m_pL); + LoadScripts(); +} + +void CLua502Plugin::OnSWEPLuaCreate(CLuaInterface* pLua) +{ + for(int i = m_Plugins.FirstInorder(); + m_Plugins.IsValidIndex(i); i = m_Plugins.NextInorder(i)) + m_Plugins[i]->m_pCallbacks->OnSWEPLuaCreate(pLua->m_pL); +} + +bool CLua502Plugin::IsPathSecure(const char* pPath) +{ + int iLen; + char szBannedChars[] = {'\t','\r','\t'}; + + if(!(iLen = V_strlen(pPath))) return false; + if(V_strstr(pPath,"..") || V_strstr(pPath,":")) return false; + if(*(unsigned short*)pPath == 0x5C5C) return false; + for(int i = 0; i < iLen; i++) + if(pPath[i] && pPath[i] <= 0x1F) return false; //Ditch up control chars + return true; +} + +LUA_API int lua502_atpanic(lua_State* L) +{ + return g_Lua502Plugin.OnLuaPanic(L); +} + +LUA_API int lua502_aterror(lua_State* L) +{ + return g_Lua502Plugin.OnLuaError(L); +} + +bool __fastcall RunFileHook(CLuaInterface* pInterface,void* edx, + const char* pName) +{ + const char* pErr = NULL; + char szBuf[MAX_PATH] = {0}; + sprintf(szBuf,"lua/%s",pName); + return (g_pLua502->RunFile(szBuf,&pErr, + pInterface->m_pL) == 0); +} + +int __fastcall SetScriptHook(void* thisptr,void*,const char* pFile) +{ + int iRet = g_Lua502Plugin.m_fnSetScript(thisptr,pFile); + CLuaInterface* pLua = *(CLuaInterface**)((char*)thisptr+SWEPLUAOFFSET); + if(pLua) g_Lua502Plugin.OnSWEPLuaCreate(pLua); + return iRet; +} + +int CreateGlobalLuaHook() +{ + bool bPrev = (*s_ppLuaInterface!=NULL); + int iRet = g_Lua502Plugin.m_fnCreateGlobalLua(); + if(bPrev) g_Lua502Plugin.Load2(); + g_Lua502Plugin.OnLuaCreate(*s_ppLuaInterface); + return iRet; +} \ No newline at end of file diff --git a/lua/lua502/plugin.h b/lua/lua502/plugin.h new file mode 100644 index 0000000..61d1502 --- /dev/null +++ b/lua/lua502/plugin.h @@ -0,0 +1,153 @@ +#ifndef __PLUGIN_H +#define __PLUGIN_H + +#include "glua.h" +#include "luafile.h" +#include "chook.h" +#include "filesystem.h" +#include "engine/iserverplugin.h" +#include "tier0/threadtools.h" +#include "tier1/utlvector.h" +#include "tier1/utlmap.h" +#include "eiface.h" + +#define RUNFILE_SIG "\x81\xEC\x00\x00\x00\x00\x55\x8B\xAC\x24\x00\x00\x00\x00\x8D\x54\x24\x08\x56\x89\x4C\x24\x08\x8B\xC5\x2B\xD5\xEB\x03\x8D\x49\x00\x8A\x08" +#define RUNFILE_MASK "xx????xxxx????xxxxxxxxxxxxxxxxxxxx" +#define RUNFILE_HOOKSIZE 6 + +#define PLUGINLOAD_SIG "\x81\xEC\x00\x00\x00\x00\x53\x8B\x9C\x24\x00\x00\x00\x00\x56\x68\x00\x00\x00\x00\x8D\x44\x24\x0C" +#define PLUGINLOAD_MASK "xx????xxxx????xx????xxxx" + +#define PLUGINUNLOAD_SIG "\x56\x8B\xF1\x8B\x8E\x00\x00\x00\x00\x57\x33\xFF\x3B\xCF\x74\x11\x8B\x01\xFF\x50\x00\x89\xBE\x00\x00\x00\x00\x89\xBE\x00\x00\x00\x00\x8B\x86\x00\x00\x00\x00\x3B\xC7\x89\xBE\x00\x00\x00\x00\x74\x0C\x8B\x0D\x00\x00\x00\x00\x8B\x11\x50\xFF\x52\x00\xF6\x44\x24\x0C\x01\x89\xBE\x00\x00\x00\x00\x74\x09" +#define PLUGINUNLOAD_MASK "xxxxx????xxxxxxxxxxx?xx????xx????xx????xxxx????xxxx????xxxxx?xxxxxxx????xx" + +#define SETSCRIPT_SIG "\x81\xEC\x00\x00\x00\x00\x57\x8B\xF9\x8B\x87\x00\x00\x00\x00\x85\xC0\x74\x25" +#define SETSCRIPT_MASK "xx????xxxxx????xxxx" +#define SETSCRIPT_HOOKSIZE 6 + +#define SWEPLUAOFFSET 0x6E4 + +typedef bool (__thiscall* FnRunFile)(const char*); +typedef int (*FnCreateGlobalLua)(void); +typedef int (__thiscall* FnSetScript)(void*,const char*); + +typedef bool (__thiscall* FnPluginLoad)(void*,const char*); +typedef void (__thiscall* FnPluginUnload)(void*); + +typedef struct { + void** m_pVTable; + CUtlVector m_pPlugins; +} pluginhelpers_t; + +class CLua502Plugin : public IServerPluginCallbacks, public ILua502, public ILua502Callbacks +{ +public: + CLua502Plugin(); + + virtual bool Load( CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory ); + virtual void Unload( void ); + virtual void Pause( void ); + virtual void UnPause( void ); + virtual const char* GetPluginDescription( void ); + virtual void LevelInit( const char* pMapName ); + virtual void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax ); + virtual void GameFrame( bool simulating ); + virtual void LevelShutdown( void ); + virtual void ClientActive( edict_t *pEntity ); + virtual void ClientDisconnect( edict_t *pEntity ); + virtual void ClientPutInServer( edict_t *pEntity, char const *playername ); + virtual void SetCommandClient( int index ); + virtual void ClientSettingsChanged( edict_t *pEdict ); + virtual PLUGIN_RESULT ClientConnect( bool *bAllowConnect, edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen ); + virtual PLUGIN_RESULT ClientCommand( edict_t *pEntity/*, void* args */); //--From version 003 + virtual PLUGIN_RESULT NetworkIDValidated( const char *pszUserName, const char *pszNetworkID ); + + virtual void Load2(); + virtual void LoadPlugins(); + + /* + --From version 003 + virtual void OnQueryCvarValueFinished( QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue ); + virtual void OnEdictAllocated( edict_t *edict ); + virtual void OnEdictFreed( edict_t *edict ); */ + + //ILua502 + virtual bool LoadPlugin(const char* pName, + int* pPlugin); + virtual void UnloadPlugin(int iPlugin); + virtual const char* RunString(const char* pCode,size_t len,const char* pName); + const char* RunStringEx(lua_State* _L,const char* pCode,size_t len,const char* pName); + virtual luaplugin_t* GetPlugin(int iPlugin); + + virtual CLuaInterface* GetLuaInterface(); + virtual void Print(const char* pFmt,...); + + virtual luafile_err_t RunFile(const char* pFile,const char** ppErr = NULL, + lua_State* pL = NULL); + + virtual void SetLuaCallbacks(ILua502Callbacks* pCallbacks); + virtual ILua502Callbacks* GetLuaCallbacks(); + + virtual void Lock(); + virtual void Unlock(); + + void LoadConfigs(); + void LoadScripts(); + + //ILua502Callbacks + + virtual int OnLuaPanic(lua_State* L); + virtual int OnLuaError(lua_State* L); + + virtual void OnPluginLoad(luaplugin_t* pPlug); + virtual void OnPluginUnload(luaplugin_t* pPlug); + + virtual void OnLuaCreate(CLuaInterface*); + virtual void OnSWEPLuaCreate(CLuaInterface*); + + static bool IsPathSecure(const char* pPath); + + CLuaInterface* m_pLuaInterface; + ILua502Callbacks* m_pCallbacks; + CUtlMap m_Plugins; + + lua_CFunction m_fnOldPanic; + CHook* m_pRunFileHook; + CThreadMutex m_LuaMutex; + + FnSetScript m_fnSetScript; + FnCreateGlobalLua m_fnCreateGlobalLua; + CHook* m_pCreateGlobalLua; + CHook* m_pSetScript; + + CreateInterfaceFn m_fnAppFactory; + CreateInterfaceFn m_fnGameFactory; + + //Settings + bool m_bLuaUseCache; + + static FnPluginLoad s_fnPluginLoad; + static FnPluginUnload s_fnPluginUnload; +}; + +/* +unsigned long hash(unsigned char* s) +{ + unsigned long h = 5381; + unsigned char c; + while((c=*s++)) + h+=(h<<5)+c; + return h; +} +*/ + +extern CLua502Plugin g_Lua502Plugin; +extern ILua502* g_pLua502; + +extern IVEngineServer* engine; +extern IFileSystem* filesystem; + +LUA_API int lua502_atpanic(lua_State* L); +LUA_API int lua502_aterror(lua_State* L); + +#endif \ No newline at end of file diff --git a/lua/lua502/sigscan.cpp b/lua/lua502/sigscan.cpp new file mode 100644 index 0000000..599728f --- /dev/null +++ b/lua/lua502/sigscan.cpp @@ -0,0 +1,95 @@ +#include "sigscan.h" + +static SigScan::CSigScan* s_pLast; + +void SigScan_Notify(SigScan::CSigScan* pSigScan,SigScan::SigNotify_t notify) +{ + char szError[64]; + if(notify==SigScan::SIG_ERROR) + { + sprintf(szError,"%s (%p) sigscan failed!",pSigScan->m_pName,pSigScan->m_pdwDest); + MessageBoxA(NULL,szError,"SigScan",MB_ICONHAND); + ExitThread(1); + } +} + +SigScan::CSigScan::CSigScan(const char* pName,const char* pDll,const char* pSig,const char* pMask, + PDWORD pdwDest,DWORD dwOffset = 0,SigType_t type) +{ + m_pPrev = NULL; + + m_pName = pName; + m_pDll = pDll; + m_pSig = pSig; + m_pMask = pMask; + m_pdwDest = pdwDest; + m_dwOffset = dwOffset; + m_Type = type; + + Add(this); +} + +void SigScan::Add(CSigScan* pSigScan) +{ + pSigScan->m_pPrev = s_pLast; + s_pLast = pSigScan; +} + +void SigScan::Scan() +{ + CSigScan* pSigScan = s_pLast; + DWORD dwTrunk; + + do { + if(!(dwTrunk = SigScan(GetModuleHandle(pSigScan->m_pDll), + pSigScan->m_pSig,pSigScan->m_pMask))) + { + SigScan_Notify(pSigScan,SIG_ERROR); + continue; + } + + dwTrunk += pSigScan->m_dwOffset; + switch(pSigScan->m_Type) + { + case CSigScan::SIG_FUNCTION: + *pSigScan->m_pdwDest = dwTrunk; + break; + case CSigScan::SIG_PTR: + *pSigScan->m_pdwDest = *(PDWORD)(dwTrunk); + break; + case CSigScan::SIG_VARIABLE: + *pSigScan->m_pdwDest = **(PDWORD*)(dwTrunk); + break; + } + SigScan_Notify(pSigScan,SIG_LOG); + } while((pSigScan = pSigScan->m_pPrev)); +} + +size_t SigScan::GetModuleSize(HMODULE hDll) +{ + PIMAGE_DOS_HEADER DosHeader; + PIMAGE_NT_HEADERS NtHeaders; + + DosHeader = (PIMAGE_DOS_HEADER)hDll; + NtHeaders = (PIMAGE_NT_HEADERS)((LONG)hDll+DosHeader->e_lfanew); + + return NtHeaders->OptionalHeader.SizeOfImage; +} + +DWORD SigScan::SigScan(HMODULE hDll,const char* sig,const char* mask) +{ + size_t j,size = GetModuleSize(hDll),len = strlen(mask); + char* mem = (char*)hDll; + for(size_t i = 0; i < size; i++) + { + for(j = 0; j < len; j++) + { + if((mask[j] != '?') && (((char*)(mem+i))[j] != sig[j])) + break; + } + + if(j==len) + return (DWORD)(mem+i); + } + return NULL; +} \ No newline at end of file diff --git a/lua/lua502/sigscan.h b/lua/lua502/sigscan.h new file mode 100644 index 0000000..743d17c --- /dev/null +++ b/lua/lua502/sigscan.h @@ -0,0 +1,49 @@ +#ifndef __SIGSCAN_H +#define __SIGSCAN_H + +#include +#include + +namespace SigScan +{ + class CSigScan + { + public: + typedef enum { + SIG_FUNCTION, + SIG_VARIABLE, + SIG_PTR, + } SigType_t; + + CSigScan(const char* pName,const char* pDll,const char* pSig,const char* pMask, + PDWORD pdwDest,DWORD dwOffset,SigType_t type = SIG_FUNCTION); + + CSigScan* m_pPrev; + + const char* m_pName; + const char* m_pDll; + const char* m_pSig; + const char* m_pMask; + + PDWORD m_pdwDest; + DWORD m_dwOffset; + SigType_t m_Type; + }; + + typedef enum { + SIG_LOG, + SIG_ERROR, + } SigNotify_t; + + size_t GetModuleSize(HMODULE hDll); + DWORD SigScan(HMODULE hDll,const char* pSig,const char* pMask); + + void Scan(); + void Add(CSigScan* pSigScan); + + //CSigScan* s_pLast; +} + +#define DECLARE_SIGSCAN(dst,dll,sig,mask,ofst,type) SigScan::CSigScan dst##_s(#dst,dll,sig,mask,(PDWORD)&dst,ofst,type) + +#endif \ No newline at end of file diff --git a/lua/lua502/svar.cpp b/lua/lua502/svar.cpp new file mode 100644 index 0000000..ce74db2 --- /dev/null +++ b/lua/lua502/svar.cpp @@ -0,0 +1,25 @@ +#include "svar.h" + + +class SCvarAccessor : public IConCommandBaseAccessor +{ +public: + virtual bool RegisterConCommandBase(ConCommandBase* pCmd) + { + Msg("Registering %s\n",pCmd->GetName()); + + pCmd->AddFlags(FCVAR_PLUGIN); + pCmd->SetNext(NULL); + cvar->RegisterConCommandBase(pCmd); + return true; + } +}; + +static SCvarAccessor g_SCvarAccessor; + +void ConVar_Register() +{ + ConCommandBaseMgr::OneTimeInit(&g_SCvarAccessor); + Msg("%s\n",ConCommandBase::s_pConCommandBases->IsRegistered() ? "registered" : "not-registered"); + Msg("ICvar::RegisterConCommandBase %p\n",(*(void***)g_pCVar)[5]); +} \ No newline at end of file diff --git a/lua/lua502/svar.h b/lua/lua502/svar.h new file mode 100644 index 0000000..216e373 --- /dev/null +++ b/lua/lua502/svar.h @@ -0,0 +1,10 @@ +#ifndef __SVAR_H +#define __SVAR_H + +#include "icvar.h" +#include "convar.h" +#include "tier1.h" + +void ConVar_Register(); + +#endif \ No newline at end of file diff --git a/lua/lua502/types.cpp b/lua/lua502/types.cpp new file mode 100644 index 0000000..c56b350 --- /dev/null +++ b/lua/lua502/types.cpp @@ -0,0 +1,13 @@ +#include "types.h" + +static char* s_TypeNames[] = { + "Pointer", + "LuaPluign", + "ConVar", + "Command" +}; + +LUA_API const char* luaf_typename(int type) +{ + return s_TypeNames[type]; +} \ No newline at end of file diff --git a/lua/lua502/types.h b/lua/lua502/types.h new file mode 100644 index 0000000..d4d8d10 --- /dev/null +++ b/lua/lua502/types.h @@ -0,0 +1,14 @@ +#ifndef __TYPES_H + +#include "lua.h" + +typedef enum { + POINTER = 0, + LUAPLUGIN, + CONVAR, + COMMAND, +} luatypes_t; + +LUA_API const char* luaf_typename(int type); + +#endif \ No newline at end of file diff --git a/lua/lua502_sdk/Release/CL.read.1.tlog b/lua/lua502_sdk/Release/CL.read.1.tlog new file mode 100644 index 0000000..a4ad3b5 Binary files /dev/null and b/lua/lua502_sdk/Release/CL.read.1.tlog differ diff --git a/lua/lua502_sdk/Release/CL.write.1.tlog b/lua/lua502_sdk/Release/CL.write.1.tlog new file mode 100644 index 0000000..3edcad1 Binary files /dev/null and b/lua/lua502_sdk/Release/CL.write.1.tlog differ diff --git a/lua/lua502_sdk/Release/Lib-link.read.1.tlog b/lua/lua502_sdk/Release/Lib-link.read.1.tlog new file mode 100644 index 0000000..46b134b --- /dev/null +++ b/lua/lua502_sdk/Release/Lib-link.read.1.tlog @@ -0,0 +1 @@ +ÿþ \ No newline at end of file diff --git a/lua/lua502_sdk/Release/Lib-link.write.1.tlog b/lua/lua502_sdk/Release/Lib-link.write.1.tlog new file mode 100644 index 0000000..46b134b --- /dev/null +++ b/lua/lua502_sdk/Release/Lib-link.write.1.tlog @@ -0,0 +1 @@ +ÿþ \ No newline at end of file diff --git a/lua/lua502_sdk/Release/Lib.read.1.tlog b/lua/lua502_sdk/Release/Lib.read.1.tlog new file mode 100644 index 0000000..6a46d11 Binary files /dev/null and b/lua/lua502_sdk/Release/Lib.read.1.tlog differ diff --git a/lua/lua502_sdk/Release/Lib.write.1.tlog b/lua/lua502_sdk/Release/Lib.write.1.tlog new file mode 100644 index 0000000..009f0cd Binary files /dev/null and b/lua/lua502_sdk/Release/Lib.write.1.tlog differ diff --git a/lua/lua502_sdk/Release/baselib.obj b/lua/lua502_sdk/Release/baselib.obj new file mode 100644 index 0000000..6666fd2 Binary files /dev/null and b/lua/lua502_sdk/Release/baselib.obj differ diff --git a/lua/lua502_sdk/Release/chook.obj b/lua/lua502_sdk/Release/chook.obj new file mode 100644 index 0000000..4310957 Binary files /dev/null and b/lua/lua502_sdk/Release/chook.obj differ diff --git a/lua/lua502_sdk/Release/cl.command.1.tlog b/lua/lua502_sdk/Release/cl.command.1.tlog new file mode 100644 index 0000000..30dc1b2 Binary files /dev/null and b/lua/lua502_sdk/Release/cl.command.1.tlog differ diff --git a/lua/lua502_sdk/Release/lib.command.1.tlog b/lua/lua502_sdk/Release/lib.command.1.tlog new file mode 100644 index 0000000..a1cc1b7 Binary files /dev/null and b/lua/lua502_sdk/Release/lib.command.1.tlog differ diff --git a/lua/lua502_sdk/Release/lua502_sdk.Build.CppClean.log b/lua/lua502_sdk/Release/lua502_sdk.Build.CppClean.log new file mode 100644 index 0000000..d8a1faa --- /dev/null +++ b/lua/lua502_sdk/Release/lua502_sdk.Build.CppClean.log @@ -0,0 +1,15 @@ +D:\LUA502\LUA\LUA502_SDK\RELEASE\BASELIB.OBJ +D:\LUA502\LUA\LUA502_SDK\RELEASE\CHOOK.OBJ +D:\lua502\lua\lua502_sdk\Release\cl.command.1.tlog +D:\lua502\lua\lua502_sdk\Release\CL.read.1.tlog +D:\lua502\lua\lua502_sdk\Release\CL.write.1.tlog +D:\lua502\lua\lua502_sdk\Release\lib.command.1.tlog +D:\lua502\lua\lua502_sdk\Release\Lib.read.1.tlog +D:\lua502\lua\lua502_sdk\Release\Lib.write.1.tlog +D:\lua502\lua\lua502_sdk\Release\Lib-link.read.1.tlog +D:\lua502\lua\lua502_sdk\Release\Lib-link.write.1.tlog +D:\lua502\lua\lua502_sdk\Release\lua502_sdk.write.1.tlog +D:\LUA502\LUA\LUA502_SDK\RELEASE\PLUGIN.OBJ +D:\LUA502\LUA\LUA502_SDK\RELEASE\SIGSCAN.OBJ +D:\LUA502\LUA\LUA502_SDK\RELEASE\VC100.PDB +D:\LUA502\LUA\RELEASE\LUA502_SDK.LIB diff --git a/lua/lua502_sdk/Release/lua502_sdk.lastbuildstate b/lua/lua502_sdk/Release/lua502_sdk.lastbuildstate new file mode 100644 index 0000000..c2d4a05 --- /dev/null +++ b/lua/lua502_sdk/Release/lua502_sdk.lastbuildstate @@ -0,0 +1,2 @@ +#v4.0:v100:false +Release|Win32|D:\lua502\lua\| diff --git a/lua/lua502_sdk/Release/lua502_sdk.log b/lua/lua502_sdk/Release/lua502_sdk.log new file mode 100644 index 0000000..709ec27 --- /dev/null +++ b/lua/lua502_sdk/Release/lua502_sdk.log @@ -0,0 +1,20 @@ +Build started 28.06.2018 3:17:35. + 1>Project "D:\lua502\lua\lua502_sdk\lua502_sdk.vcxproj" on node 2 (build target(s)). + 1>InitializeBuildStatus: + Creating "Release\lua502_sdk.unsuccessfulbuild" because "AlwaysCreate" was specified. + ClCompile: + All outputs are up-to-date. + Lib: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\Lib.exe /OUT:"D:\lua502\lua\Release\lua502_sdk.lib" lua502.lib /LIBPATH:D:\lua502\lua\Release /NOLOGO /LTCG Release\baselib.obj + Release\chook.obj + Release\plugin.obj + Release\sigscan.obj + lua502_sdk.vcxproj -> D:\lua502\lua\Release\lua502_sdk.lib + FinalizeBuildStatus: + Deleting file "Release\lua502_sdk.unsuccessfulbuild". + Touching "Release\lua502_sdk.lastbuildstate". + 1>Done Building Project "D:\lua502\lua\lua502_sdk\lua502_sdk.vcxproj" (build target(s)). + +ПоÑтроение уÑпешно завершено. + +Time Elapsed 00:00:00.17 diff --git a/lua/lua502_sdk/Release/lua502_sdk.write.1.tlog b/lua/lua502_sdk/Release/lua502_sdk.write.1.tlog new file mode 100644 index 0000000..e69de29 diff --git a/lua/lua502_sdk/Release/memoverride.obj b/lua/lua502_sdk/Release/memoverride.obj new file mode 100644 index 0000000..10eef56 Binary files /dev/null and b/lua/lua502_sdk/Release/memoverride.obj differ diff --git a/lua/lua502_sdk/Release/plugin.obj b/lua/lua502_sdk/Release/plugin.obj new file mode 100644 index 0000000..a7f8c78 Binary files /dev/null and b/lua/lua502_sdk/Release/plugin.obj differ diff --git a/lua/lua502_sdk/Release/sigscan.obj b/lua/lua502_sdk/Release/sigscan.obj new file mode 100644 index 0000000..55504f0 Binary files /dev/null and b/lua/lua502_sdk/Release/sigscan.obj differ diff --git a/lua/lua502_sdk/Release/vc100.pdb b/lua/lua502_sdk/Release/vc100.pdb new file mode 100644 index 0000000..3c457af Binary files /dev/null and b/lua/lua502_sdk/Release/vc100.pdb differ diff --git a/lua/lua502_sdk/baselib.cpp b/lua/lua502_sdk/baselib.cpp new file mode 100644 index 0000000..052344f --- /dev/null +++ b/lua/lua502_sdk/baselib.cpp @@ -0,0 +1,237 @@ +#define __BASELIB_INTERNAL_H +#include +#include "tier1/strtools.h" +#include "tier0/dbg.h" +#include "baselib.h" +#include "types.h" + +CLuaFunction::CLuaFunction(CLuaTable* pTable,const char* pName, + lua_CFunction fnFunc) +{ + m_pName = pName; + m_fnFunc = fnFunc; + pTable->Add(this); +} + +CLuaTable::CLuaTable(CLuaLibrary* pLib,const char* pName, + bool bRegister) +{ + m_pName = pName; + m_bRegister = bRegister; + pLib->Add(this); +} + +int luaf_unk_tostring(lua_State* L) +{ + luaL_checktype(L,1,LUA_TUSERDATA); + UInt16* pUserData = (UInt16*)lua_touserdata(L,1); + luaL_pushfstring(L,"%s %p",luaf_typename(*pUserData), + (char*)pUserData+sizeof(UInt16)); + return 1; +} + +void CLuaTable::Add(CLuaFunction* pFunc) +{ + pFunc->m_pNext = m_pLast; + m_pLast = pFunc; +} + +//Still work +void CLuaTable::Register(lua_State* L) +{ + CLuaFunction* pFunc; + if(!(pFunc = m_pLast)) return; + + if(!V_strcmp(m_pName,"_G")) + { + do { + lua_register(L,pFunc->m_pName, + pFunc->m_fnFunc); + } while((pFunc=pFunc->m_pNext)); + } + else + { + lua_pushstring(L,m_pName); + lua_newtable(L); + do { + lua_pushstring(L,pFunc->m_pName); + lua_pushcfunction(L,pFunc->m_fnFunc); + lua_settable(L,-3); + } while((pFunc=pFunc->m_pNext)); + lua_settable(L,LUA_GLOBALSINDEX); + } +} + +void CLuaTable::Unregister(lua_State* L) +{ + CLuaFunction* pFunc = m_pLast; + if(!V_strcmp(m_pName,"_G")) + { + while(pFunc) + { + lua_pushstring(L,pFunc->m_pName); + lua_pushnil(L); + lua_settable(L,LUA_GLOBALSINDEX); + pFunc = pFunc->m_pNext; + } + } + else + { + lua_pushstring(L,m_pName); + lua_pushnil(L); + lua_settable(L,LUA_GLOBALSINDEX); + } +} + +CLuaMetaTable::CLuaMetaTable(CLuaLibrary* pLib, + unsigned short nTypeID,CLuaTable* pParent) + : CLuaTable(pLib,NULL) +{ + m_iTypeID = (int)nTypeID; + m_pParent = pParent; +} + +void CLuaMetaTable::Register(lua_State* L) +{ + CLuaFunction* pFunc; + bool bHasIndex = false,bHasToString = false; + if(!(pFunc = m_pLast)) return; + + sprintf(m_szMetaName,"metatable_%04d",m_iTypeID); + + lua_pushstring(L,m_szMetaName); + lua_newtable(L); + do { + if(!V_strcmp(pFunc->m_pName,"__index")) + bHasIndex = true; + if(!V_strcmp(pFunc->m_pName,"__tostring")) + bHasToString = true; + lua_pushstring(L,pFunc->m_pName); + lua_pushcfunction(L,pFunc->m_fnFunc); + lua_settable(L,-3); + } while((pFunc=pFunc->m_pNext)); + if(m_pParent) + { + pFunc = m_pParent->m_pLast; + while(pFunc) + { + if(!V_strcmp(pFunc->m_pName,"__index")) + bHasIndex = true; + if(!V_strcmp(pFunc->m_pName,"__tostring")) + bHasToString = true; + lua_pushstring(L,pFunc->m_pName); + lua_pushcfunction(L,pFunc->m_fnFunc); + lua_settable(L,-3); + pFunc = pFunc->m_pNext; + } + } + if(!bHasIndex) + { + lua_pushstring(L,"__index"); + lua_pushvalue(L,-2); + lua_settable(L,-3); + } + if(!bHasToString) + { + lua_pushstring(L,"__tostring"); + lua_pushcfunction(L,luaf_unk_tostring); + lua_settable(L,-3); + } + lua_settable(L,LUA_REGISTRYINDEX); +} + +void CLuaMetaTable::Unregister(lua_State* L) +{ + lua_pushstring(L,m_szMetaName); + lua_pushnil(L); + lua_settable(L,LUA_REGISTRYINDEX); +} + +void CLuaMetaTable::PushToStack(lua_State* L) +{ + lua_pushstring(L,m_szMetaName); + lua_gettable(L,LUA_REGISTRYINDEX); +} + +CLuaLibrary* CLuaLibrary::s_pLast = NULL; + +CLuaLibrary::CLuaLibrary(const char* pName) +{ + m_pName = pName; + m_pLastTable = NULL; + + m_pNextLibrary = s_pLast; + s_pLast = this; +} + +void CLuaLibrary::Add(CLuaTable* pTable) +{ + pTable->m_pNext = m_pLastTable; + m_pLastTable = pTable; +} + +void CLuaLibrary::Register(lua_State* L) +{ + CLuaTable* pTable; + if(!(pTable = m_pLastTable)) return; + do { + if(!pTable->m_bRegister) continue; + pTable->Register(L); + } while((pTable=pTable->m_pNext)); +} + +void CLuaLibrary::Unregister(lua_State* L) +{ + CLuaTable* pTable; + if(!(pTable = m_pLastTable)) return; + do { + if(!pTable->m_bRegister) continue; + pTable->Unregister(L); + } while((pTable=pTable->m_pNext)); +} + +void CLuaLibrary::Init(lua_State* L) +{ + CLuaLibrary* pLib; + if(!(pLib = s_pLast)) return; + do { + pLib->Register(L); + } while((pLib=pLib->m_pNextLibrary)); +} + +void CLuaLibrary::Exit(lua_State* L) +{ + CLuaLibrary* pLib; + if(!(pLib = s_pLast)) return; + do { + pLib->Unregister(L); + } while((pLib=pLib->m_pNextLibrary)); +} + +void CLuaLibrary::Dump() +{ + CLuaLibrary* pLib; + CLuaTable* pTable; + CLuaFunction* pFunc; + + pLib = s_pLast; + while(pLib) + { + Msg("library %s\n",pLib->m_pName); + pTable = pLib->m_pLastTable; + while(pTable) + { + Msg("\ttable %s\n",pTable->m_iTypeID>1024 + ? pTable->m_pName:"(metatable)"); + pFunc = pTable->m_pLast; + while(pFunc) + { + Msg("\t\tfunction %s %p\n",pFunc->m_pName, + pFunc->m_fnFunc); + pFunc = pFunc->m_pNext; + } + pTable = pTable->m_pNext; + } + pLib = pLib->m_pNextLibrary; + } +} \ No newline at end of file diff --git a/lua/lua502_sdk/baselib.h b/lua/lua502_sdk/baselib.h new file mode 100644 index 0000000..4a4b58a --- /dev/null +++ b/lua/lua502_sdk/baselib.h @@ -0,0 +1,128 @@ +#ifndef __BASELIB_H +#define __BASELIB_H + +#include "lua.hpp" + +class CLuaLibrary; +class CLuaFunction; +class CLuaTable +{ +public: + CLuaTable(CLuaLibrary* pLib, + const char* pName, bool bRegister = true); + + void Add(CLuaFunction* pFunc); + virtual void Register(lua_State* L); + virtual void Unregister(lua_State* L); + + union { + const char* m_pName; + int m_iTypeID; + }; + bool m_bRegister; + + CLuaFunction* m_pLast; + CLuaTable* m_pNext; +}; + +class CLuaMetaTable : public CLuaTable +{ +public: + CLuaMetaTable(CLuaLibrary* pLib, + unsigned short nTypeID, + CLuaTable* pParent = NULL); + + virtual void Register(lua_State* L); + virtual void Unregister(lua_State* L); + virtual void PushToStack(lua_State* L); + + CLuaTable* m_pParent; + char m_szMetaName[16]; +}; + +class CLuaFunction +{ +public: + CLuaFunction(CLuaTable* pTable,const char* pName, + lua_CFunction fnFunc); + + const char* m_pName; + lua_CFunction m_fnFunc; + CLuaFunction* m_pNext; +}; + +class CLuaLibrary +{ +public: + CLuaLibrary(const char* pName); + + virtual void Register(lua_State* L); + virtual void Unregister(lua_State* L); + + void Add(CLuaTable* pTable); + + const char* m_pName; + + CLuaTable* m_pLastTable; + CLuaLibrary* m_pNextLibrary; + + static void Init(lua_State* L); + static void Exit(lua_State* L); + + static void Dump(); + + static CLuaLibrary* s_pLast; +}; + +typedef unsigned short UInt16; + +typedef struct { + UInt16 m_nType; + void* m_pData; +} userdata_t; + +LUA_API void* luaL_createuserdata(lua_State* L,size_t sz, + CLuaMetaTable* pMeta); +LUA_API void luaL_pushfstring(lua_State* L,const char* pFmt,...); +inline void* luaf_checkuserdata(lua_State* L,int idx, + CLuaMetaTable* pMeta) +{ + luaL_checktype(L,idx,LUA_TUSERDATA); + void* pUD = lua_touserdata(L,idx); + if(*(unsigned char*)pUD != pMeta->m_iTypeID) + luaL_argerror(L,idx,"Wrong userdata"); + else return (char*)pUD+sizeof(unsigned short); + return NULL; +} +LUA_API void* luaL_multicheckuserdata(lua_State* L,int idx, + int nTypes,...); + +//Eats object at top of stack +LUA_API int lua_refobj(lua_State* L); +LUA_API void lua_unrefobj(lua_State* L,int id); +LUA_API void lua_pushref(lua_State* L,int id); + +//#undef __BASELIB_INTERNAL_H +#ifndef __BASELIB_INTERNAL_H +#define DECLARE_LIBRARY(name) \ + static CLuaLibrary g_LuaLibrary(name); + +#define DECLARE_TABLE(tablename) \ + static CLuaTable g_LuaTable_##tablename(&g_LuaLibrary,#tablename); + +#define DECLARE_TABLE_DUMMY(tablename) \ + static CLuaTable g_LuaTable_##tablename(&g_LuaLibrary,#tablename,false); + +#define DECLARE_METATABLE(tablename,type) \ + static CLuaMetaTable g_LuaTable_##tablename(&g_LuaLibrary,type); + +#define DECLARE_METATABLE_INHERITOR(tablename,type,parent) \ + static CLuaMetaTable g_LuaTable_##tablename(&g_LuaLibrary,type,&g_LuaTable_##parent); + +#define DECLARE_FUNCTION(tablename,funcname) \ + static int luaf_##tablename##funcname(lua_State*); \ + static CLuaFunction g_##tablename##funcname(&g_LuaTable_##tablename,#funcname,luaf_##tablename##funcname); \ + static int luaf_##tablename##funcname(lua_State* L) +#endif + +#endif \ No newline at end of file diff --git a/lua/lua502_sdk/chook.cpp b/lua/lua502_sdk/chook.cpp new file mode 100644 index 0000000..5053341 --- /dev/null +++ b/lua/lua502_sdk/chook.cpp @@ -0,0 +1,57 @@ +#include "chook.h" +#include "tier0/memdbgon.h" + +CHook::CHook(DWORD Func,SIZE_T Size) +{ + pFunc = Func; + DetourSize = Size; + + OrigBytes = (PBYTE)malloc(Size); +} + +CHook::~CHook() +{ + if(hooked) + UnHookFunction(); +} + +DWORD CHook::HookFunction(DWORD Hook) +{ + DWORD dwProtect; + pHook = Hook; + hooked = true; + + VirtualProtect((LPVOID)pFunc,DetourSize,PAGE_EXECUTE_READWRITE,&dwProtect); + + memcpy(OrigBytes,(LPVOID)pFunc,DetourSize); + memset((LPVOID)pFunc,'\x90',DetourSize); + + *(PBYTE)pFunc = 0xE9; + *(PDWORD)(pFunc+1) = (pHook - pFunc) - 5; + + pOrig = (DWORD)VirtualAlloc(NULL,DetourSize+5,MEM_RESERVE | MEM_COMMIT,PAGE_EXECUTE_READWRITE); + + memcpy((LPVOID)pOrig,OrigBytes,DetourSize); + + *(PBYTE)(pOrig+DetourSize) = 0xE9; + *(PDWORD)(pOrig+DetourSize+1) = ((pFunc+DetourSize) - pOrig) - DetourSize - 5; + + VirtualProtect((LPVOID)pFunc,DetourSize,dwProtect,NULL); + + return pOrig; +} + +DWORD CHook::UnHookFunction() +{ + DWORD dwProtect; + hooked = false; + + VirtualProtect((LPVOID)pFunc,DetourSize,PAGE_EXECUTE_READWRITE,&dwProtect); + + memcpy((LPVOID)pFunc,OrigBytes,DetourSize); + free(OrigBytes); + + VirtualFree((LPVOID)pOrig,DetourSize+5,MEM_RELEASE | MEM_DECOMMIT); + + return pFunc; +} \ No newline at end of file diff --git a/lua/lua502_sdk/chook.h b/lua/lua502_sdk/chook.h new file mode 100644 index 0000000..7ff93d9 --- /dev/null +++ b/lua/lua502_sdk/chook.h @@ -0,0 +1,25 @@ +#ifndef __CHOOK_H +#define __CHOOK_H + +#include +#include +#include + +class CHook +{ +public: + CHook(DWORD Func,SIZE_T Size); + ~CHook(); + + DWORD HookFunction(DWORD Hook); + DWORD UnHookFunction(); +private: + bool hooked; + DWORD pFunc; + DWORD pHook; + DWORD pOrig; + SIZE_T DetourSize; + PBYTE OrigBytes; +}; + +#endif \ No newline at end of file diff --git a/lua/lua502_sdk/glua.h b/lua/lua502_sdk/glua.h new file mode 100644 index 0000000..566be30 --- /dev/null +++ b/lua/lua502_sdk/glua.h @@ -0,0 +1,81 @@ +#ifndef __GLUA_H +#define __GLUA_H + +#include "engine/iserverplugin.h" +extern "C" +{ + #include "lua.h" + #include "lualib.h" +} + +class ILua502; +class ILuaPluginCallbacks : public IServerPluginCallbacks +{ +public: + virtual bool GlobalInit(ILua502*) = 0; + virtual bool LuaInit(lua_State*) = 0; + virtual void OnSWEPLuaCreate(lua_State*) = 0; +}; + +class CLuaInterface +{ +public: + lua_State* m_pL; +}; + +typedef enum { + LUAFILE_OK = 0, + LUAFILE_MEM_FAULT, + LUAFILE_LUA_ERROR, + LUAFILE_DUMP_FAULT, + LUAFILE_LFC_FAULT, +} luafile_err_t; + +typedef struct { + char m_szName[128]; + bool m_bDisabled; + ILuaPluginCallbacks* m_pCallbacks; + int m_iVersion; + CSysModule* m_pModule; +} luaplugin_t; + +class ILua502Callbacks +{ +public: + virtual int OnLuaPanic(lua_State* L) = 0; + virtual int OnLuaError(lua_State* L) = 0; + + virtual void OnPluginLoad(luaplugin_t* pPlug) = 0; + virtual void OnPluginUnload(luaplugin_t* pPlug) = 0; + + virtual void OnLuaCreate(lua_State* L) = 0; + virtual void OnSWEPLuaCreate(CLuaInterface*) = 0; +}; + +class ILua502 +{ +public: + virtual bool LoadPlugin(const char* pName,int* pPlugin) = 0; + virtual void UnloadPlugin(int iPlugin) = 0; + + virtual luaplugin_t* GetPlugin(int iPlugin) = 0; + virtual const char* RunString(const char* pCode,size_t len,const char* pName) = 0; + + virtual CLuaInterface* GetLuaInterface() = 0; + virtual void Print(const char* fmt,...) = 0; + + virtual luafile_err_t RunFile(const char* pFile,const char** ppErr = NULL, + lua_State* pL = NULL) = 0; + + virtual void SetLuaCallbacks(ILua502Callbacks* pCallbacks) = 0; + virtual ILua502Callbacks* GetLuaCallbacks() = 0; + + virtual void Lock() = 0; + virtual void Unlock() = 0; +}; +#define INTERFACEVERSION_LUA502 "LUA502_001" + +LUA_API int lua502_atpanic(lua_State* L); +LUA_API int lua502_aterror(lua_State* L); + +#endif \ No newline at end of file diff --git a/lua/lua502_sdk/lauxlib.h b/lua/lua502_sdk/lauxlib.h new file mode 100644 index 0000000..450e16c --- /dev/null +++ b/lua/lua502_sdk/lauxlib.h @@ -0,0 +1,145 @@ +/* +** $Id: lauxlib.h,v 1.60 2003/04/03 13:35:34 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lauxlib_h +#define lauxlib_h + + +#include +#include + +#include "lua.h" + + +#ifndef LUALIB_API +#define LUALIB_API LUA_API +#endif + + + +typedef struct luaL_reg { + const char *name; + lua_CFunction func; +} luaL_reg; + + +LUALIB_API void luaL_openlib (lua_State *L, const char *libname, + const luaL_reg *l, int nup); +LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *e); +LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *e); +LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname); +LUALIB_API int luaL_argerror (lua_State *L, int numarg, const char *extramsg); +LUALIB_API const char *luaL_checklstring (lua_State *L, int numArg, size_t *l); +LUALIB_API const char *luaL_optlstring (lua_State *L, int numArg, + const char *def, size_t *l); +LUALIB_API lua_Number luaL_checknumber (lua_State *L, int numArg); +LUALIB_API lua_Number luaL_optnumber (lua_State *L, int nArg, lua_Number def); + +LUALIB_API void luaL_checkstack (lua_State *L, int sz, const char *msg); +LUALIB_API void luaL_checktype (lua_State *L, int narg, int t); +LUALIB_API void luaL_checkany (lua_State *L, int narg); + +LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname); +LUALIB_API void luaL_getmetatable (lua_State *L, const char *tname); +LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname); + +LUALIB_API void luaL_where (lua_State *L, int lvl); +LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...); + +LUALIB_API int luaL_findstring (const char *st, const char *const lst[]); + +LUALIB_API int luaL_ref (lua_State *L, int t); +LUALIB_API void luaL_unref (lua_State *L, int t, int ref); + +LUALIB_API int luaL_getn (lua_State *L, int t); +LUALIB_API void luaL_setn (lua_State *L, int t, int n); + +LUALIB_API int luaL_loadfile (lua_State *L, const char *filename); +LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t sz, + const char *name); + + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define luaL_argcheck(L, cond,numarg,extramsg) if (!(cond)) \ + luaL_argerror(L, numarg,extramsg) +#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) +#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) +#define luaL_checkint(L,n) ((int)luaL_checknumber(L, n)) +#define luaL_checklong(L,n) ((long)luaL_checknumber(L, n)) +#define luaL_optint(L,n,d) ((int)luaL_optnumber(L, n,(lua_Number)(d))) +#define luaL_optlong(L,n,d) ((long)luaL_optnumber(L, n,(lua_Number)(d))) + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + + +#ifndef LUAL_BUFFERSIZE +#define LUAL_BUFFERSIZE BUFSIZ +#endif + + +typedef struct luaL_Buffer { + char *p; /* current position in buffer */ + int lvl; /* number of strings in the stack (level) */ + lua_State *L; + char buffer[LUAL_BUFFERSIZE]; +} luaL_Buffer; + +#define luaL_putchar(B,c) \ + ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ + (*(B)->p++ = (char)(c))) + +#define luaL_addsize(B,n) ((B)->p += (n)) + +LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B); +LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B); +LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l); +LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s); +LUALIB_API void luaL_addvalue (luaL_Buffer *B); +LUALIB_API void luaL_pushresult (luaL_Buffer *B); + + +/* }====================================================== */ + + + +/* +** Compatibility macros and functions +*/ + +LUALIB_API int lua_dofile (lua_State *L, const char *filename); +LUALIB_API int lua_dostring (lua_State *L, const char *str); +LUALIB_API int lua_dobuffer (lua_State *L, const char *buff, size_t sz, + const char *n); + + +#define luaL_check_lstr luaL_checklstring +#define luaL_opt_lstr luaL_optlstring +#define luaL_check_number luaL_checknumber +#define luaL_opt_number luaL_optnumber +#define luaL_arg_check luaL_argcheck +#define luaL_check_string luaL_checkstring +#define luaL_opt_string luaL_optstring +#define luaL_check_int luaL_checkint +#define luaL_check_long luaL_checklong +#define luaL_opt_int luaL_optint +#define luaL_opt_long luaL_optlong + + +#endif + + diff --git a/lua/lua502_sdk/lua.h b/lua/lua502_sdk/lua.h new file mode 100644 index 0000000..2173541 --- /dev/null +++ b/lua/lua502_sdk/lua.h @@ -0,0 +1,395 @@ +/* +** $Id: lua.h,v 1.175b 2003/03/18 12:31:39 roberto Exp $ +** Lua - An Extensible Extension Language +** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil +** http://www.lua.org mailto:info@lua.org +** See Copyright Notice at the end of this file +*/ + + +#ifndef lua_h +#define lua_h + +#include +#include + + +#define LUA_VERSION "Lua 5.0.2" +#define LUA_COPYRIGHT "Copyright (C) 1994-2004 Tecgraf, PUC-Rio" +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" + + + +/* option for multiple returns in `lua_pcall' and `lua_call' */ +#define LUA_MULTRET (-1) + + +/* +** pseudo-indices +*/ +#define LUA_REGISTRYINDEX (-10000) +#define LUA_GLOBALSINDEX (-10001) +#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) + + +/* error codes for `lua_load' and `lua_pcall' */ +#define LUA_ERRRUN 1 +#define LUA_ERRFILE 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRERR 5 + + +typedef struct lua_State lua_State; + +typedef int (*lua_CFunction) (lua_State *L); + + +/* +** functions that read/write blocks when loading/dumping Lua chunks +*/ +typedef const char * (*lua_Chunkreader) (lua_State *L, void *ud, size_t *sz); + +typedef int (*lua_Chunkwriter) (lua_State *L, const void* p, + size_t sz, void* ud); + + +/* +** basic types +*/ +#define LUA_TNONE (-1) + +#define LUA_TNIL 0 +#define LUA_TBOOLEAN 1 +#define LUA_TLIGHTUSERDATA 2 +#define LUA_TNUMBER 3 +#define LUA_TSTRING 4 +#define LUA_TTABLE 5 +#define LUA_TFUNCTION 6 +#define LUA_TUSERDATA 7 +#define LUA_TTHREAD 8 + + +/* minimum Lua stack available to a C function */ +#define LUA_MINSTACK 20 + + +/* +** generic extra include file +*/ +#ifdef LUA_USER_H +#include LUA_USER_H +#endif + + +/* type of numbers in Lua */ +#ifndef LUA_NUMBER +typedef double lua_Number; +#else +typedef LUA_NUMBER lua_Number; +#endif + + +/* mark for all API functions */ +#ifndef LUA_API +#ifndef LUA_DLL +# define LUA_API extern "C" __declspec(dllimport) +#else +# define LUA_API extern "C" __declspec(dllexport) +#endif +#endif + + +/* +** state manipulation +*/ +LUA_API lua_State *lua_open (void); +LUA_API void lua_close (lua_State *L); +LUA_API lua_State *lua_newthread (lua_State *L); + +LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf); + + +/* +** basic stack manipulation +*/ +LUA_API int lua_gettop (lua_State *L); +LUA_API void lua_settop (lua_State *L, int idx); +LUA_API void lua_pushvalue (lua_State *L, int idx); +LUA_API void lua_remove (lua_State *L, int idx); +LUA_API void lua_insert (lua_State *L, int idx); +LUA_API void lua_replace (lua_State *L, int idx); +LUA_API int lua_checkstack (lua_State *L, int sz); + +LUA_API void lua_xmove (lua_State *from, lua_State *to, int n); + + +/* +** access functions (stack -> C) +*/ + +LUA_API int lua_isnumber (lua_State *L, int idx); +LUA_API int lua_isstring (lua_State *L, int idx); +LUA_API int lua_iscfunction (lua_State *L, int idx); +LUA_API int lua_isuserdata (lua_State *L, int idx); +LUA_API int lua_type (lua_State *L, int idx); +LUA_API const char *lua_typename (lua_State *L, int tp); + +LUA_API int lua_equal (lua_State *L, int idx1, int idx2); +LUA_API int lua_rawequal (lua_State *L, int idx1, int idx2); +LUA_API int lua_lessthan (lua_State *L, int idx1, int idx2); + +LUA_API lua_Number lua_tonumber (lua_State *L, int idx); +LUA_API int lua_toboolean (lua_State *L, int idx); +LUA_API const char *lua_tostring (lua_State *L, int idx); +LUA_API size_t lua_strlen (lua_State *L, int idx); +LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx); +LUA_API void *lua_touserdata (lua_State *L, int idx); +LUA_API lua_State *lua_tothread (lua_State *L, int idx); +LUA_API const void *lua_topointer (lua_State *L, int idx); + + +/* +** push functions (C -> stack) +*/ +LUA_API void lua_pushnil (lua_State *L); +LUA_API void lua_pushnumber (lua_State *L, lua_Number n); +LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t l); +LUA_API void lua_pushstring (lua_State *L, const char *s); +LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, + va_list argp); +LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...); +LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n); +LUA_API void lua_pushboolean (lua_State *L, int b); +LUA_API void lua_pushlightuserdata (lua_State *L, void *p); + + +/* +** get functions (Lua -> stack) +*/ +LUA_API void lua_gettable (lua_State *L, int idx); +LUA_API void lua_rawget (lua_State *L, int idx); +LUA_API void lua_rawgeti (lua_State *L, int idx, int n); +LUA_API void lua_newtable (lua_State *L); +LUA_API void *lua_newuserdata (lua_State *L, size_t sz); +LUA_API int lua_getmetatable (lua_State *L, int objindex); +LUA_API void lua_getfenv (lua_State *L, int idx); + + +/* +** set functions (stack -> Lua) +*/ +LUA_API void lua_settable (lua_State *L, int idx); +LUA_API void lua_rawset (lua_State *L, int idx); +LUA_API void lua_rawseti (lua_State *L, int idx, int n); +LUA_API int lua_setmetatable (lua_State *L, int objindex); +LUA_API int lua_setfenv (lua_State *L, int idx); + + +/* +** `load' and `call' functions (load and run Lua code) +*/ +LUA_API void lua_call (lua_State *L, int nargs, int nresults); +LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc); +LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud); +LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *dt, + const char *chunkname); + +LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data); + + +/* +** coroutine functions +*/ +LUA_API int lua_yield (lua_State *L, int nresults); +LUA_API int lua_resume (lua_State *L, int narg); + +/* +** garbage-collection functions +*/ +LUA_API int lua_getgcthreshold (lua_State *L); +LUA_API int lua_getgccount (lua_State *L); +LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold); + +/* +** miscellaneous functions +*/ + +LUA_API const char *lua_version (void); + +LUA_API int lua_error (lua_State *L); + +LUA_API int lua_next (lua_State *L, int idx); + +LUA_API void lua_concat (lua_State *L, int n); + + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define lua_boxpointer(L,u) \ + (*(void **)(lua_newuserdata(L, sizeof(void *))) = (u)) + +#define lua_unboxpointer(L,i) (*(void **)(lua_touserdata(L, i))) + +#define lua_pop(L,n) lua_settop(L, -(n)-1) + +#define lua_register(L,n,f) \ + (lua_pushstring(L, n), \ + lua_pushcfunction(L, f), \ + lua_settable(L, LUA_GLOBALSINDEX)) + +#define lua_pushcfunction(L,f) lua_pushcclosure(L, f, 0) + +#define lua_isfunction(L,n) (lua_type(L,n) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L,n) == LUA_TTABLE) +#define lua_islightuserdata(L,n) (lua_type(L,n) == LUA_TLIGHTUSERDATA) +#define lua_isnil(L,n) (lua_type(L,n) == LUA_TNIL) +#define lua_isboolean(L,n) (lua_type(L,n) == LUA_TBOOLEAN) +#define lua_isnone(L,n) (lua_type(L,n) == LUA_TNONE) +#define lua_isnoneornil(L, n) (lua_type(L,n) <= 0) + +#define lua_pushliteral(L, s) \ + lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) + + + +/* +** compatibility macros and functions +*/ + + +LUA_API int lua_pushupvalues (lua_State *L); + +#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) +#define lua_setglobal(L,s) \ + (lua_pushstring(L, s), lua_insert(L, -2), lua_settable(L, LUA_GLOBALSINDEX)) + +#define lua_getglobal(L,s) \ + (lua_pushstring(L, s), lua_gettable(L, LUA_GLOBALSINDEX)) + + +/* compatibility with ref system */ + +/* pre-defined references */ +#define LUA_NOREF (-2) +#define 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) + + + +/* +** {====================================================================== +** useful definitions for Lua kernel and libraries +** ======================================================================= +*/ + +/* formats for Lua numbers */ +#ifndef LUA_NUMBER_SCAN +#define LUA_NUMBER_SCAN "%lf" +#endif + +#ifndef LUA_NUMBER_FMT +#define LUA_NUMBER_FMT "%.14g" +#endif + +/* }====================================================================== */ + + +/* +** {====================================================================== +** Debug API +** ======================================================================= +*/ + + +/* +** Event codes +*/ +#define LUA_HOOKCALL 0 +#define LUA_HOOKRET 1 +#define LUA_HOOKLINE 2 +#define LUA_HOOKCOUNT 3 +#define LUA_HOOKTAILRET 4 + + +/* +** Event masks +*/ +#define LUA_MASKCALL (1 << LUA_HOOKCALL) +#define LUA_MASKRET (1 << LUA_HOOKRET) +#define LUA_MASKLINE (1 << LUA_HOOKLINE) +#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) + +typedef struct lua_Debug lua_Debug; /* activation record */ + +typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); + + +LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); +LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); +LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); + +LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); +LUA_API lua_Hook lua_gethook (lua_State *L); +LUA_API int lua_gethookmask (lua_State *L); +LUA_API int lua_gethookcount (lua_State *L); + + +#define LUA_IDSIZE 60 + +struct lua_Debug { + int event; + const char *name; /* (n) */ + const char *namewhat; /* (n) `global', `local', `field', `method' */ + const char *what; /* (S) `Lua', `C', `main', `tail' */ + const char *source; /* (S) */ + int currentline; /* (l) */ + int nups; /* (u) number of upvalues */ + int linedefined; /* (S) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + int i_ci; /* active function */ +}; + +/* }====================================================================== */ + + +/****************************************************************************** +* Copyright (C) 1994-2004 Tecgraf, PUC-Rio. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + + +#endif diff --git a/lua/lua502_sdk/lua.hpp b/lua/lua502_sdk/lua.hpp new file mode 100644 index 0000000..e2baf40 --- /dev/null +++ b/lua/lua502_sdk/lua.hpp @@ -0,0 +1,11 @@ +#ifndef __LUA_HPP +#define __LUA_HPP + +extern "C" +{ + #include "lua.h" + #include "lualib.h" + #include "lauxlib.h" +} + +#endif \ No newline at end of file diff --git a/lua/lua502_sdk/lua502_sdk.vcxproj b/lua/lua502_sdk/lua502_sdk.vcxproj new file mode 100644 index 0000000..69efe68 --- /dev/null +++ b/lua/lua502_sdk/lua502_sdk.vcxproj @@ -0,0 +1,90 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {F71BDA01-BDD1-4EE4-85A4-FAD463C5AAED} + lua502_sdk + + + + Application + true + MultiByte + + + StaticLibrary + false + true + MultiByte + + + + + + + + + + + + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + true + true + D:\source2006\public\tier1;D:\source2006\public\tier0;D:\source2006\public;D:\source2006\common;%(AdditionalIncludeDirectories) + + + true + true + true + + + lua502.lib;%(AdditionalDependencies) + + + D:\lua502\lua\Release;%(AdditionalLibraryDirectories) + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lua/lua502_sdk/lua502_sdk.vcxproj.filters b/lua/lua502_sdk/lua502_sdk.vcxproj.filters new file mode 100644 index 0000000..dd88ac0 --- /dev/null +++ b/lua/lua502_sdk/lua502_sdk.vcxproj.filters @@ -0,0 +1,63 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + \ No newline at end of file diff --git a/lua/lua502_sdk/lua502_sdk.vcxproj.user b/lua/lua502_sdk/lua502_sdk.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/lua/lua502_sdk/lua502_sdk.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lua/lua502_sdk/lualib.h b/lua/lua502_sdk/lualib.h new file mode 100644 index 0000000..e22c4c3 --- /dev/null +++ b/lua/lua502_sdk/lualib.h @@ -0,0 +1,56 @@ +/* +** $Id: lualib.h,v 1.28 2003/03/18 12:24:26 roberto Exp $ +** Lua standard libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lualib_h +#define lualib_h + +#include "lua.h" + + +#ifndef LUALIB_API +#define LUALIB_API LUA_API +#endif + + +#define LUA_COLIBNAME "coroutine" +LUALIB_API int luaopen_base (lua_State *L); + +#define LUA_TABLIBNAME "table" +LUALIB_API int luaopen_table (lua_State *L); + +#define LUA_IOLIBNAME "io" +#define LUA_OSLIBNAME "os" +LUALIB_API int luaopen_io (lua_State *L); + +#define LUA_STRLIBNAME "string" +LUALIB_API int luaopen_string (lua_State *L); + +#define LUA_MATHLIBNAME "math" +LUALIB_API int luaopen_math (lua_State *L); + +#define LUA_DBLIBNAME "debug" +LUALIB_API int luaopen_debug (lua_State *L); + + +LUALIB_API int luaopen_loadlib (lua_State *L); + + +/* to help testing the libraries */ +#ifndef lua_assert +#define lua_assert(c) /* empty */ +#endif + + +/* compatibility code */ +#define lua_baselibopen luaopen_base +#define lua_tablibopen luaopen_table +#define lua_iolibopen luaopen_io +#define lua_strlibopen luaopen_string +#define lua_mathlibopen luaopen_math +#define lua_dblibopen luaopen_debug + +#endif diff --git a/lua/lua502_sdk/plugin.cpp b/lua/lua502_sdk/plugin.cpp new file mode 100644 index 0000000..80d736d --- /dev/null +++ b/lua/lua502_sdk/plugin.cpp @@ -0,0 +1,98 @@ +#include "plugin.h" + +ILua502* g_pLua502 = NULL; + +CBasePlugin::CBasePlugin() +{ +} + +bool CBasePlugin::Load(CreateInterfaceFn,CreateInterfaceFn) +{ + return true; +} + +void CBasePlugin::Unload() +{ +} + +void CBasePlugin::Pause() +{ +} + +void CBasePlugin::UnPause() +{ +} + +const char* CBasePlugin::GetPluginDescription() +{ + return s_pPluginName; +} + +void CBasePlugin::LevelInit(const char*) +{ +} + +void CBasePlugin::ServerActivate(edict_t*,int,int) +{ +} + +void CBasePlugin::GameFrame(bool) +{ +} + +void CBasePlugin::LevelShutdown() +{ +} + +void CBasePlugin::ClientActive(edict_t*) +{ +} + +void CBasePlugin::ClientDisconnect(edict_t*) +{ +} + +void CBasePlugin::ClientPutInServer(edict_t*,const char*) +{ +} + +void CBasePlugin::SetCommandClient(int iIndex) +{ + m_iCommandClientIndex = iIndex; +} + +void CBasePlugin::ClientSettingsChanged(edict_t*) +{ +} + +PLUGIN_RESULT CBasePlugin::ClientConnect(bool*,edict_t*, + const char*,const char*,char*,int) +{ + return PLUGIN_CONTINUE; +} + +PLUGIN_RESULT CBasePlugin::ClientCommand(edict_t*) +{ + return PLUGIN_CONTINUE; +} + +PLUGIN_RESULT CBasePlugin::NetworkIDValidated(const char*, + const char*) +{ + return PLUGIN_CONTINUE; +} + +bool CBasePlugin::GlobalInit(ILua502* pLua502) +{ + g_pLua502 = pLua502; + return true; +} + +bool CBasePlugin::LuaInit(lua_State*) +{ + return true; +} + +void CBasePlugin::OnSWEPLuaCreate(lua_State*) +{ +} \ No newline at end of file diff --git a/lua/lua502_sdk/plugin.h b/lua/lua502_sdk/plugin.h new file mode 100644 index 0000000..050d4ee --- /dev/null +++ b/lua/lua502_sdk/plugin.h @@ -0,0 +1,57 @@ +#ifndef __PLUGIN_H +#define __PLUGIN_H + +#include "glua.h" +#include "networkvar.h" + +class CBasePlugin : public ILuaPluginCallbacks +{ +public: + CBasePlugin(); + + virtual bool Load(CreateInterfaceFn,CreateInterfaceFn); + virtual void Unload(); + virtual void Pause(); + virtual void UnPause(); + virtual const char* GetPluginDescription(); + + virtual void LevelInit(const char*); + virtual void ServerActivate(edict_t*,int,int); + virtual void GameFrame(bool); + virtual void LevelShutdown(); + + virtual void ClientActive(edict_t*); + virtual void ClientDisconnect(edict_t*); + virtual void ClientPutInServer(edict_t*,const char*); + virtual void SetCommandClient(int); + virtual void ClientSettingsChanged(edict_t*); + + virtual PLUGIN_RESULT ClientConnect(bool*,edict_t*,const char*, + const char*,char*,int); + virtual PLUGIN_RESULT ClientCommand(edict_t*); + virtual PLUGIN_RESULT NetworkIDValidated(const char*, + const char*); + + virtual bool GlobalInit(ILua502*); + virtual bool LuaInit(lua_State*); + virtual void OnSWEPLuaCreate(lua_State*); +private: + int m_iCommandClientIndex; + static const char* s_pPluginName; +}; + +#define DECLARE_PLUGIN(dllName) \ + class dllName : public CBasePlugin \ + { \ + public: \ + DECLARE_CLASS(dllName,CBasePlugin); +#define END_PLUGIN(dllName,plugName) \ + }; \ + const char* CBasePlugin::s_pPluginName = plugName; \ + static dllName s_##dllName; \ + EXPOSE_SINGLE_INTERFACE_GLOBALVAR(dllName,IServerPluginCallbacks, \ + INTERFACEVERSION_ISERVERPLUGINCALLBACKS,s_##dllName) + +extern ILua502* g_pLua502; + +#endif \ No newline at end of file diff --git a/lua/lua502_sdk/sigscan.cpp b/lua/lua502_sdk/sigscan.cpp new file mode 100644 index 0000000..599728f --- /dev/null +++ b/lua/lua502_sdk/sigscan.cpp @@ -0,0 +1,95 @@ +#include "sigscan.h" + +static SigScan::CSigScan* s_pLast; + +void SigScan_Notify(SigScan::CSigScan* pSigScan,SigScan::SigNotify_t notify) +{ + char szError[64]; + if(notify==SigScan::SIG_ERROR) + { + sprintf(szError,"%s (%p) sigscan failed!",pSigScan->m_pName,pSigScan->m_pdwDest); + MessageBoxA(NULL,szError,"SigScan",MB_ICONHAND); + ExitThread(1); + } +} + +SigScan::CSigScan::CSigScan(const char* pName,const char* pDll,const char* pSig,const char* pMask, + PDWORD pdwDest,DWORD dwOffset = 0,SigType_t type) +{ + m_pPrev = NULL; + + m_pName = pName; + m_pDll = pDll; + m_pSig = pSig; + m_pMask = pMask; + m_pdwDest = pdwDest; + m_dwOffset = dwOffset; + m_Type = type; + + Add(this); +} + +void SigScan::Add(CSigScan* pSigScan) +{ + pSigScan->m_pPrev = s_pLast; + s_pLast = pSigScan; +} + +void SigScan::Scan() +{ + CSigScan* pSigScan = s_pLast; + DWORD dwTrunk; + + do { + if(!(dwTrunk = SigScan(GetModuleHandle(pSigScan->m_pDll), + pSigScan->m_pSig,pSigScan->m_pMask))) + { + SigScan_Notify(pSigScan,SIG_ERROR); + continue; + } + + dwTrunk += pSigScan->m_dwOffset; + switch(pSigScan->m_Type) + { + case CSigScan::SIG_FUNCTION: + *pSigScan->m_pdwDest = dwTrunk; + break; + case CSigScan::SIG_PTR: + *pSigScan->m_pdwDest = *(PDWORD)(dwTrunk); + break; + case CSigScan::SIG_VARIABLE: + *pSigScan->m_pdwDest = **(PDWORD*)(dwTrunk); + break; + } + SigScan_Notify(pSigScan,SIG_LOG); + } while((pSigScan = pSigScan->m_pPrev)); +} + +size_t SigScan::GetModuleSize(HMODULE hDll) +{ + PIMAGE_DOS_HEADER DosHeader; + PIMAGE_NT_HEADERS NtHeaders; + + DosHeader = (PIMAGE_DOS_HEADER)hDll; + NtHeaders = (PIMAGE_NT_HEADERS)((LONG)hDll+DosHeader->e_lfanew); + + return NtHeaders->OptionalHeader.SizeOfImage; +} + +DWORD SigScan::SigScan(HMODULE hDll,const char* sig,const char* mask) +{ + size_t j,size = GetModuleSize(hDll),len = strlen(mask); + char* mem = (char*)hDll; + for(size_t i = 0; i < size; i++) + { + for(j = 0; j < len; j++) + { + if((mask[j] != '?') && (((char*)(mem+i))[j] != sig[j])) + break; + } + + if(j==len) + return (DWORD)(mem+i); + } + return NULL; +} \ No newline at end of file diff --git a/lua/lua502_sdk/sigscan.h b/lua/lua502_sdk/sigscan.h new file mode 100644 index 0000000..743d17c --- /dev/null +++ b/lua/lua502_sdk/sigscan.h @@ -0,0 +1,49 @@ +#ifndef __SIGSCAN_H +#define __SIGSCAN_H + +#include +#include + +namespace SigScan +{ + class CSigScan + { + public: + typedef enum { + SIG_FUNCTION, + SIG_VARIABLE, + SIG_PTR, + } SigType_t; + + CSigScan(const char* pName,const char* pDll,const char* pSig,const char* pMask, + PDWORD pdwDest,DWORD dwOffset,SigType_t type = SIG_FUNCTION); + + CSigScan* m_pPrev; + + const char* m_pName; + const char* m_pDll; + const char* m_pSig; + const char* m_pMask; + + PDWORD m_pdwDest; + DWORD m_dwOffset; + SigType_t m_Type; + }; + + typedef enum { + SIG_LOG, + SIG_ERROR, + } SigNotify_t; + + size_t GetModuleSize(HMODULE hDll); + DWORD SigScan(HMODULE hDll,const char* pSig,const char* pMask); + + void Scan(); + void Add(CSigScan* pSigScan); + + //CSigScan* s_pLast; +} + +#define DECLARE_SIGSCAN(dst,dll,sig,mask,ofst,type) SigScan::CSigScan dst##_s(#dst,dll,sig,mask,(PDWORD)&dst,ofst,type) + +#endif \ No newline at end of file diff --git a/lua/lua502_sdk/types.cpp b/lua/lua502_sdk/types.cpp new file mode 100644 index 0000000..c56b350 --- /dev/null +++ b/lua/lua502_sdk/types.cpp @@ -0,0 +1,13 @@ +#include "types.h" + +static char* s_TypeNames[] = { + "Pointer", + "LuaPluign", + "ConVar", + "Command" +}; + +LUA_API const char* luaf_typename(int type) +{ + return s_TypeNames[type]; +} \ No newline at end of file diff --git a/lua/lua502_sdk/types.h b/lua/lua502_sdk/types.h new file mode 100644 index 0000000..9b342d6 --- /dev/null +++ b/lua/lua502_sdk/types.h @@ -0,0 +1,7 @@ +#ifndef __TYPES_H + +#include "lua.hpp" + +LUA_API const char* luaf_typename(int type); + +#endif \ No newline at end of file diff --git a/lua/lzss/Release/CL.read.1.tlog b/lua/lzss/Release/CL.read.1.tlog new file mode 100644 index 0000000..c747fae Binary files /dev/null and b/lua/lzss/Release/CL.read.1.tlog differ diff --git a/lua/lzss/Release/CL.write.1.tlog b/lua/lzss/Release/CL.write.1.tlog new file mode 100644 index 0000000..1b0631b Binary files /dev/null and b/lua/lzss/Release/CL.write.1.tlog differ diff --git a/lua/lzss/Release/cl.command.1.tlog b/lua/lzss/Release/cl.command.1.tlog new file mode 100644 index 0000000..ea481b9 Binary files /dev/null and b/lua/lzss/Release/cl.command.1.tlog differ diff --git a/lua/lzss/Release/link.command.1.tlog b/lua/lzss/Release/link.command.1.tlog new file mode 100644 index 0000000..7ee22fb Binary files /dev/null and b/lua/lzss/Release/link.command.1.tlog differ diff --git a/lua/lzss/Release/link.read.1.tlog b/lua/lzss/Release/link.read.1.tlog new file mode 100644 index 0000000..87006d1 Binary files /dev/null and b/lua/lzss/Release/link.read.1.tlog differ diff --git a/lua/lzss/Release/link.write.1.tlog b/lua/lzss/Release/link.write.1.tlog new file mode 100644 index 0000000..bd98419 Binary files /dev/null and b/lua/lzss/Release/link.write.1.tlog differ diff --git a/lua/lzss/Release/lzss.Build.CppClean.log b/lua/lzss/Release/lzss.Build.CppClean.log new file mode 100644 index 0000000..987a7db --- /dev/null +++ b/lua/lzss/Release/lzss.Build.CppClean.log @@ -0,0 +1,16 @@ +D:\lua502\lua\lzss\Release\cl.command.1.tlog +D:\lua502\lua\lzss\Release\CL.read.1.tlog +D:\lua502\lua\lzss\Release\CL.write.1.tlog +D:\lua502\lua\lzss\Release\link.command.1.tlog +D:\lua502\lua\lzss\Release\link.read.1.tlog +D:\lua502\lua\lzss\Release\link.write.1.tlog +D:\LUA502\LUA\LZSS\RELEASE\LZSS.EXE.INTERMEDIATE.MANIFEST +D:\LUA502\LUA\LZSS\RELEASE\LZSS.OBJ +D:\lua502\lua\lzss\Release\lzss.write.1.tlog +D:\LUA502\LUA\LZSS\RELEASE\MAIN.OBJ +D:\lua502\lua\lzss\Release\mt.command.1.tlog +D:\lua502\lua\lzss\Release\mt.read.1.tlog +D:\lua502\lua\lzss\Release\mt.write.1.tlog +D:\LUA502\LUA\LZSS\RELEASE\VC100.PDB +D:\LUA502\LUA\RELEASE\LZSS.EXE +D:\LUA502\LUA\RELEASE\LZSS.PDB diff --git a/lua/lzss/Release/lzss.dll.intermediate.manifest b/lua/lzss/Release/lzss.dll.intermediate.manifest new file mode 100644 index 0000000..ecea6f7 --- /dev/null +++ b/lua/lzss/Release/lzss.dll.intermediate.manifest @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/lua/lzss/Release/lzss.exe.intermediate.manifest b/lua/lzss/Release/lzss.exe.intermediate.manifest new file mode 100644 index 0000000..ecea6f7 --- /dev/null +++ b/lua/lzss/Release/lzss.exe.intermediate.manifest @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/lua/lzss/Release/lzss.lastbuildstate b/lua/lzss/Release/lzss.lastbuildstate new file mode 100644 index 0000000..c2d4a05 --- /dev/null +++ b/lua/lzss/Release/lzss.lastbuildstate @@ -0,0 +1,2 @@ +#v4.0:v100:false +Release|Win32|D:\lua502\lua\| diff --git a/lua/lzss/Release/lzss.log b/lua/lzss/Release/lzss.log new file mode 100644 index 0000000..94c4ee5 --- /dev/null +++ b/lua/lzss/Release/lzss.log @@ -0,0 +1,25 @@ +Build started 24.09.2017 22:02:15. + 1>Project "D:\lua502\lua\lzss\lzss.vcxproj" on node 2 (build target(s)). + 1>InitializeBuildStatus: + Creating "Release\lzss.unsuccessfulbuild" because "AlwaysCreate" was specified. + ClCompile: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\CL.exe /c /ID:\source2006\common\ /ID:\source2006\utils\lzma\ /ID:\source2006\public\tier1 /ID:\source2006\public\tier0 /ID:\source2006\public\ /Zi /nologo /W3 /WX- /O2 /Oi /Oy- /GL /D _MBCS /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Release\\" /Fd"Release\vc100.pdb" /Gd /TP /analyze- /errorReport:prompt main.cpp + main.cpp + 1>main.cpp(13): warning C4018: <: неÑоответÑтвие типов Ñо знаком и без знака + Link: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:"D:\lua502\lua\Release\lzss.exe" /NOLOGO /LIBPATH:D:\source2006\lib\public /LIBPATH:D:\source2006\lib\common tier0.lib tier1.lib lzma.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /MANIFEST /ManifestFile:"Release\lzss.exe.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"D:\lua502\lua\Release\lzss.pdb" /OPT:REF /OPT:ICF /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"D:\lua502\lua\Release\lzss.lib" /MACHINE:X86 Release\lzss.obj + Release\main.obj + 1>LINK : warning LNK4098: библиотека по умолчанию "LIBCMT" противоречит иÑпользованию других библиотек; иÑпользуйте параметр /NODEFAULTLIB:library + Создание кода + Создание кода завершено + lzss.vcxproj -> D:\lua502\lua\Release\lzss.exe + Manifest: + C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe /nologo /verbose /outputresource:"D:\lua502\lua\Release\lzss.exe;#1" /manifest Release\lzss.exe.intermediate.manifest + FinalizeBuildStatus: + Deleting file "Release\lzss.unsuccessfulbuild". + Touching "Release\lzss.lastbuildstate". + 1>Done Building Project "D:\lua502\lua\lzss\lzss.vcxproj" (build target(s)). + +ПоÑтроение уÑпешно завершено. + +Time Elapsed 00:00:02.43 diff --git a/lua/lzss/Release/lzss.obj b/lua/lzss/Release/lzss.obj new file mode 100644 index 0000000..3f33270 Binary files /dev/null and b/lua/lzss/Release/lzss.obj differ diff --git a/lua/lzss/Release/lzss.vcxprojResolveAssemblyReference.cache b/lua/lzss/Release/lzss.vcxprojResolveAssemblyReference.cache new file mode 100644 index 0000000..3f01681 Binary files /dev/null and b/lua/lzss/Release/lzss.vcxprojResolveAssemblyReference.cache differ diff --git a/lua/lzss/Release/lzss.write.1.tlog b/lua/lzss/Release/lzss.write.1.tlog new file mode 100644 index 0000000..e69de29 diff --git a/lua/lzss/Release/main.obj b/lua/lzss/Release/main.obj new file mode 100644 index 0000000..6888156 Binary files /dev/null and b/lua/lzss/Release/main.obj differ diff --git a/lua/lzss/Release/mt.command.1.tlog b/lua/lzss/Release/mt.command.1.tlog new file mode 100644 index 0000000..a1292ec Binary files /dev/null and b/lua/lzss/Release/mt.command.1.tlog differ diff --git a/lua/lzss/Release/mt.read.1.tlog b/lua/lzss/Release/mt.read.1.tlog new file mode 100644 index 0000000..0c2ea60 Binary files /dev/null and b/lua/lzss/Release/mt.read.1.tlog differ diff --git a/lua/lzss/Release/mt.write.1.tlog b/lua/lzss/Release/mt.write.1.tlog new file mode 100644 index 0000000..bd0cd35 Binary files /dev/null and b/lua/lzss/Release/mt.write.1.tlog differ diff --git a/lua/lzss/Release/vc100.pdb b/lua/lzss/Release/vc100.pdb new file mode 100644 index 0000000..fd4cdee Binary files /dev/null and b/lua/lzss/Release/vc100.pdb differ diff --git a/lua/lzss/lzss.cpp b/lua/lzss/lzss.cpp new file mode 100644 index 0000000..11d8113 --- /dev/null +++ b/lua/lzss/lzss.cpp @@ -0,0 +1,295 @@ +//========= Copyright © 1996-2007, Valve Corporation, All rights reserved. ============// +// +// LZSS Codec. Designed for fast cheap gametime encoding/decoding. Compression results +// are not aggresive as other alogrithms, but gets 2:1 on most arbitrary uncompressed data. +// +//=====================================================================================// + +#include "tier0/platform.h" +#include "tier0/dbg.h" +#include "lzss.h" + +#define LZSS_LOOKSHIFT 4 +#define LZSS_LOOKAHEAD ( 1 << LZSS_LOOKSHIFT ) + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +CLZSS::CLZSS( int nWindowSize ) +{ + m_nWindowSize = nWindowSize; +} + +//----------------------------------------------------------------------------- +// Returns true if buffer is compressed. +//----------------------------------------------------------------------------- +bool CLZSS::IsCompressed( unsigned char *pInput ) +{ + lzss_header_t *pHeader = (lzss_header_t *)pInput; + if ( pHeader && pHeader->id == LZSS_ID ) + { + return true; + } + + // unrecognized + return false; +} + +//----------------------------------------------------------------------------- +// Returns uncompressed size of compressed input buffer. Used for allocating output +// buffer for decompression. Returns 0 if input buffer is not compressed. +//----------------------------------------------------------------------------- +unsigned int CLZSS::GetActualSize( unsigned char *pInput ) +{ + lzss_header_t *pHeader = (lzss_header_t *)pInput; + if ( pHeader && pHeader->id == LZSS_ID ) + { + return LittleLong( pHeader->actualSize ); + } + + // unrecognized + return 0; +} + +void CLZSS::BuildHash( unsigned char *pData ) +{ + lzss_list_t *pList; + lzss_node_t *pTarget; + + int targetindex = (unsigned int)pData & ( m_nWindowSize - 1 ); + pTarget = &m_pHashTarget[targetindex]; + if ( pTarget->pData ) + { + pList = &m_pHashTable[*pTarget->pData]; + if ( pTarget->pPrev ) + { + pList->pEnd = pTarget->pPrev; + pTarget->pPrev->pNext = 0; + } + else + { + pList->pEnd = 0; + pList->pStart = 0; + } + } + + pList = &m_pHashTable[*pData]; + pTarget->pData = pData; + pTarget->pPrev = 0; + pTarget->pNext = pList->pStart; + if ( pList->pStart ) + { + pList->pStart->pPrev = pTarget; + } + else + { + pList->pEnd = pTarget; + } + pList->pStart = pTarget; +} + +unsigned char *CLZSS::CompressNoAlloc( unsigned char *pInput, int inputLength, unsigned char *pOutputBuf, unsigned int *pOutputSize ) +{ + if ( inputLength <= sizeof( lzss_header_t ) + 8 ) + { + puts("inputLength too small"); + return NULL; + } + + // create the compression work buffers, small enough (~64K) for stack + m_pHashTable = (lzss_list_t *)stackalloc( 256 * sizeof( lzss_list_t ) ); + memset( m_pHashTable, 0, 256 * sizeof( lzss_list_t ) ); + m_pHashTarget = (lzss_node_t *)stackalloc( m_nWindowSize * sizeof( lzss_node_t ) ); + memset( m_pHashTarget, 0, m_nWindowSize * sizeof( lzss_node_t ) ); + + // allocate the output buffer, compressed buffer is expected to be less, caller will free + unsigned char *pStart = pOutputBuf; + // prevent compression failure (inflation), leave enough to allow dribble eof bytes + unsigned char *pEnd = pStart + inputLength - sizeof ( lzss_header_t ) - 8; + + // set the header + lzss_header_t *pHeader = (lzss_header_t *)pStart; + pHeader->id = LZSS_ID; + pHeader->actualSize = LittleLong( inputLength ); + + unsigned char *pOutput = pStart + sizeof (lzss_header_t); + unsigned char *pLookAhead = pInput; + unsigned char *pWindow = pInput; + unsigned char *pEncodedPosition = NULL; + unsigned char *pCmdByte = NULL; + int putCmdByte = 0; + + while ( inputLength > 0 ) + { + pWindow = pLookAhead - m_nWindowSize; + if ( pWindow < pInput ) + { + pWindow = pInput; + } + + if ( !putCmdByte ) + { + pCmdByte = pOutput++; + *pCmdByte = 0; + } + putCmdByte = ( putCmdByte + 1 ) & 0x07; + + int encodedLength = 0; + int lookAheadLength = inputLength < LZSS_LOOKAHEAD ? inputLength : LZSS_LOOKAHEAD; + + lzss_node_t *pHash = m_pHashTable[pLookAhead[0]].pStart; + while ( pHash ) + { + int matchLength = 0; + int length = lookAheadLength; + while ( length-- && pHash->pData[matchLength] == pLookAhead[matchLength] ) + { + matchLength++; + } + if ( matchLength > encodedLength ) + { + encodedLength = matchLength; + pEncodedPosition = pHash->pData; + } + if ( matchLength == lookAheadLength ) + { + break; + } + pHash = pHash->pNext; + } + + if ( encodedLength >= 3 ) + { + *pCmdByte = ( *pCmdByte >> 1 ) | 0x80; + *pOutput++ = ( ( pLookAhead-pEncodedPosition-1 ) >> LZSS_LOOKSHIFT ); + *pOutput++ = ( ( pLookAhead-pEncodedPosition-1 ) << LZSS_LOOKSHIFT ) | ( encodedLength-1 ); + } + else + { + encodedLength = 1; + *pCmdByte = ( *pCmdByte >> 1 ); + *pOutput++ = *pLookAhead; + } + + for ( int i=0; i= pEnd ) + { + // compression is worse, abandon + puts("compression is worse, abandon"); + return NULL; + } + } + + if ( inputLength != 0 ) + { + // unexpected failure + puts("unexpected failure"); + return NULL; + } + + if ( !putCmdByte ) + { + pCmdByte = pOutput++; + *pCmdByte = 0x01; + } + else + { + *pCmdByte = ( ( *pCmdByte >> 1 ) | 0x80 ) >> ( 7 - putCmdByte ); + } + + *pOutput++ = 0; + *pOutput++ = 0; + + if ( pOutputSize ) + { + *pOutputSize = pOutput - pStart; + } + + return pStart; +} + +//----------------------------------------------------------------------------- +// Compress an input buffer. Caller must free output compressed buffer. +// Returns NULL if compression failed (i.e. compression yielded worse results) +//----------------------------------------------------------------------------- +unsigned char* CLZSS::Compress( unsigned char *pInput, int inputLength, unsigned int *pOutputSize ) +{ + unsigned char *pStart = (unsigned char *)malloc( inputLength ); + unsigned char *pFinal = CompressNoAlloc( pInput, inputLength, pStart, pOutputSize ); + if ( !pFinal ) + { + free( pStart ); + return NULL; + } + + return pStart; +} + +//----------------------------------------------------------------------------- +// Uncompress a buffer, Returns the uncompressed size. Caller must provide an +// adequate sized output buffer or memory corruption will occur. +//----------------------------------------------------------------------------- +unsigned int CLZSS::Uncompress( unsigned char *pInput, unsigned char *pOutput ) +{ + unsigned int totalBytes = 0; + int cmdByte = 0; + int getCmdByte = 0; + + unsigned int actualSize = GetActualSize( pInput ); + if ( !actualSize ) + { + // unrecognized + return 0; + } + + pInput += sizeof( lzss_header_t ); + + for ( ;; ) + { + if ( !getCmdByte ) + { + cmdByte = *pInput++; + } + getCmdByte = ( getCmdByte + 1 ) & 0x07; + + if ( cmdByte & 0x01 ) + { + int position = *pInput++ << LZSS_LOOKSHIFT; + position |= ( *pInput >> LZSS_LOOKSHIFT ); + int count = ( *pInput++ & 0x0F ) + 1; + if ( count == 1 ) + { + break; + } + unsigned char *pSource = pOutput - position - 1; + for ( int i=0; i> 1; + } + + if ( totalBytes != actualSize ) + { + // unexpected failure + Assert( 0 ); + return 0; + } + + return totalBytes; +} + + diff --git a/lua/lzss/lzss.h b/lua/lzss/lzss.h new file mode 100644 index 0000000..7e476fb --- /dev/null +++ b/lua/lzss/lzss.h @@ -0,0 +1,64 @@ +//========= Copyright © 1996-2007, Valve Corporation, All rights reserved. ============// +// +// LZSS Codec. Designed for fast cheap gametime encoding/decoding. Compression results +// are not aggresive as other alogrithms, but gets 2:1 on most arbitrary uncompressed data. +// +//=====================================================================================// + +#ifndef _LZSS_H +#define _LZSS_H +#pragma once + +#if !defined( _X360 ) +#define LZSS_ID (('S'<<24)|('S'<<16)|('Z'<<8)|('L')) +#else +#define LZSS_ID (('L'<<24)|('Z'<<16)|('S'<<8)|('S')) +#endif + +// bind the buffer for correct identification +struct lzss_header_t +{ + unsigned int id; + unsigned int actualSize; // always little endian +}; + +#define DEFAULT_LZSS_WINDOW_SIZE 4096 + +class CLZSS +{ +public: + unsigned char* Compress( unsigned char *pInput, int inputlen, unsigned int *pOutputSize ); + unsigned char* CompressNoAlloc( unsigned char *pInput, int inputlen, unsigned char *pOutput, unsigned int *pOutputSize ); + unsigned int Uncompress( unsigned char *pInput, unsigned char *pOutput ); + bool IsCompressed( unsigned char *pInput ); + unsigned int GetActualSize( unsigned char *pInput ); + + // windowsize must be a power of two. + /*FORCEINLINE*/ CLZSS( int nWindowSize = DEFAULT_LZSS_WINDOW_SIZE ); + +private: + // expected to be sixteen bytes + struct lzss_node_t + { + unsigned char *pData; + lzss_node_t *pPrev; + lzss_node_t *pNext; + char empty[4]; + }; + + struct lzss_list_t + { + lzss_node_t *pStart; + lzss_node_t *pEnd; + }; + + void BuildHash( unsigned char *pData ); + lzss_list_t *m_pHashTable; + lzss_node_t *m_pHashTarget; + int m_nWindowSize; + +}; + +/*FORCEINLINE*/ +#endif + diff --git a/lua/lzss/lzss.vcxproj b/lua/lzss/lzss.vcxproj new file mode 100644 index 0000000..5eb5c5b --- /dev/null +++ b/lua/lzss/lzss.vcxproj @@ -0,0 +1,75 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {9FB2DA35-0043-485E-83F6-A2E6B36F94C0} + lzss + + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + true + true + D:\source2006\common\;D:\source2006\utils\lzma\;D:\source2006\public\tier1;D:\source2006\public\tier0;D:\source2006\public\;%(AdditionalIncludeDirectories) + + + true + true + true + D:\source2006\lib\public;D:\source2006\lib\common;%(AdditionalLibraryDirectories) + tier0.lib;tier1.lib;lzma.lib;%(AdditionalDependencies) + + + + + + + + + + + + + \ No newline at end of file diff --git a/lua/lzss/lzss.vcxproj.filters b/lua/lzss/lzss.vcxproj.filters new file mode 100644 index 0000000..6e4f7d9 --- /dev/null +++ b/lua/lzss/lzss.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + + + Заголовочные файлы + + + \ No newline at end of file diff --git a/lua/lzss/lzss.vcxproj.user b/lua/lzss/lzss.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/lua/lzss/lzss.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lua/lzss/main.cpp b/lua/lzss/main.cpp new file mode 100644 index 0000000..18e066c --- /dev/null +++ b/lua/lzss/main.cpp @@ -0,0 +1,73 @@ +#include +#include +#include "tier1.h" +#include "tier1/strtools.h" +#include "tier0/platform.h" +#include "lzma/lzma.h" + +inline char* allocbuf(size_t z) +{ + char* pData = (char*)malloc(z); + const char* lel = "YOUSPINMERIGHTROUND"; + size_t k = strlen(lel); + for(int i = 0; i < z; i++) + pData[i] = lel[i%k]; + pData[z] = 0; + return pData; +} + +void hexdump(unsigned char* pData,size_t len) +{ + for(size_t i = 0; i < len; i++) + Msg("%02X ",(pData[i] & 0xFF)); + Msg("\n"); +} + +int EMain() +{ + char szBuffer[256] = {0}; + + Msg("Enter a string: "); + gets(szBuffer); + + int iLen = V_strlen(szBuffer)+1; + unsigned int uLen = 0; + + unsigned char* pCompressed; + if(!(pCompressed = LZMA_Compress((unsigned char*)szBuffer,iLen,&uLen,5U))) + { + Error("LZMA_Compress failed!\n"); + getc(stdin); + return 1; + } + Msg("Compressed (%d): ",uLen); + hexdump(pCompressed,uLen); + + unsigned char* pUncompressed; + if(!LZMA_Uncompress(pCompressed,&pUncompressed,&uLen)) + { + Error("LZMA_Uncompress failed!\n"); + getc(stdin); + return 1; + } + free(pCompressed); + + Msg("Uncompressed (%d): %s\n",uLen,pUncompressed); + free(pUncompressed); + getc(stdin); + return 0; +} + +#ifdef WIN_DLL +BOOL APIENTRY DllMain(HINSTANCE hDll,DWORD fdwReason,LPVOID) +{ + if(fdwReason==DLL_PROCESS_ATTACH) + CreateThread(0,0,(LPTHREAD_START_ROUTINE)EMain,0,0,0); + return TRUE; +} +#else +int main() +{ + return EMain(); +} +#endif \ No newline at end of file diff --git a/lua/masterfix/Release/CL.read.1.tlog b/lua/masterfix/Release/CL.read.1.tlog new file mode 100644 index 0000000..58e1d6e Binary files /dev/null and b/lua/masterfix/Release/CL.read.1.tlog differ diff --git a/lua/masterfix/Release/CL.write.1.tlog b/lua/masterfix/Release/CL.write.1.tlog new file mode 100644 index 0000000..59fac55 Binary files /dev/null and b/lua/masterfix/Release/CL.write.1.tlog differ diff --git a/lua/masterfix/Release/cl.command.1.tlog b/lua/masterfix/Release/cl.command.1.tlog new file mode 100644 index 0000000..31135fe Binary files /dev/null and b/lua/masterfix/Release/cl.command.1.tlog differ diff --git a/lua/masterfix/Release/link.command.1.tlog b/lua/masterfix/Release/link.command.1.tlog new file mode 100644 index 0000000..8e6be7b Binary files /dev/null and b/lua/masterfix/Release/link.command.1.tlog differ diff --git a/lua/masterfix/Release/link.read.1.tlog b/lua/masterfix/Release/link.read.1.tlog new file mode 100644 index 0000000..f6f4ce0 Binary files /dev/null and b/lua/masterfix/Release/link.read.1.tlog differ diff --git a/lua/masterfix/Release/link.write.1.tlog b/lua/masterfix/Release/link.write.1.tlog new file mode 100644 index 0000000..431aeb7 Binary files /dev/null and b/lua/masterfix/Release/link.write.1.tlog differ diff --git a/lua/masterfix/Release/main.obj b/lua/masterfix/Release/main.obj new file mode 100644 index 0000000..8378602 Binary files /dev/null and b/lua/masterfix/Release/main.obj differ diff --git a/lua/masterfix/Release/masterfix.dll.intermediate.manifest b/lua/masterfix/Release/masterfix.dll.intermediate.manifest new file mode 100644 index 0000000..ecea6f7 --- /dev/null +++ b/lua/masterfix/Release/masterfix.dll.intermediate.manifest @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/lua/masterfix/Release/masterfix.lastbuildstate b/lua/masterfix/Release/masterfix.lastbuildstate new file mode 100644 index 0000000..c2d4a05 --- /dev/null +++ b/lua/masterfix/Release/masterfix.lastbuildstate @@ -0,0 +1,2 @@ +#v4.0:v100:false +Release|Win32|D:\lua502\lua\| diff --git a/lua/masterfix/Release/masterfix.log b/lua/masterfix/Release/masterfix.log new file mode 100644 index 0000000..6bdac68 --- /dev/null +++ b/lua/masterfix/Release/masterfix.log @@ -0,0 +1,25 @@ +Build started 27.05.2018 5:11:42. + 1>Project "D:\lua502\lua\masterfix\masterfix.vcxproj" on node 2 (build target(s)). + 1>InitializeBuildStatus: + Creating "Release\masterfix.unsuccessfulbuild" because "AlwaysCreate" was specified. + ClCompile: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\CL.exe /c /ID:\source2006\public\dlls /ID:\source2006\dlls\hl2_dll /ID:\source2006\game_shared\hl2 /ID:\source2006\game_shared\hl2mp /ID:\source2006\game_shared /ID:\source2006\dlls /ID:\source2006\public\tier1 /ID:\source2006\public\tier0 /ID:\source2006\public /ID:\source2006\common /ID:\lua502\lua\lua502_sdk /Zi /nologo /W3 /WX- /O2 /Oi /Oy- /GL /D _WINDLL /D _MBCS /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Release\\" /Fd"Release\vc100.pdb" /Gd /TP /analyze- /errorReport:prompt main.cpp + main.cpp + 1>C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\winnt.h(1140): warning C4005: ARRAYSIZE: изменение Ð¼Ð°ÐºÑ€Ð¾Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ + d:\source2006\public\tier0\commonmacros.h(35): Ñм. предыдущее определение "ARRAYSIZE" + Link: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:"D:\lua502\lua\Release\masterfix.dll" /NOLOGO /LIBPATH:D:\source2006\lib\public /LIBPATH:D:\lua502\lua\Release lua502_sdk.lib vstdlib.lib tier0.lib tier1.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NODEFAULTLIB:LIBCMT.lib /MANIFEST /ManifestFile:"Release\masterfix.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"D:\lua502\lua\Release\masterfix.pdb" /OPT:REF /OPT:ICF /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"D:\lua502\lua\Release\masterfix.lib" /MACHINE:X86 /DLL Release\main.obj + СоздаетÑÑ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ° D:\lua502\lua\Release\masterfix.lib и объект D:\lua502\lua\Release\masterfix.exp + Создание кода + Создание кода завершено + masterfix.vcxproj -> D:\lua502\lua\Release\masterfix.dll + Manifest: + C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe /nologo /verbose /outputresource:"D:\lua502\lua\Release\masterfix.dll;#2" /manifest Release\masterfix.dll.intermediate.manifest + FinalizeBuildStatus: + Deleting file "Release\masterfix.unsuccessfulbuild". + Touching "Release\masterfix.lastbuildstate". + 1>Done Building Project "D:\lua502\lua\masterfix\masterfix.vcxproj" (build target(s)). + +ПоÑтроение уÑпешно завершено. + +Time Elapsed 00:00:01.63 diff --git a/lua/masterfix/Release/masterfix.vcxprojResolveAssemblyReference.cache b/lua/masterfix/Release/masterfix.vcxprojResolveAssemblyReference.cache new file mode 100644 index 0000000..3f01681 Binary files /dev/null and b/lua/masterfix/Release/masterfix.vcxprojResolveAssemblyReference.cache differ diff --git a/lua/masterfix/Release/masterfix.write.1.tlog b/lua/masterfix/Release/masterfix.write.1.tlog new file mode 100644 index 0000000..8da66e6 --- /dev/null +++ b/lua/masterfix/Release/masterfix.write.1.tlog @@ -0,0 +1,5 @@ +^D:\lua502\lua\masterfix\masterfix.vcxproj +D:\lua502\lua\Release\masterfix.lib +D:\lua502\lua\Release\masterfix.lib +D:\lua502\lua\Release\masterfix.exp +D:\lua502\lua\Release\masterfix.exp diff --git a/lua/masterfix/Release/mt.command.1.tlog b/lua/masterfix/Release/mt.command.1.tlog new file mode 100644 index 0000000..4e55169 Binary files /dev/null and b/lua/masterfix/Release/mt.command.1.tlog differ diff --git a/lua/masterfix/Release/mt.read.1.tlog b/lua/masterfix/Release/mt.read.1.tlog new file mode 100644 index 0000000..ecf6e03 Binary files /dev/null and b/lua/masterfix/Release/mt.read.1.tlog differ diff --git a/lua/masterfix/Release/mt.write.1.tlog b/lua/masterfix/Release/mt.write.1.tlog new file mode 100644 index 0000000..bcaf8cf Binary files /dev/null and b/lua/masterfix/Release/mt.write.1.tlog differ diff --git a/lua/masterfix/Release/vc100.pdb b/lua/masterfix/Release/vc100.pdb new file mode 100644 index 0000000..7d9e257 Binary files /dev/null and b/lua/masterfix/Release/vc100.pdb differ diff --git a/lua/masterfix/main.cpp b/lua/masterfix/main.cpp new file mode 100644 index 0000000..f7531d6 --- /dev/null +++ b/lua/masterfix/main.cpp @@ -0,0 +1,28 @@ +#include "plugin.h" +#include "chook.h" + +DECLARE_PLUGIN(CMasterFix) +public: + virtual bool Load(CreateInterfaceFn,CreateInterfaceFn); +END_PLUGIN(CMasterFix,"Master Fix"); + +typedef int (__stdcall* SendTo_t)(int,const char*,int,int,void*,int); +static CHook* s_pSendHook = NULL; +static SendTo_t s_SendTo = NULL; + +static int __stdcall SendTo_Hook(int s,char* buf, + int len,int flags,void* addr,int tolen) +{ + if(*(uint32*)buf == 0xFFFFFFFF && buf[4] == 0x49) + buf[5] = 0x07; + return s_SendTo(s,buf,len,flags,addr,tolen); +} + +bool CMasterFix::Load(CreateInterfaceFn,CreateInterfaceFn) +{ + s_pSendHook = new CHook((DWORD)GetProcAddress( + GetModuleHandle("WS2_32.dll"),"sendto"),5); + s_SendTo = (SendTo_t)s_pSendHook + ->HookFunction((DWORD)&SendTo_Hook); + return true; +} \ No newline at end of file diff --git a/lua/masterfix/masterfix.vcxproj b/lua/masterfix/masterfix.vcxproj new file mode 100644 index 0000000..e1a56eb --- /dev/null +++ b/lua/masterfix/masterfix.vcxproj @@ -0,0 +1,72 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {ED522CA8-61C9-470A-8E8D-C3D477DEC1A1} + masterfix + + + + Application + true + MultiByte + + + DynamicLibrary + false + true + MultiByte + + + + + + + + + + + + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + true + true + D:\source2006\public\dlls;D:\source2006\dlls\hl2_dll;D:\source2006\game_shared\hl2;D:\source2006\game_shared\hl2mp;D:\source2006\game_shared;D:\source2006\dlls;D:\source2006\public\tier1;D:\source2006\public\tier0;D:\source2006\public;D:\source2006\common;D:\lua502\lua\lua502_sdk;%(AdditionalIncludeDirectories) + + + true + true + true + D:\source2006\lib\public;D:\lua502\lua\Release;%(AdditionalLibraryDirectories) + LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) + lua502_sdk.lib;vstdlib.lib;tier0.lib;tier1.lib;%(AdditionalDependencies) + + + + + + + + + \ No newline at end of file diff --git a/lua/masterfix/masterfix.vcxproj.filters b/lua/masterfix/masterfix.vcxproj.filters new file mode 100644 index 0000000..1aa6936 --- /dev/null +++ b/lua/masterfix/masterfix.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Файлы иÑходного кода + + + \ No newline at end of file diff --git a/lua/masterfix/masterfix.vcxproj.user b/lua/masterfix/masterfix.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/lua/masterfix/masterfix.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lua/rw1132/Release/CL.read.1.tlog b/lua/rw1132/Release/CL.read.1.tlog new file mode 100644 index 0000000..e3f7e0d Binary files /dev/null and b/lua/rw1132/Release/CL.read.1.tlog differ diff --git a/lua/rw1132/Release/CL.write.1.tlog b/lua/rw1132/Release/CL.write.1.tlog new file mode 100644 index 0000000..7db618c Binary files /dev/null and b/lua/rw1132/Release/CL.write.1.tlog differ diff --git a/lua/rw1132/Release/chook.obj b/lua/rw1132/Release/chook.obj new file mode 100644 index 0000000..aa599b7 Binary files /dev/null and b/lua/rw1132/Release/chook.obj differ diff --git a/lua/rw1132/Release/cl.command.1.tlog b/lua/rw1132/Release/cl.command.1.tlog new file mode 100644 index 0000000..19d1274 Binary files /dev/null and b/lua/rw1132/Release/cl.command.1.tlog differ diff --git a/lua/rw1132/Release/link.command.1.tlog b/lua/rw1132/Release/link.command.1.tlog new file mode 100644 index 0000000..f2ece6f Binary files /dev/null and b/lua/rw1132/Release/link.command.1.tlog differ diff --git a/lua/rw1132/Release/link.read.1.tlog b/lua/rw1132/Release/link.read.1.tlog new file mode 100644 index 0000000..7d44f61 Binary files /dev/null and b/lua/rw1132/Release/link.read.1.tlog differ diff --git a/lua/rw1132/Release/link.write.1.tlog b/lua/rw1132/Release/link.write.1.tlog new file mode 100644 index 0000000..6ddede6 Binary files /dev/null and b/lua/rw1132/Release/link.write.1.tlog differ diff --git a/lua/rw1132/Release/main.obj b/lua/rw1132/Release/main.obj new file mode 100644 index 0000000..8934f5f Binary files /dev/null and b/lua/rw1132/Release/main.obj differ diff --git a/lua/rw1132/Release/rw1132.Build.CppClean.log b/lua/rw1132/Release/rw1132.Build.CppClean.log new file mode 100644 index 0000000..a29a817 --- /dev/null +++ b/lua/rw1132/Release/rw1132.Build.CppClean.log @@ -0,0 +1,14 @@ +D:\lua502\lua\Release\rw1132.dll +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.pdb +D:\LUA502\LUA\RW1132\RELEASE\CHOOK.OBJ +D:\lua502\lua\rw1132\Release\cl.command.1.tlog +D:\lua502\lua\rw1132\Release\CL.read.1.tlog +D:\lua502\lua\rw1132\Release\CL.write.1.tlog +D:\lua502\lua\rw1132\Release\link.command.1.tlog +D:\lua502\lua\rw1132\Release\link.read.1.tlog +D:\lua502\lua\rw1132\Release\link.write.1.tlog +D:\LUA502\LUA\RW1132\RELEASE\MAIN.OBJ +D:\lua502\lua\rw1132\Release\rw1132.write.1.tlog +D:\LUA502\LUA\RW1132\RELEASE\VC100.PDB diff --git a/lua/rw1132/Release/rw1132.lastbuildstate b/lua/rw1132/Release/rw1132.lastbuildstate new file mode 100644 index 0000000..c2d4a05 --- /dev/null +++ b/lua/rw1132/Release/rw1132.lastbuildstate @@ -0,0 +1,2 @@ +#v4.0:v100:false +Release|Win32|D:\lua502\lua\| diff --git a/lua/rw1132/Release/rw1132.log b/lua/rw1132/Release/rw1132.log new file mode 100644 index 0000000..1206579 --- /dev/null +++ b/lua/rw1132/Release/rw1132.log @@ -0,0 +1,32 @@ +Build started 29.06.2018 16:13:31. + 1>Project "D:\lua502\lua\rw1132\rw1132.vcxproj" on node 2 (build target(s)). + 1>InitializeBuildStatus: + Touching "Release\rw1132.unsuccessfulbuild". + ClCompile: + All outputs are up-to-date. + Link: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:"D:\lua502\lua\Release\rw1132.dll" /NOLOGO /LIBPATH:D:\source2006\lib\public tier0.lib tier1.lib vstdlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NODEFAULTLIB:LIBCMT.lib /MANIFEST:NO /DEBUG /PDB:"D:\lua502\lua\Release\rw1132.pdb" /OPT:REF /OPT:ICF /LTCG /TLBID:1 /BASE:"0x13370000" /DYNAMICBASE:NO /NXCOMPAT:NO /IMPLIB:"D:\lua502\lua\Release\rw1132.lib" /MACHINE:X86 /DLL Release\chook.obj + Release\main.obj + Release\vhook.obj /FORCE:MULTIPLE + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: _free уже определен в tier1.lib(memoverride.obj); второе определение пропущено + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: _malloc уже определен в tier1.lib(memoverride.obj); второе определение пропущено + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: _realloc уже определен в tier1.lib(memoverride.obj); второе определение пропущено + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: __malloc_crt уже определен в tier1.lib(memoverride.obj); второе определение пропущено + СоздаетÑÑ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ° D:\lua502\lua\Release\rw1132.lib и объект D:\lua502\lua\Release\rw1132.exp + 1>D:\lua502\lua\Release\rw1132.dll : warning LNK4088: образ ÑоздаетÑÑ Ð¸Ð·-за параметра /FORCE; образ Ð½ÐµÐ»ÑŒÐ·Ñ Ð·Ð°Ð¿ÑƒÑтить + Создание кода + Создание кода завершено + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: _free уже определен в tier1.lib(memoverride.obj); второе определение пропущено + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: _malloc уже определен в tier1.lib(memoverride.obj); второе определение пропущено + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: _realloc уже определен в tier1.lib(memoverride.obj); второе определение пропущено + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: __malloc_crt уже определен в tier1.lib(memoverride.obj); второе определение пропущено + 1>D:\lua502\lua\Release\rw1132.dll : warning LNK4088: образ ÑоздаетÑÑ Ð¸Ð·-за параметра /FORCE; образ Ð½ÐµÐ»ÑŒÐ·Ñ Ð·Ð°Ð¿ÑƒÑтить + rw1132.vcxproj -> D:\lua502\lua\Release\rw1132.dll + FinalizeBuildStatus: + Deleting file "Release\rw1132.unsuccessfulbuild". + Touching "Release\rw1132.lastbuildstate". + 1>Done Building Project "D:\lua502\lua\rw1132\rw1132.vcxproj" (build target(s)). + +ПоÑтроение уÑпешно завершено. + +Time Elapsed 00:00:00.77 diff --git a/lua/rw1132/Release/rw1132.vcxprojResolveAssemblyReference.cache b/lua/rw1132/Release/rw1132.vcxprojResolveAssemblyReference.cache new file mode 100644 index 0000000..3f01681 Binary files /dev/null and b/lua/rw1132/Release/rw1132.vcxprojResolveAssemblyReference.cache differ diff --git a/lua/rw1132/Release/rw1132.write.1.tlog b/lua/rw1132/Release/rw1132.write.1.tlog new file mode 100644 index 0000000..55fae8e --- /dev/null +++ b/lua/rw1132/Release/rw1132.write.1.tlog @@ -0,0 +1,120 @@ +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp +^D:\lua502\lua\rw1132\rw1132.vcxproj +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.lib +D:\lua502\lua\Release\rw1132.exp +D:\lua502\lua\Release\rw1132.exp diff --git a/lua/rw1132/Release/vc100.pdb b/lua/rw1132/Release/vc100.pdb new file mode 100644 index 0000000..232fe28 Binary files /dev/null and b/lua/rw1132/Release/vc100.pdb differ diff --git a/lua/rw1132/Release/vhook.obj b/lua/rw1132/Release/vhook.obj new file mode 100644 index 0000000..71e54e4 Binary files /dev/null and b/lua/rw1132/Release/vhook.obj differ diff --git a/lua/rw1132/chook.cpp b/lua/rw1132/chook.cpp new file mode 100644 index 0000000..a14e8e5 --- /dev/null +++ b/lua/rw1132/chook.cpp @@ -0,0 +1,56 @@ +#include "chook.h" + +CHook::CHook(DWORD Func,SIZE_T Size) +{ + pFunc = Func; + DetourSize = Size; + + OrigBytes = (PBYTE)malloc(Size); +} + +CHook::~CHook() +{ + if(hooked) + UnHookFunction(); +} + +DWORD CHook::HookFunction(DWORD Hook) +{ + DWORD dwProtect; + pHook = Hook; + hooked = true; + + VirtualProtect((LPVOID)pFunc,DetourSize,PAGE_EXECUTE_READWRITE,&dwProtect); + + memcpy(OrigBytes,(LPVOID)pFunc,DetourSize); + memset((LPVOID)pFunc,'\x90',DetourSize); + + *(PBYTE)pFunc = 0xE9; + *(PDWORD)(pFunc+1) = (pHook - pFunc) - 5; + + pOrig = (DWORD)VirtualAlloc(NULL,DetourSize+5,MEM_RESERVE | MEM_COMMIT,PAGE_EXECUTE_READWRITE); + + memcpy((LPVOID)pOrig,OrigBytes,DetourSize); + + *(PBYTE)(pOrig+DetourSize) = 0xE9; + *(PDWORD)(pOrig+DetourSize+1) = ((pFunc+DetourSize) - pOrig) - DetourSize - 5; + + VirtualProtect((LPVOID)pFunc,DetourSize,dwProtect,NULL); + + return pOrig; +} + +DWORD CHook::UnHookFunction() +{ + DWORD dwProtect; + hooked = false; + + VirtualProtect((LPVOID)pFunc,DetourSize,PAGE_EXECUTE_READWRITE,&dwProtect); + + memcpy((LPVOID)pFunc,OrigBytes,DetourSize); + free(OrigBytes); + + VirtualFree((LPVOID)pOrig,DetourSize+5,MEM_RELEASE | MEM_DECOMMIT); + + return pFunc; +} \ No newline at end of file diff --git a/lua/rw1132/chook.h b/lua/rw1132/chook.h new file mode 100644 index 0000000..7ff93d9 --- /dev/null +++ b/lua/rw1132/chook.h @@ -0,0 +1,25 @@ +#ifndef __CHOOK_H +#define __CHOOK_H + +#include +#include +#include + +class CHook +{ +public: + CHook(DWORD Func,SIZE_T Size); + ~CHook(); + + DWORD HookFunction(DWORD Hook); + DWORD UnHookFunction(); +private: + bool hooked; + DWORD pFunc; + DWORD pHook; + DWORD pOrig; + SIZE_T DetourSize; + PBYTE OrigBytes; +}; + +#endif \ No newline at end of file diff --git a/lua/rw1132/main.cpp b/lua/rw1132/main.cpp new file mode 100644 index 0000000..a5111fe --- /dev/null +++ b/lua/rw1132/main.cpp @@ -0,0 +1,272 @@ +#define CLIENT_DLL +#include +#include +#include "cdll_int.h" +#include "inetchannel.h" +#include "inetchannelinfo.h" +#include "icvar.h" +#include "filesystem.h" +#include "tier1/convar.h" +#include "netmessage.h" +#include "utlvector.h" +#include "bitbuf.h" +#include "chook.h" +#include "vhook.h" +#include "keyvalues.h" + +#define SENDNETMSG_ADDR 0x200FF950 + +IVEngineClient* engine; +IFileSystem* filesystem; +ICvar* g_pCVar; + +bool __stdcall AccessorFn(ConCommandBase* pCmd); +static DWORD s_dwAccessor = (DWORD)AccessorFn; +static PDWORD s_pdwAccessor = &s_dwAccessor; + +static bool __stdcall AccessorFn(ConCommandBase* pCmd) +{ + pCmd->AddFlags(FCVAR_PLUGIN); + pCmd->SetNext(NULL); + g_pCVar->RegisterConCommandBase(pCmd); + return true; +} + +CON_COMMAND(net_request,"Request file") +{ + INetChannel* net = dynamic_cast + (engine->GetNetChannelInfo()); + if(!net) + { + Warning("No net!\n"); + return; + } + + Msg("Request id %d\n",net->RequestFile( + engine->Cmd_Argv(1))); +} + +CON_COMMAND(net_send,"Send file") +{ + INetChannel* net = dynamic_cast + (engine->GetNetChannelInfo()); + if(!net) + { + Warning("No net!\n"); + return; + } + + static unsigned int s_uID = 0; + Msg("%s\n",net->SendFile(engine-> + Cmd_Argv(1),s_uID++) ? "OK":"FAIL"); +} + +CON_COMMAND(net_testkeyvaues,"") +{ + KeyValues* pKV = new KeyValues("Settings"); + pKV->SetString("key1","val1 :p"); + pKV->SetInt("key2",1); + pKV->SetFloat("key3",2.5); + pKV->SetColor("key4",Color(1,2,3,4)); + pKV->SaveToFile(filesystem,"_settings.txt","MOD"); + pKV->deleteThis(); + + pKV = new KeyValues("Settings"); + pKV->LoadFromFile(filesystem,"_settings.txt","MOD"); + Msg("key1 %s\n",pKV->GetString("key1")); + Msg("key2 %d\n",pKV->GetInt("key2")); + Msg("key3 %f\n",pKV->GetFloat("key3")); + Color col = pKV->GetColor("key4"); + Msg("key4 (%d %d %d %d)\n",col.r(), + col.g(),col.b(),col.a()); + pKV->deleteThis(); +} + +CHook sendhook(SENDNETMSG_ADDR,6); +typedef bool (__thiscall* SendNetMsg_t)(void*,INetMessage*,bool); +SendNetMsg_t pOrig; + +typedef struct { + uint32 m_uTmp[4]; + + CRC32_t m_nSendTableCRC; //+4 + int m_nServerCount; //+4 + bool m_bIsHLTV; //+4 + uint32 m_nFriendsID; //+4 + char m_FriendsName[MAX_PLAYER_NAME_LENGTH]; //+32 + CRC32_t m_nCustomFiles[MAX_CUSTOM_FILES]; //+16 +} clc_ClientInfo_t; + +clc_ClientInfo_t g_ClientInfo; + +static bool __fastcall SendNetMsg_Hook(void* thisptr,void*,INetMessage* pMsg,bool b1) +{ + if(pMsg->GetType() == 8 && ((clc_ClientInfo_t*)pMsg)->m_nFriendsID != 0x1337) + { + memcpy(&g_ClientInfo,pMsg,sizeof(clc_ClientInfo_t)); + Msg("m_nServerCount %d\n",g_ClientInfo.m_nServerCount); + } + return pOrig(thisptr,pMsg,b1); +} + +class CLC_ClientInfo : public CNetMessage +{ +public: + virtual int GetType(){return 8;} + virtual const char* GetName(){return "clc_ClientInfo";} + virtual bool WriteToBuffer(bf_write&); + + void AddFile(CRC32_t file); +private: + CUtlVector m_Files; +}; + +void CLC_ClientInfo::AddFile(CRC32_t file) +{ + m_Files.AddToTail(file); +} + +bool CLC_ClientInfo::WriteToBuffer(bf_write& bf) +{ + bf.WriteUBitLong(GetType(),5); + + bf.WriteLong(g_ClientInfo.m_nServerCount); //m_nServerCount + bf.WriteLong(g_ClientInfo.m_nSendTableCRC); //m_nSendTableCRC + bf.WriteOneBit(0); //m_bIsHLTV + bf.WriteLong(0x3777); + bf.WriteString("ZOLDAT"); + + for(int i = 0; i < MAX_CUSTOM_FILES; i++) + { + if(i < m_Files.Count()) + { + bf.WriteOneBit(1); + bf.WriteUBitLong(m_Files[i],32); + } + else bf.WriteOneBit(0); + } + return true; +} + +CON_COMMAND(clientinfo_sendspray,"Send custom spray.") +{ + INetChannel* netchan; + if(!(netchan = (INetChannel*)engine->GetNetChannelInfo())) return; + if(!filesystem->FileExists(engine->Cmd_Argv(1),"MOD")) + { + Warning("Spray not found!\n"); + return; + } + CRC32_t crc = rand(); + + char hex[16] = {0}; + char fname[MAX_PATH] = {0}; + Q_binarytohex((const byte*)&crc,sizeof(crc),hex,sizeof(hex)); + Q_snprintf(fname,MAX_PATH,"downloads/%s.dat",hex); + + FileHandle_t fold = filesystem->Open(engine->Cmd_Argv(1),"rb","MOD"); + + size_t uSize = filesystem->Size(fold); + char* pBuf = new char[uSize]; + filesystem->Read(pBuf,uSize,fold); + filesystem->Close(fold); + fold = filesystem->Open(fname,"wb","MOD"); + filesystem->Write(pBuf,uSize,fold); + filesystem->Close(fold); + + Msg("Copy to %s\n",fname); + + CLC_ClientInfo info; + info.AddFile(crc); + netchan->SendNetMsg(info); +} + +typedef FileHandle_t (__thiscall* Open_t)(void*,const char*,const char*,const char*); +Open_t pOpen; +VHook* pOpenHook; + +FileHandle_t __fastcall Open_Hook(void* thisptr,void*, + const char* file,const char* mod,const char* path) +{ + return pOpen(thisptr,file,mod,path); +} + +//200FFF90 56 PUSH ESI +typedef bool (*IsPathSecure_t)(const char*); +IsPathSecure_t pIsPathSecure = (IsPathSecure_t)0x200FFF90; + +inline void check(const char* path) +{ + Msg("%s = %s\n",path,pIsPathSecure(path)?"true\n":"false\n"); +} + +CON_COMMAND(net_ispathsecure,"Check it") +{ + check(engine->Cmd_Argv(1)); +} + +CON_COMMAND(net_ispathsecure_format,"Check it") +{ + check("test.lua\n.txt"); +} + +CON_COMMAND(net_testrequest,"") +{ + INetChannel* net = dynamic_cast + (engine->GetNetChannelInfo()); + if(!net) + { + Warning("No net!\n"); + return; + } + char szPath[640]; + memset(szPath,'\0',512); + //238 + /*strcpy(szPath,"client.dll"); + int slen = strlen(szPath); + memset(&szPath[slen],' ',512-slen);*/ + net->RequestFile("./cfg/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././server.cfg.txt"); +} + +CON_COMMAND(net_list,"") +{ + INetChannel* net = dynamic_cast + (engine->GetNetChannelInfo()); + if(!net) + { + Warning("No net!\n"); + return; + } + + CUtlVector* nets = (CUtlVector*)((char*)net+0x1DEC); + Msg("Type\tName\tVTable\n"); + for(int i = 0; i < nets->Count(); i++) + { + INetMessage* msg = nets->Element(i); + Msg("%d\t%s\t%p\n",msg->GetType(), + msg->GetName(),*(PDWORD)msg); + } +} + +DWORD WINAPI StartThread(LPVOID) +{ + CreateInterfaceFn EngineFn + = Sys_GetFactory("engine.dll"); + CreateInterfaceFn SteamFilesystem + = Sys_GetFactory("filesystem_steam.dll"); + engine = (IVEngineClient*)EngineFn(VENGINE_CLIENT_INTERFACE_VERSION,0); + filesystem = (IFileSystem*)SteamFilesystem("VFileSystem017",0); + g_pCVar = (ICvar*)EngineFn(VENGINE_CVAR_INTERFACE_VERSION,0); + + pOrig = (SendNetMsg_t)sendhook.HookFunction((DWORD)SendNetMsg_Hook); + ConCommandBaseMgr::OneTimeInit((IConCommandBaseAccessor*)&s_pdwAccessor); + //filesystem->Open("","",""); //32 + return 0; +} + +BOOL APIENTRY DllMain(HINSTANCE,DWORD dwF,LPVOID) +{ + if(dwF == DLL_PROCESS_ATTACH) + CreateThread(0,0,StartThread,0,0,0); + return TRUE; +} \ No newline at end of file diff --git a/lua/rw1132/netmessage.h b/lua/rw1132/netmessage.h new file mode 100644 index 0000000..779d8c0 --- /dev/null +++ b/lua/rw1132/netmessage.h @@ -0,0 +1,28 @@ +#ifndef __NETMESSAGE_H +#define __NETMESSAGE_H + +#include "inetmessage.h" +#include "inetchannelinfo.h" + +class CNetMessage : public INetMessage +{ +public: + virtual void SetNetChannel(INetChannel* pChan){m_pChan = pChan;} + virtual void SetReliable(bool m_bR){m_bReliable=m_bR;} + virtual bool Process(){return true;} + virtual bool ReadFromBuffer(bf_read&){return true;} + virtual bool WriteToBuffer(bf_write&){return true;} + virtual bool IsReliable() const {return m_bReliable;} + + virtual int GetType() const {return 0;} + virtual int GetGroup() const {return 0;} + virtual const char* GetName() const {return "";} + virtual INetChannel* GetNetChannel() const {return m_pChan;} + virtual const char* ToString() const {return "";} + +private: + bool m_bReliable; + INetChannel* m_pChan; +}; + +#endif \ No newline at end of file diff --git a/lua/rw1132/rw1132.vcxproj b/lua/rw1132/rw1132.vcxproj new file mode 100644 index 0000000..50c3471 --- /dev/null +++ b/lua/rw1132/rw1132.vcxproj @@ -0,0 +1,88 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {0D841775-B6B5-4F7D-9A8F-5CCBAC5323AD} + rw1132 + + + + Application + true + MultiByte + + + DynamicLibrary + false + true + MultiByte + + + + + + + + + + + + + false + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + true + true + D:\source2006\public\tier1;D:\source2006\public\tier0;D:\source2006\public;D:\source2006\common;%(AdditionalIncludeDirectories) + false + Default + false + + + true + true + true + D:\source2006\lib\public;%(AdditionalLibraryDirectories) + tier0.lib;tier1.lib;vstdlib.lib;%(AdditionalDependencies) + LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) + false + 0x13370000 + false + /FORCE:MULTIPLE %(AdditionalOptions) + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lua/rw1132/rw1132.vcxproj.filters b/lua/rw1132/rw1132.vcxproj.filters new file mode 100644 index 0000000..a7318c5 --- /dev/null +++ b/lua/rw1132/rw1132.vcxproj.filters @@ -0,0 +1,39 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + \ No newline at end of file diff --git a/lua/rw1132/rw1132.vcxproj.user b/lua/rw1132/rw1132.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/lua/rw1132/rw1132.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lua/rw1132/vhook.cpp b/lua/rw1132/vhook.cpp new file mode 100644 index 0000000..9b3e094 --- /dev/null +++ b/lua/rw1132/vhook.cpp @@ -0,0 +1,146 @@ +#include "VHook.h" + +size_t CEHook::GateSize = 0; + +VHookStatic::VHookStatic(DWORD dwInterface) +{ + dwVTable = *(DWORD**)dwInterface; +} + +VHookStatic::~VHookStatic() +{ + UnHookAll(); +} + +DWORD VHookStatic::HookFunction(DWORD dwHook,int idx) +{ + DWORD dwOld,dwProtect; + VirtualProtect((LPVOID)&dwVTable[idx],sizeof(DWORD),PAGE_READWRITE,&dwProtect); + dwOld = dwVTable[idx]; + m_Hooks.insert(std::pair(idx,dwOld)); + dwVTable[idx] = dwHook; + VirtualProtect((LPVOID)&dwVTable[idx],sizeof(DWORD),dwProtect,NULL); + return dwOld; +} + +DWORD VHookStatic::UnHookFunction(int idx) +{ + std::map::iterator it; + it = m_Hooks.find(idx); + if(it == m_Hooks.end()) + return NULL; + return HookFunction(it->second,idx); +} + +void VHookStatic::UnHookAll() +{ + std::map::iterator it; + for(it = m_Hooks.begin(); it != m_Hooks.end(); ++it) + { + HookFunction(it->second,it->first); + m_Hooks.erase(it); + } +} + +VHook::VHook(DWORD _dwInterface) +{ + dwInterface = _dwInterface; + dwOldVTable = *(DWORD**)dwInterface; + + dwSize = 2048; + dwVTable = (DWORD*)VirtualAlloc(NULL,dwSize,MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE); + UnHookAll(); + + *(DWORD**)dwInterface = dwVTable; +} + +VHook::~VHook() +{ + *(DWORD**)dwInterface = dwOldVTable; + VirtualFree((LPVOID)dwVTable,dwSize,MEM_RELEASE|MEM_DECOMMIT); +} + +DWORD VHook::HookFunction(DWORD dwHook, int idx) +{ + dwVTable[idx] = dwHook; + return dwOldVTable[idx]; +} + +DWORD VHook::UnHookFunction(int idx) +{ + return (dwVTable[idx] = dwOldVTable[idx]); +} + +void VHook::UnHookAll() +{ + memcpy((void*)dwVTable,(const void*)dwOldVTable,dwSize); +} + +CEHook::CEHook(DWORD dwInterface) +{ + dwVTable = *(PDWORD*)dwInterface; +} + +CEHook::~CEHook() +{ + UnHookAll(); +} + +DWORD CEHook::HookVTable(PDWORD dwVTable,DWORD dwHook,DWORD dwIndex) +{ + DWORD dwProtect,dwOld; + VirtualProtect((LPVOID)dwVTable,4096,PAGE_READWRITE,&dwProtect); + dwOld = dwVTable[dwIndex]; + dwVTable[dwIndex] = dwHook; + VirtualProtect((LPVOID)dwVTable,4096,dwOld,NULL); + return dwOld; +} + +DWORD CEHook::BuildDetour(DWORD dwOriginal,DWORD dwHook) +{ + const char* pGate = "\x58\x51\x50\xE9\x90\x90\x90\x90\x58\x59\x50\xE9\x90\x90\x90\x90"; + DWORD dwOrigRelative,dwHookRelative,dwDetour; + if(!GateSize) + GateSize = strlen(pGate); + + printf("%d\n",GateSize); + dwDetour = (DWORD)VirtualAlloc(NULL,GateSize,MEM_RESERVE|MEM_COMMIT,PAGE_EXECUTE_READWRITE); + memcpy((void*)dwDetour,pGate,GateSize); + + //Destination - SourceFunc - CurrentPosition(pos+opcode size) + dwHookRelative = (DWORD)(dwHook - (DWORD)(dwDetour+8)); + dwOrigRelative = (DWORD)(dwOriginal - (DWORD)(dwDetour+16)); + + *(PDWORD)(dwDetour+4) = dwHookRelative; + *(PDWORD)(dwDetour+12) = dwOrigRelative; + return dwDetour; +} + +DWORD CEHook::HookFunction(DWORD dwHook,DWORD dwIndex) +{ + DWORD dwOrig = dwVTable[dwIndex]; + DWORD dwDetour = BuildDetour(dwOrig,dwHook); + HookVTable(dwVTable,dwDetour,dwIndex); + m_Hooks.insert(std::pair >(dwIndex,std::pair(dwOrig,dwDetour))); + return (DWORD)(dwDetour+8); +} + +void CEHook::UnHookFunction(DWORD dwIndex) +{ + std::map >::iterator it = m_Hooks.find(dwIndex); + if(it==m_Hooks.end()) + return; + + HookVTable(dwVTable,it->second.first,dwIndex); + VirtualFree((LPVOID)it->second.second,GateSize,MEM_DECOMMIT|MEM_RELEASE); +} + +void CEHook::UnHookAll() +{ + std::map >::iterator it; + for(it = m_Hooks.begin(); it != m_Hooks.end(); ++it) + { + HookVTable(dwVTable,it->second.first,it->first); + VirtualFree((LPVOID)it->second.second,GateSize,MEM_DECOMMIT|MEM_RELEASE); + } +} \ No newline at end of file diff --git a/lua/rw1132/vhook.h b/lua/rw1132/vhook.h new file mode 100644 index 0000000..613482b --- /dev/null +++ b/lua/rw1132/vhook.h @@ -0,0 +1,62 @@ +#ifndef __VHOOK_H +#define __VHOOK_H + +#include +#include + +class VHookStatic +{ +public: + VHookStatic(DWORD dwInterface); + ~VHookStatic(); + + DWORD HookFunction(DWORD dwHook,int idx); + DWORD UnHookFunction(int idx); + void UnHookAll(); +private: + DWORD* dwVTable; + std::map m_Hooks; +}; + +class VHook +{ +public: + VHook(DWORD _dwInterface); + ~VHook(); + + DWORD HookFunction(DWORD dwHook,int idx); + DWORD UnHookFunction(int idx); + void UnHookAll(); + + inline PDWORD GetOldVTable() + { + return dwOldVTable; + } + + DWORD dwInterface; +private: + MEMORY_BASIC_INFORMATION mba; + DWORD* dwOldVTable; + DWORD* dwVTable; + DWORD dwSize; +}; + +class CEHook +{ +public: + CEHook(DWORD dwInterface); + ~CEHook(); + + static DWORD HookVTable(PDWORD dwVTable,DWORD dwHook,DWORD dwIndex); + DWORD BuildDetour(DWORD dwOriginal,DWORD dwHook); + DWORD HookFunction(DWORD dwHook,DWORD dwIndex); + void UnHookFunction(DWORD dwIndex); + void UnHookAll(); +private: + static size_t GateSize; + PDWORD dwVTable; + //Index, + std::map > m_Hooks; +}; + +#endif \ No newline at end of file diff --git a/lua/sdk_fixes/Release/CL.read.1.tlog b/lua/sdk_fixes/Release/CL.read.1.tlog new file mode 100644 index 0000000..c562be6 Binary files /dev/null and b/lua/sdk_fixes/Release/CL.read.1.tlog differ diff --git a/lua/sdk_fixes/Release/CL.write.1.tlog b/lua/sdk_fixes/Release/CL.write.1.tlog new file mode 100644 index 0000000..31f271c Binary files /dev/null and b/lua/sdk_fixes/Release/CL.write.1.tlog differ diff --git a/lua/sdk_fixes/Release/cl.command.1.tlog b/lua/sdk_fixes/Release/cl.command.1.tlog new file mode 100644 index 0000000..3cd5675 Binary files /dev/null and b/lua/sdk_fixes/Release/cl.command.1.tlog differ diff --git a/lua/sdk_fixes/Release/link.command.1.tlog b/lua/sdk_fixes/Release/link.command.1.tlog new file mode 100644 index 0000000..ff99aff Binary files /dev/null and b/lua/sdk_fixes/Release/link.command.1.tlog differ diff --git a/lua/sdk_fixes/Release/link.read.1.tlog b/lua/sdk_fixes/Release/link.read.1.tlog new file mode 100644 index 0000000..307d5ac Binary files /dev/null and b/lua/sdk_fixes/Release/link.read.1.tlog differ diff --git a/lua/sdk_fixes/Release/link.write.1.tlog b/lua/sdk_fixes/Release/link.write.1.tlog new file mode 100644 index 0000000..51ff126 Binary files /dev/null and b/lua/sdk_fixes/Release/link.write.1.tlog differ diff --git a/lua/sdk_fixes/Release/main.obj b/lua/sdk_fixes/Release/main.obj new file mode 100644 index 0000000..cc11860 Binary files /dev/null and b/lua/sdk_fixes/Release/main.obj differ diff --git a/lua/sdk_fixes/Release/mt.command.1.tlog b/lua/sdk_fixes/Release/mt.command.1.tlog new file mode 100644 index 0000000..c254c08 Binary files /dev/null and b/lua/sdk_fixes/Release/mt.command.1.tlog differ diff --git a/lua/sdk_fixes/Release/mt.read.1.tlog b/lua/sdk_fixes/Release/mt.read.1.tlog new file mode 100644 index 0000000..391011f Binary files /dev/null and b/lua/sdk_fixes/Release/mt.read.1.tlog differ diff --git a/lua/sdk_fixes/Release/mt.write.1.tlog b/lua/sdk_fixes/Release/mt.write.1.tlog new file mode 100644 index 0000000..bc388f3 Binary files /dev/null and b/lua/sdk_fixes/Release/mt.write.1.tlog differ diff --git a/lua/sdk_fixes/Release/sdk_fixes.Build.CppClean.log b/lua/sdk_fixes/Release/sdk_fixes.Build.CppClean.log new file mode 100644 index 0000000..0fe0433 --- /dev/null +++ b/lua/sdk_fixes/Release/sdk_fixes.Build.CppClean.log @@ -0,0 +1,18 @@ +..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.pdb +D:\GMOD9DEV_SERVER\GMOD9\LUA\BIN\SDK_FIXES.DLL +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.lib +D:\lua502\lua\sdk_fixes\Release\cl.command.1.tlog +D:\lua502\lua\sdk_fixes\Release\CL.read.1.tlog +D:\lua502\lua\sdk_fixes\Release\CL.write.1.tlog +D:\lua502\lua\sdk_fixes\Release\link.command.1.tlog +D:\lua502\lua\sdk_fixes\Release\link.read.1.tlog +D:\lua502\lua\sdk_fixes\Release\link.write.1.tlog +D:\LUA502\LUA\SDK_FIXES\RELEASE\MAIN.OBJ +D:\lua502\lua\sdk_fixes\Release\mt.command.1.tlog +D:\lua502\lua\sdk_fixes\Release\mt.read.1.tlog +D:\lua502\lua\sdk_fixes\Release\mt.write.1.tlog +D:\lua502\lua\sdk_fixes\Release\sdk_fixes.dll.intermediate.manifest +D:\lua502\lua\sdk_fixes\Release\sdk_fixes.vcxprojResolveAssemblyReference.cache +D:\lua502\lua\sdk_fixes\Release\sdk_fixes.write.1.tlog +D:\LUA502\LUA\SDK_FIXES\RELEASE\VC100.PDB diff --git a/lua/sdk_fixes/Release/sdk_fixes.dll.intermediate.manifest b/lua/sdk_fixes/Release/sdk_fixes.dll.intermediate.manifest new file mode 100644 index 0000000..ecea6f7 --- /dev/null +++ b/lua/sdk_fixes/Release/sdk_fixes.dll.intermediate.manifest @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/lua/sdk_fixes/Release/sdk_fixes.lastbuildstate b/lua/sdk_fixes/Release/sdk_fixes.lastbuildstate new file mode 100644 index 0000000..c2d4a05 --- /dev/null +++ b/lua/sdk_fixes/Release/sdk_fixes.lastbuildstate @@ -0,0 +1,2 @@ +#v4.0:v100:false +Release|Win32|D:\lua502\lua\| diff --git a/lua/sdk_fixes/Release/sdk_fixes.log b/lua/sdk_fixes/Release/sdk_fixes.log new file mode 100644 index 0000000..47f99bd --- /dev/null +++ b/lua/sdk_fixes/Release/sdk_fixes.log @@ -0,0 +1,32 @@ +Build started 29.06.2018 0:54:17. + 1>Project "D:\lua502\lua\sdk_fixes\sdk_fixes.vcxproj" on node 2 (build target(s)). + 1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppBuild.targets(299,5): warning MSB8004: каталог Output заканчиваетÑÑ Ð½Ðµ коÑой чертой. Этот ÑкземплÑÑ€ поÑÑ‚Ñ€Ð¾ÐµÐ½Ð¸Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ‚ коÑую черту, поÑкольку она необходима Ð´Ð»Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ð¾Ð³Ð¾ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð° Output. + 1>InitializeBuildStatus: + Creating "Release\sdk_fixes.unsuccessfulbuild" because "AlwaysCreate" was specified. + ClCompile: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\CL.exe /c /ID:\source2006\public\tier1 /ID:\source2006\public\tier0 /ID:\source2006\game_shared /ID:\source2006\common /ID:\source2006\dlls /ID:\source2006\public /ID:\lua502\lua\lua502_sdk /Zi /nologo /W3 /WX- /O2 /Oi /Oy- /GL /D _WINDLL /D _MBCS /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Release\\" /Fd"Release\vc100.pdb" /Gd /TP /analyze- /errorReport:prompt main.cpp + main.cpp + 1>C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\winnt.h(1140): warning C4005: ARRAYSIZE: изменение Ð¼Ð°ÐºÑ€Ð¾Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ + d:\source2006\public\tier0\commonmacros.h(35): Ñм. предыдущее определение "ARRAYSIZE" + Link: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:"..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.dll" /NOLOGO /LIBPATH:D:\source2006\lib\public /LIBPATH:D:\lua502\lua\Release lua502_sdk.lib vstdlib.lib tier0.lib tier1.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NODEFAULTLIB:LIBCMT.lib /MANIFEST /ManifestFile:"Release\sdk_fixes.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.pdb" /OPT:REF /OPT:ICF /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.lib" /MACHINE:X86 /DLL Release\main.obj /FORCE:MULTIPLE + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: __malloc_crt уже определен в tier1.lib(memoverride.obj); второе определение пропущено + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: _free уже определен в tier1.lib(memoverride.obj); второе определение пропущено + СоздаетÑÑ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ° ..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.lib и объект ..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.exp + 1>..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.dll : warning LNK4088: образ ÑоздаетÑÑ Ð¸Ð·-за параметра /FORCE; образ Ð½ÐµÐ»ÑŒÐ·Ñ Ð·Ð°Ð¿ÑƒÑтить + Создание кода + Создание кода завершено + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: __malloc_crt уже определен в tier1.lib(memoverride.obj); второе определение пропущено + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: _free уже определен в tier1.lib(memoverride.obj); второе определение пропущено + 1>..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.dll : warning LNK4088: образ ÑоздаетÑÑ Ð¸Ð·-за параметра /FORCE; образ Ð½ÐµÐ»ÑŒÐ·Ñ Ð·Ð°Ð¿ÑƒÑтить + sdk_fixes.vcxproj -> D:\lua502\lua\sdk_fixes\..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.dll + Manifest: + C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe /nologo /verbose /outputresource:"..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.dll;#2" /manifest Release\sdk_fixes.dll.intermediate.manifest + FinalizeBuildStatus: + Deleting file "Release\sdk_fixes.unsuccessfulbuild". + Touching "Release\sdk_fixes.lastbuildstate". + 1>Done Building Project "D:\lua502\lua\sdk_fixes\sdk_fixes.vcxproj" (build target(s)). + +ПоÑтроение уÑпешно завершено. + +Time Elapsed 00:00:02.30 diff --git a/lua/sdk_fixes/Release/sdk_fixes.vcxprojResolveAssemblyReference.cache b/lua/sdk_fixes/Release/sdk_fixes.vcxprojResolveAssemblyReference.cache new file mode 100644 index 0000000..3f01681 Binary files /dev/null and b/lua/sdk_fixes/Release/sdk_fixes.vcxprojResolveAssemblyReference.cache differ diff --git a/lua/sdk_fixes/Release/sdk_fixes.write.1.tlog b/lua/sdk_fixes/Release/sdk_fixes.write.1.tlog new file mode 100644 index 0000000..10202c0 --- /dev/null +++ b/lua/sdk_fixes/Release/sdk_fixes.write.1.tlog @@ -0,0 +1,35 @@ +^D:\lua502\lua\sdk_fixes\sdk_fixes.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.exp +^D:\lua502\lua\sdk_fixes\sdk_fixes.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.exp +^D:\lua502\lua\sdk_fixes\sdk_fixes.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.exp +^D:\lua502\lua\sdk_fixes\sdk_fixes.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.exp +^D:\lua502\lua\sdk_fixes\sdk_fixes.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.exp +^D:\lua502\lua\sdk_fixes\sdk_fixes.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.exp +^D:\lua502\lua\sdk_fixes\sdk_fixes.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_fixes.exp diff --git a/lua/sdk_fixes/Release/vc100.pdb b/lua/sdk_fixes/Release/vc100.pdb new file mode 100644 index 0000000..6be787e Binary files /dev/null and b/lua/sdk_fixes/Release/vc100.pdb differ diff --git a/lua/sdk_fixes/main.cpp b/lua/sdk_fixes/main.cpp new file mode 100644 index 0000000..f495647 --- /dev/null +++ b/lua/sdk_fixes/main.cpp @@ -0,0 +1,434 @@ +#define GAME_DLL +#include "cbase.h" +#include "main.h" +#include "plugin.h" +#include "sigscan.h" +#include "chook.h" +#include "dlls/iplayerinfo.h" +#include "filesystem.h" +#include "eiface.h" +#include "threadtools.h" +#include "utlvector.h" +#include "vphysics_interface.h" +#include "steam/steam_api.h" +#include "inetchannelinfo.h" +#include "inetchannel.h" +#include "inetmessage.h" +#include "netmessage.h" +#include "bitbuf.h" +#include "baselib.h" +#include "memdbgon.h" + +class CBaseClient; +static bool _IsSecurePath(const char* pPath); +bool IsValidModel_Internal(const char* pPath); +bool IsValidModel_Hook(const char*); +void Nocollide_Hook(IPhysicsObject*,IPhysicsObject*); +bool __fastcall Process_Hook(void* thisptr,void*); + +typedef struct { + char name[260]; + char value[260]; +} cvar_t; + +typedef struct { + void* vtable; + bool m_bReliable; + void* chan; + void* handler; + CUtlVector cvars; +} net_setconvar_t; + +typedef struct { + void* p1; + void* p2; +} pair_t; + +inline bool IsPairsEqual(pair_t& a,pair_t& b) +{ + return ((a.p1 == b.p1) || (a.p1 == b.p2) + || (a.p2 == b.p1) || (a.p2 == b.p2)); +} + +typedef bool (__thiscall *PrcSetConVar_t)(CBaseClient*,net_setconvar_t*); +static bool __fastcall PrcSetConVar_Hook(CBaseClient*,void*,net_setconvar_t*); + +typedef void (*Nocollide_t)(void*,void*); +typedef bool (__thiscall* Process_t)(void*); +typedef void (*Disconnect_t)(void*,const char*,...); + +DECLARE_PLUGIN(CSDKFixes) + virtual bool Load(CreateInterfaceFn, + CreateInterfaceFn); + virtual bool LuaInit(lua_State*); + virtual void Unload(); + virtual void LevelShutdown(); + + static IsValidModel_t s_pIsValidModel; + static PrcSetConVar_t s_pPrcSetConVar; + static Nocollide_t s_pNocollide; + static Process_t s_pProcess; + static Disconnect_t s_pDisconnect; + + CUtlVector m_Nocollides; +private: + CHook* m_pIsValidModelHook; + CHook* m_pSetConVarHook; + CHook* m_pNocollideHook; + CHook* m_pProcessHook; +END_PLUGIN(CSDKFixes,"sdk_fixes"); + +IsValidModel_t CSDKFixes::s_pIsValidModel = NULL; +PrcSetConVar_t CSDKFixes::s_pPrcSetConVar = NULL; +Nocollide_t CSDKFixes::s_pNocollide = NULL; +Process_t CSDKFixes::s_pProcess = NULL; +Disconnect_t CSDKFixes::s_pDisconnect = NULL; +IPlayerInfoManager* playerinfomanager = NULL; +IVEngineServer* engine = NULL; +IFileSystem* filesystem = NULL; + +class CGameServer; + +class CBaseClient +{ +public: + inline edict_t* GetEdict() + { + return *((edict_t**)this+145); + } + + inline int GetUserId() + { + return *((int*)this+5); + } + + inline const char* GetVar(const char* pKey) + { + return m_pConVars->GetString(pKey); + } + + inline INetChannel* GetNetChannel() + { + return *((INetChannel**)this+54); + } + + inline int GetSignonState() + { + return *((int*)this+55); + } + + inline char* GetName() + { + return (char*)this+24; + } + + void SetName(const char* pName) + { + strncpy(((char*)this+24),pName,32); + } + + inline CSteamID* GetSteamId() + { + return *(CSteamID**)((char*)this+120); + } + + inline void SetVar(const char* pKey, + const char* pValue) + { + m_pConVars->SetString(pKey,pValue); + //m_bConvarsChanged = false; + } + + inline void SetConVarsChanged(bool bVal) + { + m_bConvarsChanged = bVal; + } + + inline int GetClientIndex() + { + return *(int*)((char*)this+0xC); + } + + char m_szTmp[160]; + KeyValues* m_pConVars; + bool m_bConvarsChanged; + CGameServer* m_Server; +}; + +class CGameServer +{ +public: + CBaseClient* GetClient(edict_t* pEdict) + { + for(int i = 0; i < m_Clients.Count(); i++) + if(m_Clients[i]->GetEdict() == pEdict) + return m_Clients[i]; + return NULL; + } + + char m_szTmp[252]; + int m_nUserId; + int m_nMaxclients; + int m_nSpawnCount; + float m_fTickInterval; + CUtlVector m_Clients; +}; + +CGameServer* gameserver = NULL; + +bool CSDKFixes::Load(CreateInterfaceFn appFactory, + CreateInterfaceFn gameFactory) +{ + DWORD dwIsValidModel,dwSetConVar,dwCall,dwNocollide,dwProcess; + filesystem = (IFileSystem*)appFactory( + FILESYSTEM_INTERFACE_VERSION,0); + engine = (IVEngineServer*)appFactory( + INTERFACEVERSION_VENGINESERVER,0); + playerinfomanager = (IPlayerInfoManager*)gameFactory( + INTERFACEVERSION_PLAYERINFOMANAGER,0); + + if(!filesystem || !engine || !playerinfomanager) + { + Warning("Failed appFactory/gameFactory (%p %p %p)\n", + filesystem,engine,playerinfomanager); + return false; + } + + DECLARE_SIGSCAN(dwIsValidModel,"server.dll", + ISVALIDMODEL_SIG,ISVALIDMODEL_MASK,0, + SigScan::CSigScan::SIG_FUNCTION); + DECLARE_SIGSCAN(dwCall,"server.dll",PCALL_SIG, + PCALL_MASK,0,SigScan::CSigScan::SIG_FUNCTION); + DECLARE_SIGSCAN(gameserver,"engine.dll",GAMESERVER_SIG, + GAMESERVER_MASK,GAMESERVER_OFFSET, + SigScan::CSigScan::SIG_PTR); + DECLARE_SIGSCAN(dwSetConVar,"engine.dll",SETCONVAR_SIG, + SETCONVAR_MASK,0,SigScan::CSigScan::SIG_FUNCTION); + DECLARE_SIGSCAN(dwProcess,"engine.dll",CLCPROCESS_SIG, + CLCPROCESS_MASK,0,SigScan::CSigScan::SIG_FUNCTION); + DECLARE_SIGSCAN(s_pDisconnect,"engine.dll",CLDISCONNECT_SIG, + CLDISCONNECT_MASK,0,SigScan::CSigScan::SIG_FUNCTION); + SigScan::Scan(); + dwNocollide = FetchCall(dwCall); + + Msg("gameserver %p\n",gameserver); + m_pIsValidModelHook = new CHook(dwIsValidModel, + ISVALIDMODEL_HOOKSIZE); + s_pIsValidModel = (IsValidModel_t)m_pIsValidModelHook + ->HookFunction((DWORD)IsValidModel_Hook); + + m_pSetConVarHook = new CHook(dwSetConVar, + SETCONVAR_HOOKSIZE); + s_pPrcSetConVar = (PrcSetConVar_t)m_pSetConVarHook + ->HookFunction((DWORD)&PrcSetConVar_Hook); + + m_pNocollideHook = new CHook(dwNocollide,PCALL_HOOKSIZE); + s_pNocollide = (Nocollide_t)m_pNocollideHook + ->HookFunction((DWORD)&Nocollide_Hook); + + m_pProcessHook = new CHook(dwProcess,CLCPROCESS_HOOKSIZE); + s_pProcess = (Process_t)m_pProcessHook + ->HookFunction((DWORD)&Process_Hook); + Msg("GetPlayerUserid %p\n",(*(void***)engine)[15]); + return true; +} + +bool CSDKFixes::LuaInit(lua_State* L) +{ + CLuaLibrary::Init(L); + return true; +} + +void CSDKFixes::Unload() +{ + if(m_pIsValidModelHook) + delete m_pIsValidModelHook; + if(m_pSetConVarHook) + delete m_pSetConVarHook; + if(m_pNocollideHook) + delete m_pNocollideHook; +} + +void CSDKFixes::LevelShutdown() +{ + m_Nocollides.RemoveAll(); +} + +typedef enum { + VALUE_NONE, + VALUE_MODEL, + VALUE_MATERIAL, +} vartype_t; + +typedef struct { + const char* pName; + const char* pDefault; + vartype_t type; +} userinfo_t; + +userinfo_t g_UserInfos[] = { + {"gm_wheel_model","models/props_junk/sawblade001a.mdl",VALUE_MODEL}, + {NULL,NULL,VALUE_NONE} +}; + +static bool __fastcall PrcSetConVar_Hook(CBaseClient* pClient, + void* edx,net_setconvar_t* pMsg) +{ + bool bOk = CSDKFixes::s_pPrcSetConVar(pClient,pMsg); + for(int i = 0; i < pMsg->cvars.Count(); i++) + { + for(userinfo_t* j = g_UserInfos; j->pName; j++) + { + cvar_t& cv = pMsg->cvars[i]; + if(strcmp(cv.name,j->pName) + || j->type != VALUE_MODEL) + continue; + if(!IsValidModel_Internal(cv.value)) + { + Msg("Client %d tried to send invalid user value (%s)!\n", + pClient->GetUserId(),cv.name); + strcpy_s(cv.value,j->pDefault); + } + } + } + return bOk; +} + +inline bool _CheckExtension(const char* pPath, + const char* pExt) +{ + const char* pTmp; + if(!(pTmp = strrchr(pPath,'.'))) + return false; + return !strcmp(pTmp,pExt); +} + +static bool _IsSecurePath(const char* pPath) +{ + static char s_cBanned[] = { + '\t','\r','\b','\n',':'}; + size_t uLen = strlen(pPath); + if(pPath[0] == '/' + || pPath[0] == '\\') + return false; + for(size_t i = 0; i < uLen; i++) + { + if(pPath[i] == s_cBanned[ + i%sizeof(s_cBanned)]) + return false; + if(pPath[i] == '.' && pPath[i+1] == '.') + return false; + } + + return !_CheckExtension(pPath,".bsp"); +} + +bool IsValidModel_Internal(const char* pPath) +{ + if(!_IsSecurePath(pPath)) return false; + if(!_CheckExtension(pPath,".mdl")) return false; + if(!filesystem->FileExists(pPath)) + return false; + return true; +} + +bool IsValidModel_Hook(const char* pPath) +{ + if(!IsValidModel_Internal(pPath)) + return false; + return CSDKFixes::s_pIsValidModel(pPath); +} + +void Nocollide_Hook(IPhysicsObject* obj1,IPhysicsObject* obj2) +{ + pair_t pr; + pr.p1 = obj1; + pr.p2 = obj2; + for(int i = 0; i < s_CSDKFixes.m_Nocollides.Count(); i++) + { + pair_t pr2 = s_CSDKFixes.m_Nocollides[i]; + if(IsPairsEqual(pr,pr2)) return; + } + s_CSDKFixes.m_Nocollides.AddToTail(pr); + CSDKFixes::s_pNocollide(obj1,obj2); +} + +const char* RenderSteamId(CSteamID* id) +{ + static char szBuf[64]; + uint64 sid = id->ConvertToUint64(); + int x,y,z; + //STEAM_X:Y:Z + x = sid>>61; + y = sid&1; + z = (sid>>1)&0x7FFFFFFF; + Q_snprintf(szBuf,64,"STEAM_%d:%d:%d",x,y,z); + return szBuf; +} + +bool __fastcall Process_Hook(void* thisptr,void*) +{ + INetMessage* pMsg = (INetMessage*)thisptr; + INetChannel* netchan = pMsg->GetNetChannel(); + for(int i = 0; i < gameserver->m_Clients.Count(); i++) + { + CBaseClient* cl = gameserver->m_Clients[i]; + if(cl->GetNetChannel() == netchan) + { + if(cl->GetSignonState() > 3) + { + char szBuf[128]; + Q_snprintf(szBuf,sizeof(szBuf),"Player %s (%s) attempted to bug sprays, lets kick him\n", + cl->GetName(),RenderSteamId(cl->GetSteamId())); + + Log(szBuf); + CSDKFixes::s_pDisconnect((char*)cl+0x4,szBuf); + return false; + } + } + } + + return CSDKFixes::s_pProcess(thisptr); +} + +DECLARE_LIBRARY("_player") +DECLARE_TABLE(_G) + +inline CBaseClient* GetPlayer(lua_State* L) +{ + edict_t* pPly; + CBaseClient* pClient; + if(!(pPly = engine->PEntityOfEntIndex((int)lua_tonumber(L,1)))) + luaL_error(L,"Wrong player index!"); + if(!(pClient = gameserver->GetClient(pPly))) + luaL_error(L,"Edict isn't a client (%d)!",(int)lua_tonumber(L,1)); + return pClient; +} + +DECLARE_FUNCTION(_G,_SetClientConVar_String) +{ + luaL_checktype(L,1,LUA_TNUMBER); + luaL_checktype(L,2,LUA_TSTRING); + luaL_checktype(L,3,LUA_TSTRING); + CBaseClient* pPlayer = GetPlayer(L); + pPlayer->SetVar(lua_tostring(L,2),lua_tostring(L,3)); + pPlayer->SetConVarsChanged(true); + return 0; +} + +DECLARE_FUNCTION(_G,_PlayerGetName) +{ + luaL_checktype(L,1,LUA_TNUMBER); + lua_pushstring(L,GetPlayer(L)->GetVar("name")); + return 1; +} + +DECLARE_FUNCTION(_G,_PlayerSetName) +{ + luaL_checktype(L,1,LUA_TNUMBER); + luaL_checktype(L,2,LUA_TSTRING); + CBaseClient* pPlayer = GetPlayer(L); + pPlayer->SetVar("name",lua_tostring(L,2)); + pPlayer->SetConVarsChanged(true); + return 0; +} \ No newline at end of file diff --git a/lua/sdk_fixes/main.h b/lua/sdk_fixes/main.h new file mode 100644 index 0000000..98d1ea7 --- /dev/null +++ b/lua/sdk_fixes/main.h @@ -0,0 +1,30 @@ +#ifndef __MAIN_H +#define __MAIN_H + +#define FetchCall(dwSig) ((dwSig+5)+*(int*)((char*)dwSig+1)) + +#define ISVALIDMODEL_SIG "\x51\x55\x8B\x6C\x24\x0C\x8B\xC5\x8D\x50\x01\xEB\x03\x8D\x49\x00\x8A\x08\x40\x84\xC9\x75\xF9\x2B\xC2\x83\xF8\x04\x73\x05\x32\xC0\x5D\x59\xC3\x53\x56\x57\x55\xE8\x00\x00\x00\x00\x8B\xD8\xA1\x00\x00\x00\x00\x83\xC4\x04\x33\xFF\x85\xC0" +#define ISVALIDMODEL_MASK "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx????xxx????xxxxxxx" +#define ISVALIDMODEL_HOOKSIZE 0x06 +typedef bool (*IsValidModel_t)(const char*); + +#define GAMESERVER_SIG "\xB9\x00\x00\x00\x00\xE8\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x5F\x5E\x81\xC4\x00\x00\x00\x00\xC3" +#define GAMESERVER_MASK "x????x????x????xxxx????x" +#define GAMESERVER_OFFSET 0x01 + +#define SETCONVAR_SIG "\x55\x56\x57\x8B\x7C\x24\x10\x33\xF6\x39\x77\x1C" +#define SETCONVAR_MASK "xxxxxxxxxxxx" +#define SETCONVAR_HOOKSIZE 0x07 + +#define PCALL_SIG "\xE8\x00\x00\x00\x00\x83\xC4\x08\x8D\x54\x24\x14\x52\x6A\x00\x8B\xCF\xC7\x44\x24\x00\x00\x00\x00\x00\xE8\x00\x00\x00\x00" +#define PCALL_MASK "x????xxxxxxxxxxxxxxx?????x????" +#define PCALL_HOOKSIZE 0x05 + +#define CLCPROCESS_SIG "\x8B\xC1\x8B\x48\x0C\x8B\x11\x50\xFF\x52\x00\xC3\xCC\xCC\xCC\xCC\x6A\xFF\x68\x00\x00\x00\x00\x64\xA1\x00\x00\x00\x00\x50\x64\x89\x25\x00\x00\x00\x00\x51\x8B\xC1\x89\x04\x24\xC7\x00\x00\x00\x00\x00\x33\xD2\x89\x54\x24\x0C\xB9\x00\x00\x00\x00\xC7\x00\x00\x00\x00\x00\x88\x48\x04\x89\x50\x08\x89\x4C\x24\x0C\xC7\x00\x00\x00\x00\x00\x33\xC9" +#define CLCPROCESS_MASK "xxxxxxxxxx?xxxxxxxx????xx????xxxx????xxxxxxxx????xxxxxxx????xx????xxxxxxxxxxxx????xx" +#define CLCPROCESS_HOOKSIZE 0x07 + +#define CLDISCONNECT_SIG "\x81\xEC\x00\x00\x00\x00\x56\x8B\xB4\x24\x00\x00\x00\x00\x83\xBE\xD8\x00\x00\x00\x00" +#define CLDISCONNECT_MASK "xx????xxxx????xxxxxxx" + +#endif \ No newline at end of file diff --git a/lua/sdk_fixes/netmessage.h b/lua/sdk_fixes/netmessage.h new file mode 100644 index 0000000..779d8c0 --- /dev/null +++ b/lua/sdk_fixes/netmessage.h @@ -0,0 +1,28 @@ +#ifndef __NETMESSAGE_H +#define __NETMESSAGE_H + +#include "inetmessage.h" +#include "inetchannelinfo.h" + +class CNetMessage : public INetMessage +{ +public: + virtual void SetNetChannel(INetChannel* pChan){m_pChan = pChan;} + virtual void SetReliable(bool m_bR){m_bReliable=m_bR;} + virtual bool Process(){return true;} + virtual bool ReadFromBuffer(bf_read&){return true;} + virtual bool WriteToBuffer(bf_write&){return true;} + virtual bool IsReliable() const {return m_bReliable;} + + virtual int GetType() const {return 0;} + virtual int GetGroup() const {return 0;} + virtual const char* GetName() const {return "";} + virtual INetChannel* GetNetChannel() const {return m_pChan;} + virtual const char* ToString() const {return "";} + +private: + bool m_bReliable; + INetChannel* m_pChan; +}; + +#endif \ No newline at end of file diff --git a/lua/sdk_fixes/sdk_fixes.vcxproj b/lua/sdk_fixes/sdk_fixes.vcxproj new file mode 100644 index 0000000..803a857 --- /dev/null +++ b/lua/sdk_fixes/sdk_fixes.vcxproj @@ -0,0 +1,82 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {B02E949C-9ADA-4A7E-ACFE-0016D3C22CC3} + sdk_fixes + + + + Application + true + MultiByte + + + DynamicLibrary + false + true + MultiByte + + + + + + + + + + + + + ..\..\..\GMod9Dev_Server\gmod9\lua\bin + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + true + true + D:\source2006\public\tier1;D:\source2006\public\tier0;D:\source2006\game_shared;D:\source2006\common;D:\source2006\dlls;D:\source2006\public;D:\lua502\lua\lua502_sdk;%(AdditionalIncludeDirectories) + + + true + true + true + D:\source2006\lib\public;D:\lua502\lua\Release;%(AdditionalLibraryDirectories) + lua502_sdk.lib;vstdlib.lib;tier0.lib;tier1.lib;%(AdditionalDependencies) + LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) + /FORCE:MULTIPLE %(AdditionalOptions) + + + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/lua/sdk_fixes/sdk_fixes.vcxproj.filters b/lua/sdk_fixes/sdk_fixes.vcxproj.filters new file mode 100644 index 0000000..8e38d65 --- /dev/null +++ b/lua/sdk_fixes/sdk_fixes.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Файлы иÑходного кода + + + + + Заголовочные файлы + + + Заголовочные файлы + + + \ No newline at end of file diff --git a/lua/sdk_fixes/sdk_fixes.vcxproj.user b/lua/sdk_fixes/sdk_fixes.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/lua/sdk_fixes/sdk_fixes.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lua/sdk_http b/lua/sdk_http new file mode 160000 index 0000000..f97a70d --- /dev/null +++ b/lua/sdk_http @@ -0,0 +1 @@ +Subproject commit f97a70db14956e0d1d0ca7719e3db9eed36fcfef diff --git a/lua/sdk_http.rar b/lua/sdk_http.rar new file mode 100644 index 0000000..1ee5287 Binary files /dev/null and b/lua/sdk_http.rar differ diff --git a/lua/sdk_net/Release/CL.read.1.tlog b/lua/sdk_net/Release/CL.read.1.tlog new file mode 100644 index 0000000..3de5d43 Binary files /dev/null and b/lua/sdk_net/Release/CL.read.1.tlog differ diff --git a/lua/sdk_net/Release/CL.write.1.tlog b/lua/sdk_net/Release/CL.write.1.tlog new file mode 100644 index 0000000..b276fc2 Binary files /dev/null and b/lua/sdk_net/Release/CL.write.1.tlog differ diff --git a/lua/sdk_net/Release/cl.command.1.tlog b/lua/sdk_net/Release/cl.command.1.tlog new file mode 100644 index 0000000..4e0d036 Binary files /dev/null and b/lua/sdk_net/Release/cl.command.1.tlog differ diff --git a/lua/sdk_net/Release/link.command.1.tlog b/lua/sdk_net/Release/link.command.1.tlog new file mode 100644 index 0000000..27e4594 Binary files /dev/null and b/lua/sdk_net/Release/link.command.1.tlog differ diff --git a/lua/sdk_net/Release/link.read.1.tlog b/lua/sdk_net/Release/link.read.1.tlog new file mode 100644 index 0000000..3014179 Binary files /dev/null and b/lua/sdk_net/Release/link.read.1.tlog differ diff --git a/lua/sdk_net/Release/link.write.1.tlog b/lua/sdk_net/Release/link.write.1.tlog new file mode 100644 index 0000000..9e67737 Binary files /dev/null and b/lua/sdk_net/Release/link.write.1.tlog differ diff --git a/lua/sdk_net/Release/main.obj b/lua/sdk_net/Release/main.obj new file mode 100644 index 0000000..c4a7e99 Binary files /dev/null and b/lua/sdk_net/Release/main.obj differ diff --git a/lua/sdk_net/Release/mt.command.1.tlog b/lua/sdk_net/Release/mt.command.1.tlog new file mode 100644 index 0000000..3590b92 Binary files /dev/null and b/lua/sdk_net/Release/mt.command.1.tlog differ diff --git a/lua/sdk_net/Release/mt.read.1.tlog b/lua/sdk_net/Release/mt.read.1.tlog new file mode 100644 index 0000000..615b8eb Binary files /dev/null and b/lua/sdk_net/Release/mt.read.1.tlog differ diff --git a/lua/sdk_net/Release/mt.write.1.tlog b/lua/sdk_net/Release/mt.write.1.tlog new file mode 100644 index 0000000..8e79286 Binary files /dev/null and b/lua/sdk_net/Release/mt.write.1.tlog differ diff --git a/lua/sdk_net/Release/sdk_net.dll.intermediate.manifest b/lua/sdk_net/Release/sdk_net.dll.intermediate.manifest new file mode 100644 index 0000000..ecea6f7 --- /dev/null +++ b/lua/sdk_net/Release/sdk_net.dll.intermediate.manifest @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/lua/sdk_net/Release/sdk_net.lastbuildstate b/lua/sdk_net/Release/sdk_net.lastbuildstate new file mode 100644 index 0000000..c2d4a05 --- /dev/null +++ b/lua/sdk_net/Release/sdk_net.lastbuildstate @@ -0,0 +1,2 @@ +#v4.0:v100:false +Release|Win32|D:\lua502\lua\| diff --git a/lua/sdk_net/Release/sdk_net.log b/lua/sdk_net/Release/sdk_net.log new file mode 100644 index 0000000..35c4431 --- /dev/null +++ b/lua/sdk_net/Release/sdk_net.log @@ -0,0 +1,30 @@ +Build started 01.07.2018 2:34:32. + 1>Project "D:\lua502\lua\sdk_net\sdk_net.vcxproj" on node 2 (build target(s)). + 1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppBuild.targets(299,5): warning MSB8004: каталог Output заканчиваетÑÑ Ð½Ðµ коÑой чертой. Этот ÑкземплÑÑ€ поÑÑ‚Ñ€Ð¾ÐµÐ½Ð¸Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ‚ коÑую черту, поÑкольку она необходима Ð´Ð»Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ð¾Ð³Ð¾ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð° Output. + 1>InitializeBuildStatus: + Creating "Release\sdk_net.unsuccessfulbuild" because "AlwaysCreate" was specified. + ClCompile: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\CL.exe /c /ID:\source2006\public\tier1 /ID:\source2006\public\tier0 /ID:\source2006\game_shared /ID:\source2006\common /ID:\source2006\dlls /ID:\source2006\public /ID:\lua502\lua\lua502_sdk /Zi /nologo /W3 /WX- /O2 /Oi /Oy- /GL /D _WINDLL /D _MBCS /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Release\\" /Fd"Release\vc100.pdb" /Gd /TP /analyze- /errorReport:prompt main.cpp + main.cpp + Link: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:"..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_net.dll" /NOLOGO /LIBPATH:D:\source2006\lib\public /LIBPATH:D:\lua502\lua\Release lua502_sdk.lib vstdlib.lib tier0.lib tier1.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NODEFAULTLIB:LIBCMT.lib /MANIFEST /ManifestFile:"Release\sdk_net.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.pdb" /OPT:REF /OPT:ICF /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib" /MACHINE:X86 /DLL Release\main.obj /FORCE:MULTIPLE + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: __malloc_crt уже определен в tier1.lib(memoverride.obj); второе определение пропущено + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: _free уже определен в tier1.lib(memoverride.obj); второе определение пропущено + СоздаетÑÑ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ° ..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib и объект ..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp + 1>..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_net.dll : warning LNK4088: образ ÑоздаетÑÑ Ð¸Ð·-за параметра /FORCE; образ Ð½ÐµÐ»ÑŒÐ·Ñ Ð·Ð°Ð¿ÑƒÑтить + Создание кода + Создание кода завершено + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: __malloc_crt уже определен в tier1.lib(memoverride.obj); второе определение пропущено + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: _free уже определен в tier1.lib(memoverride.obj); второе определение пропущено + 1>..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_net.dll : warning LNK4088: образ ÑоздаетÑÑ Ð¸Ð·-за параметра /FORCE; образ Ð½ÐµÐ»ÑŒÐ·Ñ Ð·Ð°Ð¿ÑƒÑтить + sdk_net.vcxproj -> D:\lua502\lua\sdk_net\..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_net.dll + Manifest: + C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe /nologo /verbose /outputresource:"..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_net.dll;#2" /manifest Release\sdk_net.dll.intermediate.manifest + FinalizeBuildStatus: + Deleting file "Release\sdk_net.unsuccessfulbuild". + Touching "Release\sdk_net.lastbuildstate". + 1>Done Building Project "D:\lua502\lua\sdk_net\sdk_net.vcxproj" (build target(s)). + +ПоÑтроение уÑпешно завершено. + +Time Elapsed 00:00:01.27 diff --git a/lua/sdk_net/Release/sdk_net.vcxprojResolveAssemblyReference.cache b/lua/sdk_net/Release/sdk_net.vcxprojResolveAssemblyReference.cache new file mode 100644 index 0000000..3f01681 Binary files /dev/null and b/lua/sdk_net/Release/sdk_net.vcxprojResolveAssemblyReference.cache differ diff --git a/lua/sdk_net/Release/sdk_net.write.1.tlog b/lua/sdk_net/Release/sdk_net.write.1.tlog new file mode 100644 index 0000000..1bd7fed --- /dev/null +++ b/lua/sdk_net/Release/sdk_net.write.1.tlog @@ -0,0 +1,80 @@ +^D:\lua502\lua\sdk_net\sdk_net.vcxproj +D:\lua502\lua\Release\sdk_net.lib +D:\lua502\lua\Release\sdk_net.lib +D:\lua502\lua\Release\sdk_net.exp +D:\lua502\lua\Release\sdk_net.exp +^D:\lua502\lua\sdk_net\sdk_net.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +^D:\lua502\lua\sdk_net\sdk_net.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +^D:\lua502\lua\sdk_net\sdk_net.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +^D:\lua502\lua\sdk_net\sdk_net.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +^D:\lua502\lua\sdk_net\sdk_net.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +^D:\lua502\lua\sdk_net\sdk_net.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +^D:\lua502\lua\sdk_net\sdk_net.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +^D:\lua502\lua\sdk_net\sdk_net.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +^D:\lua502\lua\sdk_net\sdk_net.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +^D:\lua502\lua\sdk_net\sdk_net.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +^D:\lua502\lua\sdk_net\sdk_net.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +^D:\lua502\lua\sdk_net\sdk_net.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +^D:\lua502\lua\sdk_net\sdk_net.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +^D:\lua502\lua\sdk_net\sdk_net.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +^D:\lua502\lua\sdk_net\sdk_net.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_net.exp diff --git a/lua/sdk_net/Release/vc100.pdb b/lua/sdk_net/Release/vc100.pdb new file mode 100644 index 0000000..609cdfd Binary files /dev/null and b/lua/sdk_net/Release/vc100.pdb differ diff --git a/lua/sdk_net/main.cpp b/lua/sdk_net/main.cpp new file mode 100644 index 0000000..ea53b01 --- /dev/null +++ b/lua/sdk_net/main.cpp @@ -0,0 +1,386 @@ +#include "plugin.h" +#include "baselib.h" +#include "eiface.h" +#include "inetmsghandler.h" +#include "inetchannel.h" +#include "inetmessage.h" +#include "protocol.h" +#include "netmessage.h" +#include "bitbuf.h" +#include "utlvector.h" +#include "ehandle.h" +#include "basehandle.h" + +DECLARE_PLUGIN(CSDKNet) + virtual bool Load(CreateInterfaceFn,CreateInterfaceFn); + virtual bool LuaInit(lua_State*); +END_PLUGIN(CSDKNet,"sdk_net"); + +IVEngineServer* engine; + +bool CSDKNet::Load(CreateInterfaceFn intFn,CreateInterfaceFn) +{ + if(!(engine = (IVEngineServer*)intFn(INTERFACEVERSION_VENGINESERVER,0))) + return false; + return true; +} + +bool CSDKNet::LuaInit(lua_State* L) +{ + CLuaLibrary::Init(L); + return true; +} + +DECLARE_LIBRARY("net") +DECLARE_TABLE(net) + +inline INetChannel* GetPlayerNet(lua_State* L,int idx) +{ + INetChannel* pNet; + if(!(pNet = (INetChannel*)engine->GetPlayerNetInfo((int)lua_tonumber(L,idx)))) + luaL_error(L,"Wrong INetChannel!"); + return pNet; +} + +class NET_StringCmd : public CNetMessage +{ +public: + virtual int GetType(){return net_StringCmd;} + virtual bool WriteToBuffer(bf_write& bf) + { + bf.WriteUBitLong(GetType(),5); + bf.WriteString(pCommand); + return true; + } + + const char* pCommand; +} g_StringCmd; + +DECLARE_FUNCTION(net,StringCmd) +{ + luaL_checktype(L,1,LUA_TNUMBER); + luaL_checktype(L,2,LUA_TSTRING); + g_StringCmd.pCommand = lua_tostring(L,2); + GetPlayerNet(L,1)->SendNetMsg(g_StringCmd); + return 0; +} + +class NET_SetConVar : public CNetMessage +{ +public: + typedef struct { + char szName[260]; + char szValue[260]; + } cvar_t; + + virtual int GetType(){return net_SetConVar;} + virtual bool WriteToBuffer(bf_write& bf) + { + bf.WriteUBitLong(GetType(),5); + uint8 bCount = m_Cvars.Count()&0xFF; + bf.WriteByte(bCount); + for(int i = 0; i < bCount; i++) + { + bf.WriteString(m_Cvars[i].szName); + bf.WriteString(m_Cvars[i].szValue); + } + return true; + } + + CUtlVector m_Cvars; +} g_SetConVar; + +DECLARE_FUNCTION(net,SetConVar) +{ + luaL_checktype(L,1,LUA_TNUMBER); + luaL_checktype(L,2,LUA_TTABLE); + + lua_pushnil(L); + while(lua_next(L,2)) + { + lua_pushvalue(L,-2); + NET_SetConVar::cvar_t cvar; + V_strncpy(cvar.szName,lua_tostring(L,-1),260); + V_strncpy(cvar.szValue,lua_tostring(L,-2),260); + g_SetConVar.m_Cvars.AddToTail(cvar); + lua_pop(L,2); + } + + GetPlayerNet(L,1)->SendNetMsg(g_SetConVar); + g_SetConVar.m_Cvars.RemoveAll(); + return 0; +} + +static char g_szUMsg[256]; +bf_write g_Msg(g_szUMsg,sizeof(g_szUMsg)); +int g_iMsgId = -1; +CUtlVector g_Recipients; + +inline void CheckMsg(lua_State* L) +{ + if(g_iMsgId<0) + luaL_error(L,"No message started"); +} + +const char* s_Msgs[] = { + "Geiger", + "Train", + "HudText", + "SayText", + "TextMsg", + "HudMsg", + "GModText", + "GModTextAnimate", + "GModVersion", + "GModRect", + "GModTextHide", + "GModRectHide", + "GModTextHideAll", + "GModRectHideAll", + "GModRectAnimate", + "ResetHUD", + "GameTitle", + "ItemPickup", + "ShowMenu", + "Shake", + "Fade", + "VGUIMenu", + "Battery", + "Damage", + "VoiceMask", + "RequestState", + "CloseCaption", + "HintText", + "SquadMemberDied", + "AmmoDenied", + "CreditsMsg", + "GModAddSpawnItem", + "GModRemoveSpawnItem", + "GModRemoveSpawnCat", + "GModRemoveSpawnAll", + "Spawn_SetCategory", + "WQuad", + "WQuadHide", + "WQuadHideAll", + "WQuadAnimate" +}; +#define NUM_MSGS (sizeof(s_Msgs)/sizeof(const char*)) + +DECLARE_TABLE(_G) + +DECLARE_FUNCTION(_G,_UserMessageBegin) +{ + luaL_checktype(L,1,LUA_TTABLE); + if(lua_isnumber(L,2)) g_iMsgId = lua_tonumber(L,1); + else if(lua_isstring(L,2)) + { + for(int i = 0; i < NUM_MSGS; i++) + { + if(!V_strcmp(lua_tostring(L,2),s_Msgs[i])) + { + g_iMsgId = i; + break; + } + } + if(g_iMsgId<0) + return luaL_error(L,"Wrong usermessage!"); + } + lua_pushnil(L); + while(lua_next(L,1)) + { + //-1 value, -2 key + g_Recipients.AddToTail(lua_tonumber(L,-1)); + lua_pop(L,1); + } + memset(g_szUMsg,'\0',sizeof(g_szUMsg)); + g_Msg.Reset(); + return 0; +} + +class SVC_UserMessage : public CNetMessage +{ +public: + virtual int GetType(){return svc_UserMessage;} + virtual bool WriteToBuffer(bf_write& bf) + { + bf.WriteUBitLong(GetType(),5); + bf.WriteByte(g_iMsgId); + int len = g_Msg.GetNumBitsWritten(); + bf.WriteUBitLong(len,11); + bf.WriteBits(g_Msg.GetData(),len); + return true; + } +} g_UMsg; + +DECLARE_FUNCTION(_G,_MessageEnd) +{ + if(g_iMsgId<0) + return luaL_error(L,"No message started!"); + if(!g_Recipients.Count()) + return luaL_error(L,"No recipients!"); + for(int i = 0; i < g_Recipients.Count(); i++) + { + INetChannel* pNet; + if(!(pNet = (INetChannel*)engine->GetPlayerNetInfo(g_Recipients[i]))) + return luaL_error(L,"Player %d doesn't have netchannel!"); + pNet->SendNetMsg(g_UMsg); + } + g_Recipients.RemoveAll(); + g_iMsgId = -1; + return 0; +} + +DECLARE_FUNCTION(_G,_WRITE_BYTE) +{ + luaL_checktype(L,1,LUA_TNUMBER); + CheckMsg(L); + g_Msg.WriteByte(lua_tonumber(L,1)); + return 0; +} + +DECLARE_FUNCTION(_G,_WRITE_CHAR) +{ + luaL_checktype(L,1,LUA_TNUMBER); + CheckMsg(L); + g_Msg.WriteChar(lua_tonumber(L,1)); + return 0; +} + +DECLARE_FUNCTION(_G,_WRITE_SHORT) +{ + luaL_checktype(L,1,LUA_TNUMBER); + CheckMsg(L); + g_Msg.WriteShort(lua_tonumber(L,1)); + return 0; +} + +DECLARE_FUNCTION(_G,_WRITE_WORD) +{ + luaL_checktype(L,1,LUA_TNUMBER); + CheckMsg(L); + g_Msg.WriteWord(lua_tonumber(L,1)); + return 0; +} + +DECLARE_FUNCTION(_G,_WRITE_LONG) +{ + luaL_checktype(L,1,LUA_TNUMBER); + CheckMsg(L); + g_Msg.WriteLong(lua_tonumber(L,1)); + return 0; +} + +DECLARE_FUNCTION(_G,_WRITE_FLOAT) +{ + luaL_checktype(L,1,LUA_TNUMBER); + CheckMsg(L); + g_Msg.WriteFloat(lua_tonumber(L,1)); + return 0; +} + +DECLARE_FUNCTION(_G,_WRITE_ANGLE) +{ + luaL_checktype(L,1,LUA_TNUMBER); + CheckMsg(L); + g_Msg.WriteBitAngle(lua_tonumber(L,1),8); + return 0; +} + +DECLARE_FUNCTION(_G,_WRITE_COORD) +{ + luaL_checktype(L,1,LUA_TNUMBER); + CheckMsg(L); + g_Msg.WriteBitCoord(lua_tonumber(L,1)); + return 0; +} + +DECLARE_FUNCTION(_G,_WRITE_VEC3COORD) +{ + luaL_checkudata(L,1,"vector3"); + CheckMsg(L); + g_Msg.WriteBitVec3Coord(*(Vector*)lua_touserdata(L,1)); + return 0; +} + +DECLARE_FUNCTION(_G,_WRITE_VEC3NORMAL) +{ + luaL_checkudata(L,1,"vector3"); + CheckMsg(L); + g_Msg.WriteBitVec3Normal(*(Vector*)lua_touserdata(L,1)); + return 0; +} + +DECLARE_FUNCTION(_G,_WRITE_ANGLES) +{ + luaL_checkudata(L,1,"vector3"); + CheckMsg(L); + g_Msg.WriteBitVec3Coord(*(Vector*)lua_touserdata(L,1)); + return 0; +} + +DECLARE_FUNCTION(_G,_WRITE_STRING) +{ + luaL_checktype(L,1,LUA_TSTRING); + CheckMsg(L); + g_Msg.WriteString(lua_tostring(L,1)); + return 0; +} + +DECLARE_FUNCTION(_G,_WRITE_ENTITY) +{ + luaL_checktype(L,1,LUA_TNUMBER); + CheckMsg(L); + g_Msg.WriteWord(lua_tonumber(L,1)); + return 0; +} + +DECLARE_FUNCTION(_G,_WRITE_EHANDLE) +{ + luaL_checktype(L,1,LUA_TNUMBER); + CheckMsg(L); + edict_t* pEnt; + if(!(pEnt = engine->PEntityOfEntIndex(lua_tonumber(L,1)))) + return luaL_error(L,"Wrong entity!"); + + int iSerialNum = pEnt->m_NetworkSerialNumber&0x3FF; //Round to 10 bits + g_Msg.WriteLong((iSerialNum<<11)&(int)lua_tonumber(L,1)); + return 0; +} + +DECLARE_FUNCTION(_G,_WRITE_BOOL) +{ + luaL_checktype(L,1,LUA_TBOOLEAN); + CheckMsg(L); + g_Msg.WriteOneBit(!!lua_toboolean(L,1)); + return 0; +} + +DECLARE_FUNCTION(_G,_WRITE_UBITLONG) +{ + luaL_checktype(L,1,LUA_TNUMBER); + luaL_checktype(L,2,LUA_TNUMBER); + CheckMsg(L); + g_Msg.WriteUBitLong((unsigned int)lua_tonumber(L,1), + (int)lua_tonumber(L,2)); + return 0; +} + +DECLARE_FUNCTION(_G,_WRITE_SBITLONG) +{ + luaL_checktype(L,1,LUA_TNUMBER); + luaL_checktype(L,2,LUA_TNUMBER); + CheckMsg(L); + g_Msg.WriteSBitLong((int)lua_tonumber(L,1), + (int)lua_tonumber(L,2)); + return 0; +} + +DECLARE_FUNCTION(_G,_WRITE_BITS) +{ + luaL_checktype(L,1,LUA_TSTRING); + luaL_checktype(L,2,LUA_TNUMBER); + CheckMsg(L); + const char* pBuf = lua_tostring(L,1); + g_Msg.WriteBits(pBuf,lua_tonumber(L,2)); + return 0; +} \ No newline at end of file diff --git a/lua/sdk_net/netmessage.h b/lua/sdk_net/netmessage.h new file mode 100644 index 0000000..779d8c0 --- /dev/null +++ b/lua/sdk_net/netmessage.h @@ -0,0 +1,28 @@ +#ifndef __NETMESSAGE_H +#define __NETMESSAGE_H + +#include "inetmessage.h" +#include "inetchannelinfo.h" + +class CNetMessage : public INetMessage +{ +public: + virtual void SetNetChannel(INetChannel* pChan){m_pChan = pChan;} + virtual void SetReliable(bool m_bR){m_bReliable=m_bR;} + virtual bool Process(){return true;} + virtual bool ReadFromBuffer(bf_read&){return true;} + virtual bool WriteToBuffer(bf_write&){return true;} + virtual bool IsReliable() const {return m_bReliable;} + + virtual int GetType() const {return 0;} + virtual int GetGroup() const {return 0;} + virtual const char* GetName() const {return "";} + virtual INetChannel* GetNetChannel() const {return m_pChan;} + virtual const char* ToString() const {return "";} + +private: + bool m_bReliable; + INetChannel* m_pChan; +}; + +#endif \ No newline at end of file diff --git a/lua/sdk_net/protocol.h b/lua/sdk_net/protocol.h new file mode 100644 index 0000000..435deda --- /dev/null +++ b/lua/sdk_net/protocol.h @@ -0,0 +1,36 @@ +#ifndef __PROTOCOL_H +#define __PROTOCOL_H + +#define net_NOP 0 // nop command used for padding +#define net_Disconnect 1 // disconnect, last message in connection +#define net_File 2 // file transmission message request/deny +#define net_Tick 3 // send last world tick +#define net_StringCmd 4 // a string command +#define net_SetConVar 5 // sends one/multiple convar settings +#define net_SignonState 6 // signals current signon state +#define svc_Print 7 // print text to console +#define svc_ServerInfo 8 // first message from server about game, map etc +#define svc_SendTable 9 // sends a sendtable description for a game class +#define svc_ClassInfo 10 // Info about classes (first byte is a CLASSINFO_ define). +#define svc_SetPause 11 // tells client if server paused or unpaused +#define svc_CreateStringTable 12 // inits shared string tables +#define svc_UpdateStringTable 13 // updates a string table +#define svc_VoiceInit 14 // inits used voice codecs & quality +#define svc_VoiceData 15 // Voicestream data from the server +#define svc_Sounds 17 // starts playing sound +#define svc_SetView 18 // sets entity as point of view +#define svc_FixAngle 19 // sets/corrects players viewangle +#define svc_CrosshairAngle 20 // adjusts crosshair in auto aim mode to lock on traget +#define svc_BSPDecal 21 // add a static decal to the worl BSP +#define svc_UserMessage 23 // a game specific message +#define svc_EntityMessage 24 // a message for an entity +#define svc_GameEvent 25 // global game event fired +#define svc_PacketEntities 26 // non-delta compressed entities +#define svc_TempEntities 27 // non-reliable event object +#define svc_Prefetch 28 // only sound indices for now +#define svc_Menu 29 // display a menu from a plugin +#define svc_GameEventList 30 // list of known games events and fields +#define svc_GetCvarValue 31 // Server wants to know the value of a cvar on the client. +#define SVC_LASTMSG 31 // last known server messages + +#endif \ No newline at end of file diff --git a/lua/sdk_net/sdk_net.vcxproj b/lua/sdk_net/sdk_net.vcxproj new file mode 100644 index 0000000..12ff01a --- /dev/null +++ b/lua/sdk_net/sdk_net.vcxproj @@ -0,0 +1,79 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {D39138E1-F689-4256-B237-33F989464123} + sdk_net + + + + Application + true + MultiByte + + + DynamicLibrary + false + true + MultiByte + + + + + + + + + + + + + ..\..\..\GMod9Dev_Server\gmod9\lua\bin + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + true + true + D:\source2006\public\tier1;D:\source2006\public\tier0;D:\source2006\game_shared;D:\source2006\common;D:\source2006\dlls;D:\source2006\public;D:\lua502\lua\lua502_sdk;%(AdditionalIncludeDirectories) + + + true + true + true + D:\source2006\lib\public;D:\lua502\lua\Release;%(AdditionalLibraryDirectories) + lua502_sdk.lib;vstdlib.lib;tier0.lib;tier1.lib;%(AdditionalDependencies) + LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) + /FORCE:MULTIPLE %(AdditionalOptions) + + + + + + + + + + + + + \ No newline at end of file diff --git a/lua/sdk_net/sdk_net.vcxproj.filters b/lua/sdk_net/sdk_net.vcxproj.filters new file mode 100644 index 0000000..5d51101 --- /dev/null +++ b/lua/sdk_net/sdk_net.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Файлы иÑходного кода + + + + + Заголовочные файлы + + + Заголовочные файлы + + + \ No newline at end of file diff --git a/lua/sdk_net/sdk_net.vcxproj.user b/lua/sdk_net/sdk_net.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/lua/sdk_net/sdk_net.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lua/sdk_ppcore/Release/CL.read.1.tlog b/lua/sdk_ppcore/Release/CL.read.1.tlog new file mode 100644 index 0000000..0adae25 Binary files /dev/null and b/lua/sdk_ppcore/Release/CL.read.1.tlog differ diff --git a/lua/sdk_ppcore/Release/CL.write.1.tlog b/lua/sdk_ppcore/Release/CL.write.1.tlog new file mode 100644 index 0000000..ab635de Binary files /dev/null and b/lua/sdk_ppcore/Release/CL.write.1.tlog differ diff --git a/lua/sdk_ppcore/Release/cl.command.1.tlog b/lua/sdk_ppcore/Release/cl.command.1.tlog new file mode 100644 index 0000000..3ccbf09 Binary files /dev/null and b/lua/sdk_ppcore/Release/cl.command.1.tlog differ diff --git a/lua/sdk_ppcore/Release/link.command.1.tlog b/lua/sdk_ppcore/Release/link.command.1.tlog new file mode 100644 index 0000000..3153227 Binary files /dev/null and b/lua/sdk_ppcore/Release/link.command.1.tlog differ diff --git a/lua/sdk_ppcore/Release/link.read.1.tlog b/lua/sdk_ppcore/Release/link.read.1.tlog new file mode 100644 index 0000000..5876945 Binary files /dev/null and b/lua/sdk_ppcore/Release/link.read.1.tlog differ diff --git a/lua/sdk_ppcore/Release/link.write.1.tlog b/lua/sdk_ppcore/Release/link.write.1.tlog new file mode 100644 index 0000000..da02f70 Binary files /dev/null and b/lua/sdk_ppcore/Release/link.write.1.tlog differ diff --git a/lua/sdk_ppcore/Release/main.obj b/lua/sdk_ppcore/Release/main.obj new file mode 100644 index 0000000..5c8b9e6 Binary files /dev/null and b/lua/sdk_ppcore/Release/main.obj differ diff --git a/lua/sdk_ppcore/Release/mt.command.1.tlog b/lua/sdk_ppcore/Release/mt.command.1.tlog new file mode 100644 index 0000000..02a22d0 Binary files /dev/null and b/lua/sdk_ppcore/Release/mt.command.1.tlog differ diff --git a/lua/sdk_ppcore/Release/mt.read.1.tlog b/lua/sdk_ppcore/Release/mt.read.1.tlog new file mode 100644 index 0000000..9654e42 Binary files /dev/null and b/lua/sdk_ppcore/Release/mt.read.1.tlog differ diff --git a/lua/sdk_ppcore/Release/mt.write.1.tlog b/lua/sdk_ppcore/Release/mt.write.1.tlog new file mode 100644 index 0000000..984cde9 Binary files /dev/null and b/lua/sdk_ppcore/Release/mt.write.1.tlog differ diff --git a/lua/sdk_ppcore/Release/pplib.obj b/lua/sdk_ppcore/Release/pplib.obj new file mode 100644 index 0000000..f38e9f2 Binary files /dev/null and b/lua/sdk_ppcore/Release/pplib.obj differ diff --git a/lua/sdk_ppcore/Release/sdk_ppcore.Build.CppClean.log b/lua/sdk_ppcore/Release/sdk_ppcore.Build.CppClean.log new file mode 100644 index 0000000..4bc7838 --- /dev/null +++ b/lua/sdk_ppcore/Release/sdk_ppcore.Build.CppClean.log @@ -0,0 +1,20 @@ +..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.pdb +D:\GMOD9DEV_SERVER\GMOD9\LUA\BIN\SDK_PPCORE.DLL +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.lib +D:\GMOD9DEV_SERVER\GMOD9\LUA\BIN\SDK_PPCORE.PDB +D:\lua502\lua\sdk_ppcore\..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.dll +D:\lua502\lua\sdk_ppcore\Release\cl.command.1.tlog +D:\lua502\lua\sdk_ppcore\Release\CL.read.1.tlog +D:\lua502\lua\sdk_ppcore\Release\CL.write.1.tlog +D:\lua502\lua\sdk_ppcore\Release\link.command.1.tlog +D:\lua502\lua\sdk_ppcore\Release\link.read.1.tlog +D:\lua502\lua\sdk_ppcore\Release\link.write.1.tlog +D:\LUA502\LUA\SDK_PPCORE\RELEASE\MAIN.OBJ +D:\lua502\lua\sdk_ppcore\Release\mt.command.1.tlog +D:\lua502\lua\sdk_ppcore\Release\mt.read.1.tlog +D:\lua502\lua\sdk_ppcore\Release\mt.write.1.tlog +D:\LUA502\LUA\SDK_PPCORE\RELEASE\PPLIB.OBJ +D:\LUA502\LUA\SDK_PPCORE\RELEASE\SDK_PPCORE.DLL.INTERMEDIATE.MANIFEST +D:\lua502\lua\sdk_ppcore\Release\sdk_ppcore.write.1.tlog +D:\LUA502\LUA\SDK_PPCORE\RELEASE\VC100.PDB diff --git a/lua/sdk_ppcore/Release/sdk_ppcore.dll.intermediate.manifest b/lua/sdk_ppcore/Release/sdk_ppcore.dll.intermediate.manifest new file mode 100644 index 0000000..ecea6f7 --- /dev/null +++ b/lua/sdk_ppcore/Release/sdk_ppcore.dll.intermediate.manifest @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/lua/sdk_ppcore/Release/sdk_ppcore.lastbuildstate b/lua/sdk_ppcore/Release/sdk_ppcore.lastbuildstate new file mode 100644 index 0000000..c2d4a05 --- /dev/null +++ b/lua/sdk_ppcore/Release/sdk_ppcore.lastbuildstate @@ -0,0 +1,2 @@ +#v4.0:v100:false +Release|Win32|D:\lua502\lua\| diff --git a/lua/sdk_ppcore/Release/sdk_ppcore.log b/lua/sdk_ppcore/Release/sdk_ppcore.log new file mode 100644 index 0000000..b12c2b0 --- /dev/null +++ b/lua/sdk_ppcore/Release/sdk_ppcore.log @@ -0,0 +1,32 @@ +Build started 28.06.2018 3:21:58. + 1>Project "D:\lua502\lua\sdk_ppcore\sdk_ppcore.vcxproj" on node 2 (build target(s)). + 1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppBuild.targets(299,5): warning MSB8004: каталог Output заканчиваетÑÑ Ð½Ðµ коÑой чертой. Этот ÑкземплÑÑ€ поÑÑ‚Ñ€Ð¾ÐµÐ½Ð¸Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ‚ коÑую черту, поÑкольку она необходима Ð´Ð»Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ð¾Ð³Ð¾ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð° Output. + 1>InitializeBuildStatus: + Creating "Release\sdk_ppcore.unsuccessfulbuild" because "AlwaysCreate" was specified. + ClCompile: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\CL.exe /c /ID:\source2006\public\dlls /ID:\source2006\dlls\hl2_dll /ID:\source2006\game_shared\hl2 /ID:\source2006\game_shared\hl2mp /ID:\source2006\game_shared /ID:\source2006\dlls /ID:\source2006\public\tier1 /ID:\source2006\public\tier0 /ID:\source2006\public /ID:\source2006\common /ID:\lua502\lua\lua502_sdk /Zi /nologo /W3 /WX- /O2 /Oi /Oy- /GL /D _WINDLL /D _MBCS /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Release\\" /Fd"Release\vc100.pdb" /Gd /TP /analyze- /errorReport:prompt main.cpp pplib.cpp + main.cpp + pplib.cpp + Link: + C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:"..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.dll" /NOLOGO /LIBPATH:D:\source2006\lib\public /LIBPATH:D:\lua502\lua\Release lua502_sdk.lib vstdlib.lib tier0.lib tier1.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NODEFAULTLIB:LIBCMT.lib /MANIFEST /ManifestFile:"Release\sdk_ppcore.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"D:\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.pdb" /OPT:REF /OPT:ICF /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.lib" /MACHINE:X86 /DLL Release\main.obj + Release\pplib.obj /FORCE:MULTIPLE + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: __malloc_crt уже определен в tier1.lib(memoverride.obj); второе определение пропущено + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: _free уже определен в tier1.lib(memoverride.obj); второе определение пропущено + СоздаетÑÑ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ° ..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.lib и объект ..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.exp + 1>..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.dll : warning LNK4088: образ ÑоздаетÑÑ Ð¸Ð·-за параметра /FORCE; образ Ð½ÐµÐ»ÑŒÐ·Ñ Ð·Ð°Ð¿ÑƒÑтить + Создание кода + Создание кода завершено + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: __malloc_crt уже определен в tier1.lib(memoverride.obj); второе определение пропущено + 1>MSVCRT.lib(MSVCR100.dll) : warning LNK4006: _free уже определен в tier1.lib(memoverride.obj); второе определение пропущено + 1>..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.dll : warning LNK4088: образ ÑоздаетÑÑ Ð¸Ð·-за параметра /FORCE; образ Ð½ÐµÐ»ÑŒÐ·Ñ Ð·Ð°Ð¿ÑƒÑтить + sdk_ppcore.vcxproj -> D:\lua502\lua\sdk_ppcore\..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.dll + Manifest: + C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe /nologo /verbose /outputresource:"..\..\..\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.dll;#2" /manifest Release\sdk_ppcore.dll.intermediate.manifest + FinalizeBuildStatus: + Deleting file "Release\sdk_ppcore.unsuccessfulbuild". + Touching "Release\sdk_ppcore.lastbuildstate". + 1>Done Building Project "D:\lua502\lua\sdk_ppcore\sdk_ppcore.vcxproj" (build target(s)). + +ПоÑтроение уÑпешно завершено. + +Time Elapsed 00:00:02.41 diff --git a/lua/sdk_ppcore/Release/sdk_ppcore.write.1.tlog b/lua/sdk_ppcore/Release/sdk_ppcore.write.1.tlog new file mode 100644 index 0000000..23c8a0e --- /dev/null +++ b/lua/sdk_ppcore/Release/sdk_ppcore.write.1.tlog @@ -0,0 +1,20 @@ +^D:\lua502\lua\sdk_ppcore\sdk_ppcore.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.exp +^D:\lua502\lua\sdk_ppcore\sdk_ppcore.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.exp +^D:\lua502\lua\sdk_ppcore\sdk_ppcore.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.exp +^D:\lua502\lua\sdk_ppcore\sdk_ppcore.vcxproj +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.lib +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.exp +D:\GMod9Dev_Server\gmod9\lua\bin\sdk_ppcore.exp diff --git a/lua/sdk_ppcore/Release/vc100.pdb b/lua/sdk_ppcore/Release/vc100.pdb new file mode 100644 index 0000000..db8f510 Binary files /dev/null and b/lua/sdk_ppcore/Release/vc100.pdb differ diff --git a/lua/sdk_ppcore/main.cpp b/lua/sdk_ppcore/main.cpp new file mode 100644 index 0000000..746e413 --- /dev/null +++ b/lua/sdk_ppcore/main.cpp @@ -0,0 +1,120 @@ +#define GAME_DLL +#include "plugin.h" +#include "tier1.h" +#include "eiface.h" +#include "baselib.h" +#include "cbase.h" +#include "pplib.h" +#include "main.h" + +DECLARE_PLUGIN(CSDKPPCore) + virtual bool Load(CreateInterfaceFn,CreateInterfaceFn); + virtual void Unload(); + + virtual void LevelShutdown(); + virtual void ClientActive(edict_t*); + virtual void ClientDisconnect(edict_t*); + + virtual bool LuaInit(lua_State*); + virtual void OnSWEPLuaCreate(lua_State* L); + + CUtlVector m_Objects; +END_PLUGIN(CSDKPPCore,"sdk_ppcore"); + +IVEngineServer* engine; + +inline uint32 ToAccountId(const char* pSteamId) +{ + uint32 account; + sscanf(pSteamId,"STEAM_%*d:%*d:%d",&account); + return account; +} + +DLL_EXPORT int GetObjectOwner(EHANDLE hObject) +{ + for(int i = 0; i < s_CSDKPPCore.m_Objects.Count(); i++) + { + object_t obj = s_CSDKPPCore.m_Objects[i]; + if(obj.m_hEntity.GetEntryIndex() == hObject.GetEntryIndex()) + return obj.m_iAccount; + } + return 0; +} + +DLL_EXPORT int GetPlayerAccountId(edict_t* pPly) +{ + return ToAccountId(engine->GetPlayerNetworkIDString(pPly)); +} + +DLL_EXPORT CUtlVector* GetAllObjects() +{ + return &s_CSDKPPCore.m_Objects; +} + +bool CSDKPPCore::Load(CreateInterfaceFn engineFn,CreateInterfaceFn gameFn) +{ + ConnectTier1Libraries(&engineFn,1); + if(!(engine = (IVEngineServer*)engineFn(INTERFACEVERSION_VENGINESERVER,0))) + return false; + return true; +} + +void CSDKPPCore::OnSWEPLuaCreate(lua_State* L) +{ +} + +void CSDKPPCore::Unload() +{ + DisconnectTier1Libraries(); +} + +void CSDKPPCore::LevelShutdown() +{ + m_Objects.RemoveAll(); +} + +void CSDKPPCore::ClientActive(edict_t* pPly) +{ + int account = GetPlayerAccountId(pPly); + for(int i = 0; i < m_Objects.Count();) + { + object_t obj = m_Objects[i]; + if(!INDEXENT(obj.m_hEntity.GetEntryIndex())) + { + m_Objects.Remove(i); + continue; + } + else if(obj.m_iAccount == account) + { + GetProperty(pPly,obj.m_iType) + ->AddToTail(obj.m_hEntity); + } + i++; + } +} + +void CSDKPPCore::ClientDisconnect(edict_t* pPly) +{ + object_t obj; + obj.m_iAccount = GetPlayerAccountId(pPly); + for(int i = 0; i < MaxType; i++) + { + obj.m_iType = i; + EntityVector_t* pEnts = GetProperty(pPly,i); + for(int j = 0; j < pEnts->Count(); j++) + { + EHANDLE hnd = pEnts->Element(j); + if(INDEXENT(hnd.GetEntryIndex())) + { + obj.m_hEntity = hnd; + m_Objects.AddToTail(obj); + } + } + } +} + +bool CSDKPPCore::LuaInit(lua_State* L) +{ + CLuaLibrary::Init(L); + return true; +} \ No newline at end of file diff --git a/lua/sdk_ppcore/main.h b/lua/sdk_ppcore/main.h new file mode 100644 index 0000000..1625d2e --- /dev/null +++ b/lua/sdk_ppcore/main.h @@ -0,0 +1,17 @@ +#ifndef __MAIN_H +#define __MAIN_H + +#define GAME_DLL +#include "cbase.h" + +typedef struct { + int m_iAccount; + int m_iType; + EHANDLE m_hEntity; +} object_t; + +DLL_EXPORT int GetObjectOwner(EHANDLE hObject); +DLL_EXPORT int GetPlayerAccountId(edict_t* pPly); +DLL_EXPORT CUtlVector* GetAllObjects(); + +#endif \ No newline at end of file diff --git a/lua/sdk_ppcore/pplib.cpp b/lua/sdk_ppcore/pplib.cpp new file mode 100644 index 0000000..a7ee5e1 --- /dev/null +++ b/lua/sdk_ppcore/pplib.cpp @@ -0,0 +1,188 @@ +#define GAME_DLL +#include "cbase.h" +#include "baselib.h" +#include "hl2mp_dll/hl2mp_player.h" +#include "hl2mp/hl2mp_player_shared.h" +#include "basehandle.h" +#include "pplib.h" +#include "main.h" + +DECLARE_LIBRARY("pp"); +DECLARE_TABLE(pp); + +static int s_iOffsets[] = { + 0x1094, + 0x10AC, + 0x10C4, + 0x10F4, + 0x10DC, + 0x110C, + 0x1124, + 0x113C, + 0x1154, + 0x107C, +}; + +DLL_EXPORT EntityVector_t* GetProperty(edict_t* pEdict,int iType) +{ + CBaseEntity* pPly; + if(!(pPly = GetContainingEntity(pEdict))) + return NULL; + return (EntityVector_t*)((char*)pPly+s_iOffsets[iType]); +} + +DLL_EXPORT void FixupProperty(EntityVector_t* pProperty) +{ + for(int i = 0; i < pProperty->Count();) + { + if(!INDEXENT(pProperty->Element(i).GetEntryIndex())) + pProperty->Remove(i); + else i++; + } +} + +inline CBaseEntity* ToEntity(lua_State* L,int idx = 1) +{ + int iEnt = lua_tonumber(L,idx); + CBaseEntity* pPly; + edict_t* pEdict; + if(!(pEdict = INDEXENT(iEnt))) + return NULL; + if(!(pPly = GetContainingEntity(pEdict))) + return NULL; + //if(!pPly->IsPlayer()) return NULL; + return pPly; +} + +#define DECLARE_OBJECT(type) \ +DECLARE_FUNCTION(pp,Get##type) \ +{ \ + lua_newtable(L); \ + CBaseEntity* pPly; \ + if(!(pPly = ToEntity(L))) \ + return 1; \ + CUtlVector* pVec \ + = (CUtlVector*)((char*)pPly+s_iOffsets[type]); \ + for(int i = 0; i < pVec->Count();) \ + { \ + int iEnt = pVec->Element(i).GetEntryIndex(); \ + if(INDEXENT(iEnt)) \ + { \ + lua_pushnumber(L,iEnt); \ + lua_rawseti(L,-2,i++ + 1); \ + } \ + else pVec->Remove(i); \ + } \ + return 1; \ +} \ +DECLARE_FUNCTION(pp,Add##type) \ +{ \ + CBaseEntity* pPly,*pEnt; \ + if(!(pPly = ToEntity(L))) \ + return 0; \ + if(!(pEnt = ToEntity(L,2))) \ + return 0; \ + CUtlVector* pVec \ + = (CUtlVector*) \ + ((char*)pPly+s_iOffsets[type]); \ + pVec->AddToTail(EHANDLE(pEnt)); \ + return 0; \ +} + +//enum { +// Ragdolls, +// Props, +// Balloons, +// Effects, +// Sprites, +// Emitters, +// Wheels, +// Npcs, +// Dynamites, +// Thrusters +//}; + +DECLARE_OBJECT(Ragdolls) +DECLARE_OBJECT(Props) +DECLARE_OBJECT(Balloons) +DECLARE_OBJECT(Effects) +DECLARE_OBJECT(Sprites) +DECLARE_OBJECT(Emitters) +DECLARE_OBJECT(Wheels) +DECLARE_OBJECT(Npcs) +DECLARE_OBJECT(Dynamites) +DECLARE_OBJECT(Thrusters) + +DECLARE_FUNCTION(pp,GetObjectAccount) +{ + luaL_checktype(L,1,LUA_TNUMBER); + + int idx = lua_tonumber(L,1); + if(!INDEXENT(idx)) + lua_pushnumber(L,0); + else + { + lua_pushnumber(L,GetObjectOwner( + EHANDLE::FromIndex(idx))); + } + return 1; +} + +DECLARE_FUNCTION(pp,GetPlayerAccountid) +{ + luaL_checktype(L,1,LUA_TNUMBER); + edict_t* pPly; + if(!(pPly = INDEXENT(lua_tonumber(L,1)))) + lua_pushnumber(L,0); + else + lua_pushnumber(L,GetPlayerAccountId(pPly)); + return 1; +} + +//DLL_EXPORT CUtlVector* GetAllObjects(); +DECLARE_FUNCTION(pp,GetAccountObjects) +{ + luaL_checktype(L,1,LUA_TNUMBER); + luaL_checktype(L,2,LUA_TNUMBER); + lua_newtable(L); + int iAcc = lua_tonumber(L,1); + int iType = lua_tonumber(L,2); + if(iType >= MaxType) return 1; + CUtlVector* pObjs = GetAllObjects(); + int idx = 1; + for(int i = 0; i < pObjs->Count(); i++) + { + object_t obj = pObjs->Element(i); + if(obj.m_iAccount == iAcc + && obj.m_iType == iType) + { + lua_pushnumber(L,obj.m_hEntity.GetEntryIndex()); + lua_rawseti(L,-2,idx++); + } + } + return 1; +} + +DECLARE_FUNCTION(pp,GetPlayerObjects) +{ + luaL_checktype(L,1,LUA_TNUMBER); + luaL_checktype(L,2,LUA_TNUMBER); + lua_newtable(L); + edict_t* pEdict; + int iType = lua_tonumber(L,2); + if(iType >= MaxType) return 1; + if(!(pEdict = INDEXENT(lua_tonumber(L,1)))) + return 1; + int idx = 1; + EntityVector_t* pEnts = GetProperty(pEdict,iType); + for(int i = 0; i < pEnts->Count(); i++) + { + int iEnt = pEnts->Element(i).GetEntryIndex(); + if(INDEXENT(iEnt)) + { + lua_pushnumber(L,iEnt); + lua_rawseti(L,-2,idx++); + } + } + return 1; +} \ No newline at end of file diff --git a/lua/sdk_ppcore/pplib.h b/lua/sdk_ppcore/pplib.h new file mode 100644 index 0000000..31beef5 --- /dev/null +++ b/lua/sdk_ppcore/pplib.h @@ -0,0 +1,25 @@ +#ifndef __PPLIB_H +#define __PPLIB_H + +#define GAME_DLL +#include "cbase.h" +typedef CUtlVector EntityVector_t; + +enum { + Ragdolls = 0, + Props, + Balloons, + Effects, + Sprites, + Emitters, + Wheels, + Npcs, + Dynamites, + Thrusters, + MaxType, +}; + +DLL_EXPORT EntityVector_t* GetProperty(edict_t* pPly,int iType); +DLL_EXPORT void FixupProperty(EntityVector_t* pProperty); + +#endif \ No newline at end of file diff --git a/lua/sdk_ppcore/sdk_ppcore.vcxproj b/lua/sdk_ppcore/sdk_ppcore.vcxproj new file mode 100644 index 0000000..fdc2660 --- /dev/null +++ b/lua/sdk_ppcore/sdk_ppcore.vcxproj @@ -0,0 +1,80 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {40CB1037-BD7E-45A4-AB78-33C5E981893C} + sdk_ppcore + + + + Application + true + MultiByte + + + DynamicLibrary + false + true + MultiByte + + + + + + + + + + + + + ..\..\..\GMod9Dev_Server\gmod9\lua\bin + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + true + true + D:\source2006\public\dlls;D:\source2006\dlls\hl2_dll;D:\source2006\game_shared\hl2;D:\source2006\game_shared\hl2mp;D:\source2006\game_shared;D:\source2006\dlls;D:\source2006\public\tier1;D:\source2006\public\tier0;D:\source2006\public;D:\source2006\common;D:\lua502\lua\lua502_sdk;%(AdditionalIncludeDirectories) + + + true + true + true + D:\source2006\lib\public;D:\lua502\lua\Release;%(AdditionalLibraryDirectories) + lua502_sdk.lib;vstdlib.lib;tier0.lib;tier1.lib;%(AdditionalDependencies) + LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) + /FORCE:MULTIPLE %(AdditionalOptions) + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lua/sdk_ppcore/sdk_ppcore.vcxproj.filters b/lua/sdk_ppcore/sdk_ppcore.vcxproj.filters new file mode 100644 index 0000000..fb44680 --- /dev/null +++ b/lua/sdk_ppcore/sdk_ppcore.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + + + Заголовочные файлы + + + Заголовочные файлы + + + \ No newline at end of file diff --git a/lua/sdk_ppcore/sdk_ppcore.vcxproj.user b/lua/sdk_ppcore/sdk_ppcore.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/lua/sdk_ppcore/sdk_ppcore.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lua/sv_a2s_fix b/lua/sv_a2s_fix new file mode 160000 index 0000000..29dbcd1 --- /dev/null +++ b/lua/sv_a2s_fix @@ -0,0 +1 @@ +Subproject commit 29dbcd1a1ea4bd2bf0b4f74f21d2d5d73166193b diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..bf64c03 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,85 @@ +# makefile for Lua core library + +LUA= .. + +include $(LUA)/config + +OBJS= \ + lapi.o \ + lcode.o \ + ldebug.o \ + ldo.o \ + ldump.o \ + lfunc.o \ + lgc.o \ + llex.o \ + lmem.o \ + lobject.o \ + lopcodes.o \ + lparser.o \ + lstate.o \ + lstring.o \ + ltable.o \ + ltests.o \ + ltm.o \ + lundump.o \ + lvm.o \ + lzio.o + +SRCS= \ + lapi.c \ + lcode.c \ + ldebug.c \ + ldo.c \ + ldump.c \ + lfunc.c \ + lgc.c \ + llex.c \ + lmem.c \ + lobject.c \ + lopcodes.c \ + lparser.c \ + lstate.c \ + lstring.c \ + ltable.c \ + ltests.c \ + ltm.c \ + lundump.c \ + lvm.c \ + lzio.c \ + lapi.h \ + lcode.h \ + ldebug.h \ + ldo.h \ + lfunc.h \ + lgc.h \ + llex.h \ + llimits.h \ + lmem.h \ + lobject.h \ + lopcodes.h \ + lparser.h \ + lstate.h \ + lstring.h \ + ltable.h \ + ltm.h \ + lundump.h \ + lvm.h \ + lzio.h + +T= $(LIB)/liblua.a + +all: $T + +$T: $(OBJS) + $(AR) $@ $(OBJS) + $(RANLIB) $@ + +clean: + rm -f $(OBJS) $T + +co: + co -q -f -M $(SRCS) + +klean: clean + rm -f $(SRCS) diff --git a/src/README b/src/README new file mode 100644 index 0000000..e537598 --- /dev/null +++ b/src/README @@ -0,0 +1,5 @@ +This is the Lua core. + +The standard Lua library are in lib/. +A sample interpreter is in lua/. +A standalone compiler is in luac/. diff --git a/src/lapi.cpp b/src/lapi.cpp new file mode 100644 index 0000000..d5dd9ca --- /dev/null +++ b/src/lapi.cpp @@ -0,0 +1,922 @@ +/* +** $Id: lapi.c,v 1.235 2003/04/07 14:36:08 roberto Exp $ +** Lua API +** See Copyright Notice in lua.h +*/ + + +#include +#include + +#define lapi_c + +#include "lua.h" + +#include "lapi.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lundump.h" +#include "lvm.h" + + +const char lua_ident[] = + "$Lua: " LUA_VERSION " " LUA_COPYRIGHT " $\n" + "$Authors: " LUA_AUTHORS " $\n" + "$URL: www.lua.org $\n"; + + + +#ifndef api_check +#define api_check(L, o) /*{ assert(o); }*/ +#endif + +#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) + +#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} + + + + +static TObject *negindex (lua_State *L, int idx) { + 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_GLOBALSINDEX: return gt(L); + default: { + TObject *func = (L->base - 1); + idx = LUA_GLOBALSINDEX - idx; + lua_assert(iscfunction(func)); + return (idx <= clvalue(func)->c.nupvalues) + ? &clvalue(func)->c.upvalue[idx-1] + : NULL; + } + } +} + + +static TObject *luaA_index (lua_State *L, int idx) { + if (idx > 0) { + api_check(L, idx <= L->top - L->base); + return L->base + idx - 1; + } + else { + TObject *o = negindex(L, idx); + api_check(L, o != NULL); + return o; + } +} + + +static TObject *luaA_indexAcceptable (lua_State *L, int idx) { + if (idx > 0) { + TObject *o = L->base+(idx-1); + api_check(L, idx <= L->stack_last - L->base); + if (o >= L->top) return NULL; + else return o; + } + else + return negindex(L, idx); +} + + +void luaA_pushobject (lua_State *L, const TObject *o) { + setobj2s(L->top, o); + incr_top(L); +} + + +LUA_API int lua_checkstack (lua_State *L, int size) { + int res; + lua_lock(L); + if ((L->top - L->base + size) > LUA_MAXCSTACK) + res = 0; /* stack overflow */ + else { + luaD_checkstack(L, size); + if (L->ci->top < L->top + size) + L->ci->top = L->top + size; + res = 1; + } + lua_unlock(L); + return res; +} + + +LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { + int i; + lua_lock(to); + api_checknelems(from, n); + from->top -= n; + for (i = 0; i < n; i++) { + setobj2s(to->top, from->top + i); + api_incr_top(to); + } + lua_unlock(to); +} + + +LUA_API 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; +} + + +LUA_API lua_State *lua_newthread (lua_State *L) { + lua_State *L1; + lua_lock(L); + luaC_checkGC(L); + L1 = luaE_newthread(L); + setthvalue(L->top, L1); + api_incr_top(L); + lua_unlock(L); + lua_userstateopen(L1); + return L1; +} + + + +/* +** basic stack manipulation +*/ + + +LUA_API int lua_gettop (lua_State *L) { + return (L->top - L->base); +} + + +LUA_API 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(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); +} + + +LUA_API void lua_remove (lua_State *L, int idx) { + StkId p; + lua_lock(L); + p = luaA_index(L, idx); + while (++p < L->top) setobjs2s(p-1, p); + L->top--; + lua_unlock(L); +} + + +LUA_API void lua_insert (lua_State *L, int idx) { + StkId p; + StkId q; + lua_lock(L); + p = luaA_index(L, idx); + for (q = L->top; q>p; q--) setobjs2s(q, q-1); + setobjs2s(p, L->top); + lua_unlock(L); +} + + +LUA_API void lua_replace (lua_State *L, int idx) { + lua_lock(L); + api_checknelems(L, 1); + setobj(luaA_index(L, idx), L->top - 1); /* write barrier */ + L->top--; + lua_unlock(L); +} + + +LUA_API void lua_pushvalue (lua_State *L, int idx) { + lua_lock(L); + setobj2s(L->top, luaA_index(L, idx)); + api_incr_top(L); + lua_unlock(L); +} + + + +/* +** access functions (stack -> C) +*/ + + +LUA_API int lua_type (lua_State *L, int idx) { + StkId o = luaA_indexAcceptable(L, idx); + return (o == NULL) ? LUA_TNONE : ttype(o); +} + + +LUA_API const char *lua_typename (lua_State *L, int t) { + UNUSED(L); + return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; +} + + +LUA_API int lua_iscfunction (lua_State *L, int idx) { + StkId o = luaA_indexAcceptable(L, idx); + return (o == NULL) ? 0 : iscfunction(o); +} + + +LUA_API int lua_isnumber (lua_State *L, int idx) { + TObject n; + const TObject *o = luaA_indexAcceptable(L, idx); + return (o != NULL && tonumber(o, &n)); +} + + +LUA_API int lua_isstring (lua_State *L, int idx) { + int t = lua_type(L, idx); + return (t == LUA_TSTRING || t == LUA_TNUMBER); +} + + +LUA_API int lua_isuserdata (lua_State *L, int idx) { + const TObject *o = luaA_indexAcceptable(L, idx); + return (o != NULL && (ttisuserdata(o) || ttislightuserdata(o))); +} + + +LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { + StkId o1 = luaA_indexAcceptable(L, index1); + StkId o2 = luaA_indexAcceptable(L, index2); + return (o1 == NULL || o2 == NULL) ? 0 /* index out of range */ + : luaO_rawequalObj(o1, o2); +} + + +LUA_API int lua_equal (lua_State *L, int index1, int index2) { + StkId o1, o2; + int i; + lua_lock(L); /* may call tag method */ + o1 = luaA_indexAcceptable(L, index1); + o2 = luaA_indexAcceptable(L, index2); + i = (o1 == NULL || o2 == NULL) ? 0 /* index out of range */ + : equalobj(L, o1, o2); + lua_unlock(L); + return i; +} + + +LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { + StkId o1, o2; + int i; + lua_lock(L); /* may call tag method */ + o1 = luaA_indexAcceptable(L, index1); + o2 = luaA_indexAcceptable(L, index2); + i = (o1 == NULL || o2 == NULL) ? 0 /* index out-of-range */ + : luaV_lessthan(L, o1, o2); + lua_unlock(L); + return i; +} + + + +LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { + TObject n; + const TObject *o = luaA_indexAcceptable(L, idx); + if (o != NULL && tonumber(o, &n)) + return nvalue(o); + else + return 0; +} + + +LUA_API int lua_toboolean (lua_State *L, int idx) { + const TObject *o = luaA_indexAcceptable(L, idx); + return (o != NULL) && !l_isfalse(o); +} + + +LUA_API const char *lua_tostring (lua_State *L, int idx) { + StkId o = luaA_indexAcceptable(L, idx); + if (o == NULL) + return NULL; + else if (ttisstring(o)) + return svalue(o); + else { + const char *s; + lua_lock(L); /* `luaV_tostring' may create a new string */ + s = (luaV_tostring(L, o) ? svalue(o) : NULL); + luaC_checkGC(L); + lua_unlock(L); + return s; + } +} + + +LUA_API size_t lua_strlen (lua_State *L, int idx) { + StkId o = luaA_indexAcceptable(L, idx); + if (o == NULL) + return 0; + else if (ttisstring(o)) + return tsvalue(o)->tsv.len; + else { + size_t l; + lua_lock(L); /* `luaV_tostring' may create a new string */ + l = (luaV_tostring(L, o) ? tsvalue(o)->tsv.len : 0); + lua_unlock(L); + return l; + } +} + + +LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { + StkId o = luaA_indexAcceptable(L, idx); + return (o == NULL || !iscfunction(o)) ? NULL : clvalue(o)->c.f; +} + + +LUA_API void *lua_touserdata (lua_State *L, int idx) { + StkId o = luaA_indexAcceptable(L, idx); + if (o == NULL) return NULL; + switch (ttype(o)) { + case LUA_TUSERDATA: return (uvalue(o) + 1); + case LUA_TLIGHTUSERDATA: return pvalue(o); + default: return NULL; + } +} + + +LUA_API lua_State *lua_tothread (lua_State *L, int idx) { + StkId o = luaA_indexAcceptable(L, idx); + return (o == NULL || !ttisthread(o)) ? NULL : thvalue(o); +} + + +LUA_API const void *lua_topointer (lua_State *L, int idx) { + StkId o = luaA_indexAcceptable(L, idx); + if (o == NULL) return NULL; + else { + 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) +*/ + + +LUA_API void lua_pushnil (lua_State *L) { + lua_lock(L); + setnilvalue(L->top); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { + lua_lock(L); + setnvalue(L->top, n); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { + lua_lock(L); + luaC_checkGC(L); + setsvalue2s(L->top, luaS_newlstr(L, s, len)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushstring (lua_State *L, const char *s) { + if (s == NULL) + lua_pushnil(L); + else + lua_pushlstring(L, s, strlen(s)); +} + + +LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, + va_list argp) { + const char *ret; + lua_lock(L); + luaC_checkGC(L); + ret = luaO_pushvfstring(L, fmt, argp); + lua_unlock(L); + return ret; +} + + +LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { + const char *ret; + va_list argp; + lua_lock(L); + luaC_checkGC(L); + va_start(argp, fmt); + ret = luaO_pushvfstring(L, fmt, argp); + va_end(argp); + lua_unlock(L); + return ret; +} + + +LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { + Closure *cl; + lua_lock(L); + luaC_checkGC(L); + api_checknelems(L, n); + cl = luaF_newCclosure(L, n); + cl->c.f = fn; + L->top -= n; + while (n--) + setobj2n(&cl->c.upvalue[n], L->top+n); + setclvalue(L->top, cl); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushboolean (lua_State *L, int b) { + lua_lock(L); + setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { + lua_lock(L); + setpvalue(L->top, p); + api_incr_top(L); + lua_unlock(L); +} + + + +/* +** get functions (Lua -> stack) +*/ + + +LUA_API void lua_gettable (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = luaA_index(L, idx); + setobj2s(L->top - 1, luaV_gettable(L, t, L->top - 1, 0)); + lua_unlock(L); +} + + +LUA_API void lua_rawget (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = luaA_index(L, idx); + api_check(L, ttistable(t)); + setobj2s(L->top - 1, luaH_get(hvalue(t), L->top - 1)); + lua_unlock(L); +} + + +LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { + StkId o; + lua_lock(L); + o = luaA_index(L, idx); + api_check(L, ttistable(o)); + setobj2s(L->top, luaH_getnum(hvalue(o), n)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_newtable (lua_State *L) { + lua_lock(L); + luaC_checkGC(L); + sethvalue(L->top, luaH_new(L, 0, 0)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API int lua_getmetatable (lua_State *L, int objindex) { + const TObject *obj; + Table *mt = NULL; + int res; + lua_lock(L); + obj = luaA_indexAcceptable(L, objindex); + if (obj != NULL) { + switch (ttype(obj)) { + case LUA_TTABLE: + mt = hvalue(obj)->metatable; + break; + case LUA_TUSERDATA: + mt = uvalue(obj)->uv.metatable; + break; + } + } + if (mt == NULL || mt == hvalue(defaultmeta(L))) + res = 0; + else { + sethvalue(L->top, mt); + api_incr_top(L); + res = 1; + } + lua_unlock(L); + return res; +} + + +LUA_API void lua_getfenv (lua_State *L, int idx) { + StkId o; + lua_lock(L); + o = luaA_index(L, idx); + setobj2s(L->top, isLfunction(o) ? &clvalue(o)->l.g : gt(L)); + api_incr_top(L); + lua_unlock(L); +} + + +/* +** set functions (stack -> Lua) +*/ + + +LUA_API void lua_settable (lua_State *L, int idx) { + StkId t; + lua_lock(L); + api_checknelems(L, 2); + t = luaA_index(L, idx); + luaV_settable(L, t, L->top - 2, L->top - 1); + L->top -= 2; /* pop index and value */ + lua_unlock(L); +} + + +LUA_API void lua_rawset (lua_State *L, int idx) { + StkId t; + lua_lock(L); + api_checknelems(L, 2); + t = luaA_index(L, idx); + api_check(L, ttistable(t)); + setobj2t(luaH_set(L, hvalue(t), L->top-2), L->top-1); /* write barrier */ + L->top -= 2; + lua_unlock(L); +} + + +LUA_API void lua_rawseti (lua_State *L, int idx, int n) { + StkId o; + lua_lock(L); + api_checknelems(L, 1); + o = luaA_index(L, idx); + api_check(L, ttistable(o)); + setobj2t(luaH_setnum(L, hvalue(o), n), L->top-1); /* write barrier */ + L->top--; + lua_unlock(L); +} + + +LUA_API int lua_setmetatable (lua_State *L, int objindex) { + TObject *obj, *mt; + int res = 1; + lua_lock(L); + api_checknelems(L, 1); + obj = luaA_index(L, objindex); + mt = (!ttisnil(L->top - 1)) ? L->top - 1 : defaultmeta(L); + api_check(L, ttistable(mt)); + switch (ttype(obj)) { + case LUA_TTABLE: { + hvalue(obj)->metatable = hvalue(mt); /* write barrier */ + break; + } + case LUA_TUSERDATA: { + uvalue(obj)->uv.metatable = hvalue(mt); /* write barrier */ + break; + } + default: { + res = 0; /* cannot set */ + break; + } + } + L->top--; + lua_unlock(L); + return res; +} + + +LUA_API int lua_setfenv (lua_State *L, int idx) { + StkId o; + int res = 0; + lua_lock(L); + api_checknelems(L, 1); + o = luaA_index(L, idx); + L->top--; + api_check(L, ttistable(L->top)); + if (isLfunction(o)) { + res = 1; + clvalue(o)->l.g = *(L->top); + } + lua_unlock(L); + return res; +} + + +/* +** `load' and `call' functions (run Lua code) +*/ + +LUA_API void lua_call (lua_State *L, int nargs, int nresults) { + StkId func; + lua_lock(L); + api_checknelems(L, nargs+1); + func = L->top - (nargs+1); + luaD_call(L, func, nresults); + lua_unlock(L); +} + + + +/* +** Execute a protected call. +*/ +struct CallS { /* data to `f_call' */ + StkId func; + int nresults; +}; + + +static void f_call (lua_State *L, void *ud) { + struct CallS *c = cast(struct CallS *, ud); + luaD_call(L, c->func, c->nresults); +} + + + +LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) { + struct CallS c; + int status; + ptrdiff_t func; + lua_lock(L); + func = (errfunc == 0) ? 0 : savestack(L, luaA_index(L, errfunc)); + 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); + lua_unlock(L); + return status; +} + + +/* +** Execute a protected C call. +*/ +struct CCallS { /* data to `f_Ccall' */ + lua_CFunction func; + void *ud; +}; + + +static void f_Ccall (lua_State *L, void *ud) { + struct CCallS *c = cast(struct CCallS *, ud); + Closure *cl; + cl = luaF_newCclosure(L, 0); + cl->c.f = c->func; + setclvalue(L->top, cl); /* push function */ + incr_top(L); + setpvalue(L->top, c->ud); /* push only argument */ + incr_top(L); + luaD_call(L, L->top - 2, 0); +} + + +LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) { + struct CCallS c; + int status; + lua_lock(L); + c.func = func; + c.ud = ud; + status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0); + lua_unlock(L); + return status; +} + + +LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *data, + const char *chunkname) { + ZIO z; + int status; + int c; + lua_lock(L); + if (!chunkname) chunkname = "?"; + luaZ_init(&z, reader, data, chunkname); + c = luaZ_lookahead(&z); + status = luaD_protectedparser(L, &z, (c == LUA_SIGNATURE[0])); + lua_unlock(L); + return status; +} + + +LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data) { + int status; + TObject *o; + lua_lock(L); + api_checknelems(L, 1); + o = L->top - 1; + if (isLfunction(o) && clvalue(o)->l.nupvalues == 0) { + luaU_dump(L, clvalue(o)->l.p, writer, data); + status = 1; + } + else + status = 0; + lua_unlock(L); + return status; +} + + +/* +** Garbage-collection functions +*/ + +/* GC values are expressed in Kbytes: #bytes/2^10 */ +#define GCscalel(x) ((x)>>10) +#define GCscale(x) (cast(int, GCscalel(x))) +#define GCunscale(x) (cast(lu_mem, x)<<10) + +LUA_API int lua_getgcthreshold (lua_State *L) { + int threshold; + lua_lock(L); + threshold = GCscale(G(L)->GCthreshold); + lua_unlock(L); + return threshold; +} + +LUA_API int lua_getgccount (lua_State *L) { + int count; + lua_lock(L); + count = GCscale(G(L)->nblocks); + lua_unlock(L); + return count; +} + +LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) { + lua_lock(L); + if (cast(lu_mem, newthreshold) > GCscalel(MAX_LUMEM)) + G(L)->GCthreshold = MAX_LUMEM; + else + G(L)->GCthreshold = GCunscale(newthreshold); + luaC_checkGC(L); + lua_unlock(L); +} + + +/* +** miscellaneous functions +*/ + + +LUA_API const char *lua_version (void) { + return LUA_VERSION; +} + + +LUA_API int lua_error (lua_State *L) { + lua_lock(L); + api_checknelems(L, 1); + luaG_errormsg(L); + lua_unlock(L); + return 0; /* to avoid warnings */ +} + + +LUA_API int lua_next (lua_State *L, int idx) { + StkId t; + int more; + lua_lock(L); + t = luaA_index(L, idx); + api_check(L, ttistable(t)); + more = luaH_next(L, hvalue(t), L->top - 1); + if (more) { + api_incr_top(L); + } + else /* no more elements */ + L->top -= 1; /* remove key */ + lua_unlock(L); + return more; +} + + +LUA_API void lua_concat (lua_State *L, int n) { + lua_lock(L); + luaC_checkGC(L); + api_checknelems(L, n); + if (n >= 2) { + luaV_concat(L, n, L->top - L->base - 1); + L->top -= (n-1); + } + else if (n == 0) { /* push empty string */ + setsvalue2s(L->top, luaS_newlstr(L, NULL, 0)); + api_incr_top(L); + } + /* else n == 1; nothing to do */ + lua_unlock(L); +} + + +LUA_API void *lua_newuserdata (lua_State *L, size_t size) { + Udata *u; + lua_lock(L); + luaC_checkGC(L); + u = luaS_newudata(L, size); + setuvalue(L->top, u); + api_incr_top(L); + lua_unlock(L); + return u + 1; +} + + +LUA_API int lua_pushupvalues (lua_State *L) { + Closure *func; + int n, i; + lua_lock(L); + api_check(L, iscfunction(L->base - 1)); + func = clvalue(L->base - 1); + n = func->c.nupvalues; + luaD_checkstack(L, n + LUA_MINSTACK); + for (i=0; itop, &func->c.upvalue[i]); + L->top++; + } + lua_unlock(L); + return n; +} + + +static const char *aux_upvalue (lua_State *L, int funcindex, int n, + TObject **val) { + Closure *f; + StkId fi = luaA_index(L, funcindex); + if (!ttisfunction(fi)) return NULL; + f = clvalue(fi); + if (f->c.isC) { + if (n > f->c.nupvalues) return NULL; + *val = &f->c.upvalue[n-1]; + return ""; + } + else { + Proto *p = f->l.p; + if (n > p->sizeupvalues) return NULL; + *val = f->l.upvals[n-1]->v; + return getstr(p->upvalues[n-1]); + } +} + + +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { + const char *name; + TObject *val; + lua_lock(L); + name = aux_upvalue(L, funcindex, n, &val); + if (name) { + setobj2s(L->top, val); + api_incr_top(L); + } + lua_unlock(L); + return name; +} + + +LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { + const char *name; + TObject *val; + lua_lock(L); + api_checknelems(L, 1); + name = aux_upvalue(L, funcindex, n, &val); + if (name) { + L->top--; + setobj(val, L->top); /* write barrier */ + } + lua_unlock(L); + return name; +} + diff --git a/src/lapi.h b/src/lapi.h new file mode 100644 index 0000000..d12612f --- /dev/null +++ b/src/lapi.h @@ -0,0 +1,16 @@ +/* +** $Id: lapi.h,v 1.21 2002/03/04 21:29:41 roberto Exp $ +** Auxiliary functions from Lua API +** See Copyright Notice in lua.h +*/ + +#ifndef lapi_h +#define lapi_h + + +#include "lobject.h" + + +void luaA_pushobject (lua_State *L, const TObject *o); + +#endif diff --git a/src/lcode.cpp b/src/lcode.cpp new file mode 100644 index 0000000..d626ecd --- /dev/null +++ b/src/lcode.cpp @@ -0,0 +1,714 @@ +/* +** $Id: lcode.c,v 1.117 2003/04/03 13:35:34 roberto Exp $ +** Code generator for Lua +** See Copyright Notice in lua.h +*/ + + +#include + +#define lcode_c + +#include "lua.h" + +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "llex.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "ltable.h" + + +#define hasjumps(e) ((e)->t != (e)->f) + + +void luaK_nil (FuncState *fs, int from, int n) { + Instruction *previous; + if (fs->pc > fs->lasttarget && /* no jumps to current position? */ + GET_OPCODE(*(previous = &fs->f->code[fs->pc-1])) == 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, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ +} + + +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, OP_JMP, 0, NO_JUMP); + luaK_concat(fs, &j, jpc); /* keep them on hold */ + return j; +} + + +static int luaK_condjump (FuncState *fs, OpCode op, int A, int B, int C) { + luaK_codeABC(fs, op, A, B, C); + return luaK_jump(fs); +} + + +static void luaK_fixjump (FuncState *fs, int pc, int dest) { + Instruction *jmp = &fs->f->code[pc]; + int offset = dest-(pc+1); + lua_assert(dest != NO_JUMP); + if (abs(offset) > MAXARG_sBx) + luaX_syntaxerror(fs->ls, "control structure too long"); + SETARG_sBx(*jmp, offset); +} + + +/* +** returns current `pc' and marks it as a jump target (to avoid wrong +** optimizations with consecutive instructions not in the same basic block). +*/ +int luaK_getlabel (FuncState *fs) { + fs->lasttarget = fs->pc; + return fs->pc; +} + + +static int luaK_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 */ +} + + +static Instruction *getjumpcontrol (FuncState *fs, int pc) { + Instruction *pi = &fs->f->code[pc]; + if (pc >= 1 && testOpMode(GET_OPCODE(*(pi-1)), OpModeT)) + return pi-1; + else + return pi; +} + + +/* +** check whether list has any jump that do not produce a value +** (or produce an inverted value) +*/ +static int need_value (FuncState *fs, int list, int cond) { + for (; list != NO_JUMP; list = luaK_getjump(fs, list)) { + Instruction i = *getjumpcontrol(fs, list); + if (GET_OPCODE(i) != OP_TEST || GETARG_C(i) != cond) return 1; + } + return 0; /* not found */ +} + + +static void patchtestreg (Instruction *i, int reg) { + if (reg == NO_REG) reg = GETARG_B(*i); + SETARG_A(*i, reg); +} + + +static void luaK_patchlistaux (FuncState *fs, int list, + int ttarget, int treg, int ftarget, int freg, int dtarget) { + while (list != NO_JUMP) { + int next = luaK_getjump(fs, list); + Instruction *i = getjumpcontrol(fs, list); + if (GET_OPCODE(*i) != OP_TEST) { + lua_assert(dtarget != NO_JUMP); + luaK_fixjump(fs, list, dtarget); /* jump to default target */ + } + else { + if (GETARG_C(*i)) { + lua_assert(ttarget != NO_JUMP); + patchtestreg(i, treg); + luaK_fixjump(fs, list, ttarget); + } + else { + lua_assert(ftarget != NO_JUMP); + patchtestreg(i, freg); + luaK_fixjump(fs, list, ftarget); + } + } + list = next; + } +} + + +static void luaK_dischargejpc (FuncState *fs) { + luaK_patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc, NO_REG, fs->pc); + fs->jpc = NO_JUMP; +} + + +void luaK_patchlist (FuncState *fs, int list, int target) { + if (target == fs->pc) + luaK_patchtohere(fs, list); + else { + lua_assert(target < fs->pc); + luaK_patchlistaux(fs, list, target, NO_REG, target, NO_REG, target); + } +} + + +void luaK_patchtohere (FuncState *fs, int list) { + luaK_getlabel(fs); + luaK_concat(fs, &fs->jpc, list); +} + + +void luaK_concat (FuncState *fs, int *l1, int l2) { + if (l2 == NO_JUMP) return; + else if (*l1 == NO_JUMP) + *l1 = l2; + else { + int list = *l1; + int next; + while ((next = luaK_getjump(fs, list)) != NO_JUMP) /* find last element */ + list = next; + luaK_fixjump(fs, list, l2); + } +} + + +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(lu_byte, newstack); + } +} + + +void luaK_reserveregs (FuncState *fs, int n) { + luaK_checkstack(fs, n); + fs->freereg += n; +} + + +static void freereg (FuncState *fs, int reg) { + if (reg >= fs->nactvar && reg < MAXSTACK) { + fs->freereg--; + lua_assert(reg == fs->freereg); + } +} + + +static void freeexp (FuncState *fs, expdesc *e) { + if (e->k == VNONRELOC) + freereg(fs, e->info); +} + + +static int addk (FuncState *fs, TObject *k, TObject *v) { + const TObject *idx = luaH_get(fs->h, k); + 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 */ + Proto *f = fs->f; + luaM_growvector(fs->L, f->k, fs->nk, f->sizek, TObject, + MAXARG_Bx, "constant table overflow"); + setobj2n(&f->k[fs->nk], v); + setnvalue(luaH_set(fs->L, fs->h, k), cast(lua_Number, fs->nk)); + return fs->nk++; + } +} + + +int luaK_stringK (FuncState *fs, TString *s) { + TObject o; + setsvalue(&o, s); + return addk(fs, &o, &o); +} + + +int luaK_numberK (FuncState *fs, lua_Number r) { + TObject o; + setnvalue(&o, r); + return addk(fs, &o, &o); +} + + +static int nil_constant (FuncState *fs) { + TObject k, v; + setnilvalue(&v); + sethvalue(&k, fs->h); /* cannot use nil as key; instead use table itself */ + return addk(fs, &k, &v); +} + + +void luaK_setcallreturns (FuncState *fs, expdesc *e, int nresults) { + if (e->k == VCALL) { /* expression is an open function call? */ + SETARG_C(getcode(fs, e), nresults+1); + if (nresults == 1) { /* `regular' expression? */ + e->k = VNONRELOC; + e->info = GETARG_A(getcode(fs, e)); + } + } +} + + +void luaK_dischargevars (FuncState *fs, expdesc *e) { + switch (e->k) { + case VLOCAL: { + e->k = VNONRELOC; + break; + } + case VUPVAL: { + e->info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->info, 0); + e->k = VRELOCABLE; + break; + } + case VGLOBAL: { + e->info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->info); + e->k = VRELOCABLE; + break; + } + case VINDEXED: { + freereg(fs, e->aux); + freereg(fs, e->info); + e->info = luaK_codeABC(fs, OP_GETTABLE, 0, e->info, e->aux); + e->k = VRELOCABLE; + break; + } + case VCALL: { + luaK_setcallreturns(fs, e, 1); + break; + } + default: break; /* there is one value available (somewhere) */ + } +} + + +static int code_label (FuncState *fs, int A, int b, int jump) { + luaK_getlabel(fs); /* those instructions may be jump targets */ + return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); +} + + +static void discharge2reg (FuncState *fs, expdesc *e, int reg) { + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: { + luaK_nil(fs, reg, 1); + break; + } + case VFALSE: case VTRUE: { + luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); + break; + } + case VK: { + luaK_codeABx(fs, OP_LOADK, reg, e->info); + break; + } + case VRELOCABLE: { + Instruction *pc = &getcode(fs, e); + SETARG_A(*pc, reg); + break; + } + case VNONRELOC: { + if (reg != e->info) + luaK_codeABC(fs, OP_MOVE, reg, e->info, 0); + break; + } + default: { + lua_assert(e->k == VVOID || e->k == VJMP); + return; /* nothing to do... */ + } + } + e->info = reg; + e->k = VNONRELOC; +} + + +static void discharge2anyreg (FuncState *fs, expdesc *e) { + if (e->k != VNONRELOC) { + luaK_reserveregs(fs, 1); + discharge2reg(fs, e, fs->freereg-1); + } +} + + +static void luaK_exp2reg (FuncState *fs, expdesc *e, int reg) { + discharge2reg(fs, e, reg); + if (e->k == VJMP) + luaK_concat(fs, &e->t, e->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, 1) || need_value(fs, e->f, 0)) { + int fj = NO_JUMP; /* first jump (over LOAD ops.) */ + if (e->k != VJMP) + fj = 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); + luaK_patchlistaux(fs, e->f, p_f, NO_REG, final, reg, p_f); + luaK_patchlistaux(fs, e->t, final, reg, p_t, NO_REG, p_t); + } + e->f = e->t = NO_JUMP; + e->info = reg; + e->k = VNONRELOC; +} + + +void luaK_exp2nextreg (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + freeexp(fs, e); + luaK_reserveregs(fs, 1); + luaK_exp2reg(fs, e, fs->freereg - 1); +} + + +int luaK_exp2anyreg (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + if (e->k == VNONRELOC) { + if (!hasjumps(e)) return e->info; /* exp is already in a register */ + if (e->info >= fs->nactvar) { /* reg. is not a local? */ + luaK_exp2reg(fs, e, e->info); /* put value on it */ + return e->info; + } + } + luaK_exp2nextreg(fs, e); /* default */ + return e->info; +} + + +void luaK_exp2val (FuncState *fs, expdesc *e) { + if (hasjumps(e)) + luaK_exp2anyreg(fs, e); + else + luaK_dischargevars(fs, e); +} + + +int luaK_exp2RK (FuncState *fs, expdesc *e) { + luaK_exp2val(fs, e); + switch (e->k) { + case VNIL: { + if (fs->nk + MAXSTACK <= MAXARG_C) { /* constant fit in argC? */ + e->info = nil_constant(fs); + e->k = VK; + return e->info + MAXSTACK; + } + else break; + } + case VK: { + if (e->info + MAXSTACK <= MAXARG_C) /* constant fit in argC? */ + return e->info + MAXSTACK; + else break; + } + default: break; + } + /* not a constant in the right range: put it in a register */ + return luaK_exp2anyreg(fs, e); +} + + +void luaK_storevar (FuncState *fs, expdesc *var, expdesc *exp) { + switch (var->k) { + case VLOCAL: { + freeexp(fs, exp); + luaK_exp2reg(fs, exp, var->info); + return; + } + case VUPVAL: { + int e = luaK_exp2anyreg(fs, exp); + luaK_codeABC(fs, OP_SETUPVAL, e, var->info, 0); + break; + } + case VGLOBAL: { + int e = luaK_exp2anyreg(fs, exp); + luaK_codeABx(fs, OP_SETGLOBAL, e, var->info); + break; + } + case VINDEXED: { + int e = luaK_exp2RK(fs, exp); + luaK_codeABC(fs, OP_SETTABLE, var->info, var->aux, e); + break; + } + default: { + lua_assert(0); /* invalid var kind to store */ + break; + } + } + freeexp(fs, exp); +} + + +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, OP_SELF, func, e->info, luaK_exp2RK(fs, key)); + freeexp(fs, key); + e->info = func; + e->k = VNONRELOC; +} + + +static void invertjump (FuncState *fs, expdesc *e) { + Instruction *pc = getjumpcontrol(fs, e->info); + lua_assert(testOpMode(GET_OPCODE(*pc), OpModeT) && + GET_OPCODE(*pc) != OP_TEST); + SETARG_A(*pc, !(GETARG_A(*pc))); +} + + +static int jumponcond (FuncState *fs, expdesc *e, int cond) { + if (e->k == VRELOCABLE) { + Instruction ie = getcode(fs, e); + if (GET_OPCODE(ie) == OP_NOT) { + fs->pc--; /* remove previous OP_NOT */ + return luaK_condjump(fs, OP_TEST, NO_REG, GETARG_B(ie), !cond); + } + /* else go through */ + } + discharge2anyreg(fs, e); + freeexp(fs, e); + return luaK_condjump(fs, OP_TEST, NO_REG, e->info, cond); +} + + +void luaK_goiftrue (FuncState *fs, expdesc *e) { + int pc; /* pc of last jump */ + luaK_dischargevars(fs, e); + switch (e->k) { + case VK: case VTRUE: { + pc = NO_JUMP; /* always true; do nothing */ + break; + } + case VFALSE: { + pc = luaK_jump(fs); /* always jump */ + break; + } + case VJMP: { + invertjump(fs, e); + pc = e->info; + break; + } + default: { + pc = jumponcond(fs, e, 0); + break; + } + } + luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ +} + + +void luaK_goiffalse (FuncState *fs, expdesc *e) { + int pc; /* pc of last jump */ + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: case VFALSE: { + pc = NO_JUMP; /* always false; do nothing */ + break; + } + case VTRUE: { + pc = luaK_jump(fs); /* always jump */ + break; + } + case VJMP: { + pc = e->info; + break; + } + default: { + pc = jumponcond(fs, e, 1); + break; + } + } + luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ +} + + +static void codenot (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: case VFALSE: { + e->k = VTRUE; + break; + } + case VK: case VTRUE: { + e->k = VFALSE; + break; + } + case VJMP: { + invertjump(fs, e); + break; + } + case VRELOCABLE: + case VNONRELOC: { + discharge2anyreg(fs, e); + freeexp(fs, e); + e->info = luaK_codeABC(fs, OP_NOT, 0, e->info, 0); + e->k = 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; } +} + + +void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { + t->aux = luaK_exp2RK(fs, k); + t->k = VINDEXED; +} + + +void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { + if (op == OPR_MINUS) { + luaK_exp2val(fs, e); + if (e->k == VK && ttisnumber(&fs->f->k[e->info])) + e->info = luaK_numberK(fs, -nvalue(&fs->f->k[e->info])); + else { + luaK_exp2anyreg(fs, e); + freeexp(fs, e); + e->info = luaK_codeABC(fs, OP_UNM, 0, e->info, 0); + e->k = VRELOCABLE; + } + } + else /* op == NOT */ + codenot(fs, e); +} + + +void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { + switch (op) { + case OPR_AND: { + luaK_goiftrue(fs, v); + luaK_patchtohere(fs, v->t); + v->t = NO_JUMP; + break; + } + case OPR_OR: { + luaK_goiffalse(fs, v); + luaK_patchtohere(fs, v->f); + v->f = NO_JUMP; + break; + } + case OPR_CONCAT: { + luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ + break; + } + default: { + luaK_exp2RK(fs, v); + break; + } + } +} + + +static void codebinop (FuncState *fs, expdesc *res, BinOpr op, + int o1, int o2) { + if (op <= OPR_POW) { /* arithmetic operator? */ + OpCode opc = cast(OpCode, (op - OPR_ADD) + OP_ADD); /* ORDER OP */ + res->info = luaK_codeABC(fs, opc, 0, o1, o2); + res->k = VRELOCABLE; + } + else { /* test operator */ + static const OpCode ops[] = {OP_EQ, OP_EQ, OP_LT, OP_LE, OP_LT, OP_LE}; + int cond = 1; + if (op >= OPR_GT) { /* `>' or `>='? */ + int temp; /* exchange args and replace by `<' or `<=' */ + temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ + } + else if (op == OPR_NE) cond = 0; + res->info = luaK_condjump(fs, ops[op - OPR_NE], cond, o1, o2); + res->k = VJMP; + } +} + + +void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { + switch (op) { + case OPR_AND: { + lua_assert(e1->t == NO_JUMP); /* list must be closed */ + luaK_dischargevars(fs, e2); + luaK_concat(fs, &e1->f, e2->f); + e1->k = e2->k; e1->info = e2->info; e1->aux = e2->aux; e1->t = e2->t; + break; + } + case OPR_OR: { + lua_assert(e1->f == NO_JUMP); /* list must be closed */ + luaK_dischargevars(fs, e2); + luaK_concat(fs, &e1->t, e2->t); + e1->k = e2->k; e1->info = e2->info; e1->aux = e2->aux; e1->f = e2->f; + break; + } + case OPR_CONCAT: { + luaK_exp2val(fs, e2); + if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { + lua_assert(e1->info == GETARG_B(getcode(fs, e2))-1); + freeexp(fs, e1); + SETARG_B(getcode(fs, e2), e1->info); + e1->k = e2->k; e1->info = e2->info; + } + else { + luaK_exp2nextreg(fs, e2); + freeexp(fs, e2); + freeexp(fs, e1); + e1->info = luaK_codeABC(fs, OP_CONCAT, 0, e1->info, e2->info); + e1->k = VRELOCABLE; + } + break; + } + default: { + int o1 = luaK_exp2RK(fs, e1); + int o2 = luaK_exp2RK(fs, e2); + freeexp(fs, e2); + freeexp(fs, e1); + codebinop(fs, e1, op, o1, o2); + } + } +} + + +void luaK_fixline (FuncState *fs, int line) { + fs->f->lineinfo[fs->pc - 1] = line; +} + + +int luaK_code (FuncState *fs, Instruction i, int line) { + Proto *f = fs->f; + luaK_dischargejpc(fs); /* `pc' will change */ + /* put new instruction in code array */ + luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, + MAX_INT, "code size overflow"); + f->code[fs->pc] = i; + /* save corresponding line information */ + luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int, + MAX_INT, "code size overflow"); + f->lineinfo[fs->pc] = line; + return fs->pc++; +} + + +int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { + lua_assert(getOpMode(o) == iABC); + return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline); +} + + +int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { + lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); + return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline); +} + diff --git a/src/lcode.h b/src/lcode.h new file mode 100644 index 0000000..74908c6 --- /dev/null +++ b/src/lcode.h @@ -0,0 +1,74 @@ +/* +** $Id: lcode.h,v 1.38 2002/12/11 12:34:22 roberto Exp $ +** Code generator for Lua +** See Copyright Notice in lua.h +*/ + +#ifndef lcode_h +#define lcode_h + +#include "llex.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" + + +/* +** 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). +*/ +#define NO_JUMP (-1) + + +/* +** grep "ORDER OPR" if you change these enums +*/ +typedef enum BinOpr { + OPR_ADD, OPR_SUB, OPR_MULT, OPR_DIV, OPR_POW, + OPR_CONCAT, + OPR_NE, OPR_EQ, + OPR_LT, OPR_LE, OPR_GT, OPR_GE, + OPR_AND, OPR_OR, + OPR_NOBINOPR +} BinOpr; + +#define binopistest(op) ((op) >= OPR_NE) + +typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_NOUNOPR } UnOpr; + + +#define getcode(fs,e) ((fs)->f->code[(e)->info]) + +#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) + +int luaK_code (FuncState *fs, Instruction i, int line); +int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); +int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); +void luaK_fixline (FuncState *fs, int line); +void luaK_nil (FuncState *fs, int from, int n); +void luaK_reserveregs (FuncState *fs, int n); +void luaK_checkstack (FuncState *fs, int n); +int luaK_stringK (FuncState *fs, TString *s); +int luaK_numberK (FuncState *fs, lua_Number r); +void luaK_dischargevars (FuncState *fs, expdesc *e); +int luaK_exp2anyreg (FuncState *fs, expdesc *e); +void luaK_exp2nextreg (FuncState *fs, expdesc *e); +void luaK_exp2val (FuncState *fs, expdesc *e); +int luaK_exp2RK (FuncState *fs, expdesc *e); +void luaK_self (FuncState *fs, expdesc *e, expdesc *key); +void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); +void luaK_goiftrue (FuncState *fs, expdesc *e); +void luaK_goiffalse (FuncState *fs, expdesc *e); +void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); +void luaK_setcallreturns (FuncState *fs, expdesc *var, int nresults); +int luaK_jump (FuncState *fs); +void luaK_patchlist (FuncState *fs, int list, int target); +void luaK_patchtohere (FuncState *fs, int list); +void luaK_concat (FuncState *fs, int *l1, int l2); +int luaK_getlabel (FuncState *fs); +void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); +void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); +void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); + + +#endif diff --git a/src/ldebug.cpp b/src/ldebug.cpp new file mode 100644 index 0000000..8e511e3 --- /dev/null +++ b/src/ldebug.cpp @@ -0,0 +1,585 @@ +/* +** $Id: ldebug.c,v 1.150 2003/03/19 21:24:04 roberto Exp $ +** Debug Interface +** See Copyright Notice in lua.h +*/ + + +#include +#include + +#define ldebug_c + +#include "lua.h" + +#include "lapi.h" +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" + + + +static const char *getfuncname (CallInfo *ci, const char **name); + + +#define isLua(ci) (!((ci)->state & CI_C)) + + +static int currentpc (CallInfo *ci) { + if (!isLua(ci)) return -1; /* function is not a Lua function? */ + if (ci->state & CI_HASFRAME) /* function has a frame? */ + ci->u.l.savedpc = *ci->u.l.pc; /* use `pc' from there */ + /* function's pc is saved */ + return pcRel(ci->u.l.savedpc, ci_func(ci)->l.p); +} + + +static int currentline (CallInfo *ci) { + int pc = currentpc(ci); + if (pc < 0) + return -1; /* only active lua functions have current-line information */ + else + return getline(ci_func(ci)->l.p, pc); +} + + +void luaG_inithooks (lua_State *L) { + CallInfo *ci; + for (ci = L->ci; ci != L->base_ci; ci--) /* update all `savedpc's */ + currentpc(ci); + L->hookinit = 1; +} + + +/* +** this function can be called asynchronous (e.g. during a signal) +*/ +LUA_API 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(lu_byte, mask); + L->hookinit = 0; + return 1; +} + + +LUA_API lua_Hook lua_gethook (lua_State *L) { + return L->hook; +} + + +LUA_API int lua_gethookmask (lua_State *L) { + return L->hookmask; +} + + +LUA_API int lua_gethookcount (lua_State *L) { + return L->basehookcount; +} + + +LUA_API 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; ci--) { + level--; + if (!(ci->state & CI_C)) /* Lua function? */ + level -= ci->u.l.tailcalls; /* skip lost tail calls */ + } + if (level > 0 || ci == L->base_ci) status = 0; /* there is no such level */ + else if (level < 0) { /* level is of a lost tail call */ + status = 1; + ar->i_ci = 0; + } + else { + status = 1; + ar->i_ci = ci - L->base_ci; + } + lua_unlock(L); + return status; +} + + +static Proto *getluaproto (CallInfo *ci) { + return (isLua(ci) ? ci_func(ci)->l.p : NULL); +} + + +LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { + const char *name; + CallInfo *ci; + Proto *fp; + lua_lock(L); + name = NULL; + ci = L->base_ci + ar->i_ci; + fp = getluaproto(ci); + if (fp) { /* is a Lua function? */ + name = luaF_getlocalname(fp, n, currentpc(ci)); + if (name) + luaA_pushobject(L, ci->base+(n-1)); /* push value */ + } + lua_unlock(L); + return name; +} + + +LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { + const char *name; + CallInfo *ci; + Proto *fp; + lua_lock(L); + name = NULL; + ci = L->base_ci + ar->i_ci; + fp = getluaproto(ci); + L->top--; /* pop new value */ + if (fp) { /* is a Lua function? */ + name = luaF_getlocalname(fp, n, currentpc(ci)); + if (!name || name[0] == '(') /* `(' starts private locals */ + name = NULL; + else + setobjs2s(ci->base+(n-1), L->top); + } + lua_unlock(L); + return name; +} + + +static void funcinfo (lua_Debug *ar, StkId func) { + Closure *cl = clvalue(func); + if (cl->c.isC) { + ar->source = "=[C]"; + ar->linedefined = -1; + ar->what = "C"; + } + else { + ar->source = getstr(cl->l.p->source); + ar->linedefined = cl->l.p->lineDefined; + ar->what = (ar->linedefined == 0) ? "main" : "Lua"; + } + luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); +} + + +static const char *travglobals (lua_State *L, const TObject *o) { + Table *g = hvalue(gt(L)); + int i = sizenode(g); + while (i--) { + Node *n = gnode(g, i); + if (luaO_rawequalObj(o, gval(n)) && ttisstring(gkey(n))) + return getstr(tsvalue(gkey(n))); + } + return NULL; +} + + +static void info_tailcall (lua_State *L, lua_Debug *ar) { + ar->name = ar->namewhat = ""; + ar->what = "tail"; + ar->linedefined = ar->currentline = -1; + ar->source = "=(tail call)"; + luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); + ar->nups = 0; + setnilvalue(L->top); +} + + +static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, + StkId f, CallInfo *ci) { + int status = 1; + for (; *what; what++) { + switch (*what) { + case 'S': { + funcinfo(ar, f); + break; + } + case 'l': { + ar->currentline = (ci) ? currentline(ci) : -1; + break; + } + case 'u': { + ar->nups = clvalue(f)->c.nupvalues; + break; + } + case 'n': { + ar->namewhat = (ci) ? getfuncname(ci, &ar->name) : NULL; + if (ar->namewhat == NULL) { + /* try to find a global name */ + if ((ar->name = travglobals(L, f)) != NULL) + ar->namewhat = "global"; + else ar->namewhat = ""; /* not found */ + } + break; + } + case 'f': { + setobj2s(L->top, f); + break; + } + default: status = 0; /* invalid option */ + } + } + return status; +} + + +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { + int status = 1; + lua_lock(L); + if (*what == '>') { + StkId f = L->top - 1; + if (!ttisfunction(f)) + luaG_runerror(L, "value for `lua_getinfo' is not a function"); + status = auxgetinfo(L, what + 1, ar, f, NULL); + L->top--; /* pop function */ + } + else if (ar->i_ci != 0) { /* no tail call? */ + CallInfo *ci = L->base_ci + ar->i_ci; + lua_assert(ttisfunction(ci->base - 1)); + status = auxgetinfo(L, what, ar, ci->base - 1, ci); + } + else + info_tailcall(L, ar); + if (strchr(what, 'f')) incr_top(L); + lua_unlock(L); + return status; +} + + +/* +** {====================================================== +** Symbolic Execution and code checker +** ======================================================= +*/ + +#define check(x) if (!(x)) return 0; + +#define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode) + +#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) + + + +static int precheck (const Proto *pt) { + check(pt->maxstacksize <= MAXSTACK); + check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0); + lua_assert(pt->numparams+pt->is_vararg <= pt->maxstacksize); + check(GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); + return 1; +} + + +static int checkopenop (const Proto *pt, int pc) { + Instruction i = pt->code[pc+1]; + switch (GET_OPCODE(i)) { + case OP_CALL: + case OP_TAILCALL: + case OP_RETURN: { + check(GETARG_B(i) == 0); + return 1; + } + case OP_SETLISTO: return 1; + default: return 0; /* invalid instruction after an open call */ + } +} + + +static int checkRK (const Proto *pt, int r) { + return (r < pt->maxstacksize || (r >= MAXSTACK && r-MAXSTACK < pt->sizek)); +} + + +static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) { + int pc; + int last; /* stores position of last instruction that changed `reg' */ + last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ + check(precheck(pt)); + for (pc = 0; pc < lastpc; pc++) { + const Instruction i = pt->code[pc]; + OpCode op = GET_OPCODE(i); + int a = GETARG_A(i); + int b = 0; + int c = 0; + checkreg(pt, a); + switch (getOpMode(op)) { + case iABC: { + b = GETARG_B(i); + c = GETARG_C(i); + if (testOpMode(op, OpModeBreg)) { + checkreg(pt, b); + } + else if (testOpMode(op, OpModeBrk)) + check(checkRK(pt, b)); + if (testOpMode(op, OpModeCrk)) + check(checkRK(pt, c)); + break; + } + case iABx: { + b = GETARG_Bx(i); + if (testOpMode(op, OpModeK)) check(b < pt->sizek); + break; + } + case iAsBx: { + b = GETARG_sBx(i); + break; + } + } + if (testOpMode(op, OpModesetA)) { + if (a == reg) last = pc; /* change register `a' */ + } + if (testOpMode(op, OpModeT)) { + check(pc+2 < pt->sizecode); /* check skip */ + check(GET_OPCODE(pt->code[pc+1]) == OP_JMP); + } + switch (op) { + case OP_LOADBOOL: { + check(c == 0 || pc+2 < pt->sizecode); /* check its jump */ + break; + } + case OP_LOADNIL: { + if (a <= reg && reg <= b) + last = pc; /* set registers from `a' to `b' */ + break; + } + case OP_GETUPVAL: + case OP_SETUPVAL: { + check(b < pt->nups); + break; + } + case OP_GETGLOBAL: + case OP_SETGLOBAL: { + check(ttisstring(&pt->k[b])); + break; + } + case OP_SELF: { + checkreg(pt, a+1); + if (reg == a+1) last = pc; + break; + } + case OP_CONCAT: { + /* `c' is a register, and at least two operands */ + check(c < MAXSTACK && b < c); + break; + } + case OP_TFORLOOP: + checkreg(pt, a+c+5); + if (reg >= a) last = pc; /* affect all registers above base */ + /* go through */ + case OP_FORLOOP: + checkreg(pt, a+2); + /* go through */ + case OP_JMP: { + int dest = pc+1+b; + check(0 <= dest && dest < pt->sizecode); + /* 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 OP_CALL: + case OP_TAILCALL: { + if (b != 0) { + checkreg(pt, a+b-1); + } + c--; /* c = num. returns */ + if (c == LUA_MULTRET) { + check(checkopenop(pt, pc)); + } + else if (c != 0) + checkreg(pt, a+c-1); + if (reg >= a) last = pc; /* affect all registers above base */ + break; + } + case OP_RETURN: { + b--; /* b = num. returns */ + if (b > 0) checkreg(pt, a+b-1); + break; + } + case OP_SETLIST: { + checkreg(pt, a + (b&(LFIELDS_PER_FLUSH-1)) + 1); + break; + } + case OP_CLOSURE: { + int nup; + check(b < pt->sizep); + nup = pt->p[b]->nups; + check(pc + nup < pt->sizecode); + for (; nup>0; nup--) { + OpCode op1 = GET_OPCODE(pt->code[pc+nup]); + check(op1 == OP_GETUPVAL || op1 == OP_MOVE); + } + break; + } + default: break; + } + } + return pt->code[last]; +} + +#undef check +#undef checkjump +#undef checkreg + +/* }====================================================== */ + + +int luaG_checkcode (const Proto *pt) { + return luaG_symbexec(pt, pt->sizecode, NO_REG); +} + + +static const char *kname (Proto *p, int c) { + c = c - MAXSTACK; + if (c >= 0 && ttisstring(&p->k[c])) + return svalue(&p->k[c]); + else + return "?"; +} + + +static const char *getobjname (CallInfo *ci, int stackpos, const char **name) { + if (isLua(ci)) { /* a Lua function? */ + Proto *p = ci_func(ci)->l.p; + int pc = currentpc(ci); + Instruction i; + *name = luaF_getlocalname(p, stackpos+1, pc); + if (*name) /* is a local? */ + return "local"; + i = luaG_symbexec(p, pc, stackpos); /* try symbolic execution */ + lua_assert(pc != -1); + switch (GET_OPCODE(i)) { + case OP_GETGLOBAL: { + int g = GETARG_Bx(i); /* global index */ + lua_assert(ttisstring(&p->k[g])); + *name = svalue(&p->k[g]); + return "global"; + } + case OP_MOVE: { + int a = GETARG_A(i); + int b = GETARG_B(i); /* move from `b' to `a' */ + if (b < a) + return getobjname(ci, b, name); /* get name for `b' */ + break; + } + case OP_GETTABLE: { + int k = GETARG_C(i); /* key index */ + *name = kname(p, k); + return "field"; + } + case OP_SELF: { + int k = GETARG_C(i); /* key index */ + *name = kname(p, k); + return "method"; + } + default: break; + } + } + return NULL; /* no useful name found */ +} + + +static const char *getfuncname (CallInfo *ci, const char **name) { + Instruction i; + if ((isLua(ci) && ci->u.l.tailcalls > 0) || !isLua(ci - 1)) + return NULL; /* calling function is not Lua (or is unknown) */ + ci--; /* calling function */ + i = ci_func(ci)->l.p->code[currentpc(ci)]; + if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL) + return getobjname(ci, GETARG_A(i), name); + else + return NULL; /* no useful name can be found */ +} + + +/* only ANSI way to check whether a pointer points to an array */ +static int isinstack (CallInfo *ci, const TObject *o) { + StkId p; + for (p = ci->base; p < ci->top; p++) + if (o == p) return 1; + return 0; +} + + +void luaG_typeerror (lua_State *L, const TObject *o, const char *op) { + const char *name = NULL; + const char *t = luaT_typenames[ttype(o)]; + const char *kind = (isinstack(L->ci, o)) ? + getobjname(L->ci, o - L->base, &name) : NULL; + if (kind) + luaG_runerror(L, "attempt to %s %s `%s' (a %s value)", + op, kind, name, t); + else + luaG_runerror(L, "attempt to %s a %s value", op, t); +} + + +void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { + if (ttisstring(p1)) p1 = p2; + lua_assert(!ttisstring(p1)); + luaG_typeerror(L, p1, "concatenate"); +} + + +void luaG_aritherror (lua_State *L, const TObject *p1, const TObject *p2) { + TObject temp; + if (luaV_tonumber(p1, &temp) == NULL) + p2 = p1; /* first operand is wrong */ + luaG_typeerror(L, p2, "perform arithmetic on"); +} + + +int luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2) { + const char *t1 = luaT_typenames[ttype(p1)]; + const char *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; +} + + +static void addinfo (lua_State *L, const char *msg) { + CallInfo *ci = L->ci; + if (isLua(ci)) { /* is Lua code? */ + char buff[LUA_IDSIZE]; /* add file:line information */ + int line = currentline(ci); + luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE); + luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); + } +} + + +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->top, L->top - 1); /* move argument */ + setobjs2s(L->top - 1, errfunc); /* push function */ + incr_top(L); + luaD_call(L, L->top - 2, 1); /* call it */ + } + luaD_throw(L, LUA_ERRRUN); +} + + +void luaG_runerror (lua_State *L, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + addinfo(L, luaO_pushvfstring(L, fmt, argp)); + va_end(argp); + luaG_errormsg(L); +} + diff --git a/src/ldebug.h b/src/ldebug.h new file mode 100644 index 0000000..7ff3958 --- /dev/null +++ b/src/ldebug.h @@ -0,0 +1,31 @@ +/* +** $Id: ldebug.h,v 1.32 2002/11/18 11:01:55 roberto Exp $ +** Auxiliary functions from Debug Interface module +** See Copyright Notice in lua.h +*/ + +#ifndef ldebug_h +#define ldebug_h + + +#include "lstate.h" + + +#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) + +#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) + +#define resethookcount(L) (L->hookcount = L->basehookcount) + + +void luaG_inithooks (lua_State *L); +void luaG_typeerror (lua_State *L, const TObject *o, const char *opname); +void luaG_concaterror (lua_State *L, StkId p1, StkId p2); +void luaG_aritherror (lua_State *L, const TObject *p1, const TObject *p2); +int luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2); +void luaG_runerror (lua_State *L, const char *fmt, ...); +void luaG_errormsg (lua_State *L); +int luaG_checkcode (const Proto *pt); + + +#endif diff --git a/src/ldo.cpp b/src/ldo.cpp new file mode 100644 index 0000000..a6d344c --- /dev/null +++ b/src/ldo.cpp @@ -0,0 +1,471 @@ +/* +** $Id: ldo.c,v 1.217a 2003/04/03 13:35:34 roberto Exp $ +** Stack and Call structure of Lua +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +#define ldo_c + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lundump.h" +#include "lvm.h" +#include "lzio.h" + + + + +/* +** {====================================================== +** Error-recovery functions (based on long jumps) +** ======================================================= +*/ + + +/* chain list of long jump buffers */ +struct lua_longjmp { + struct lua_longjmp *previous; + jmp_buf b; + volatile int status; /* error code */ +}; + + +static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { + switch (errcode) { + case LUA_ERRMEM: { + setsvalue2s(oldtop, luaS_new(L, MEMERRMSG)); + break; + } + case LUA_ERRERR: { + setsvalue2s(oldtop, luaS_new(L, "error in error handling")); + break; + } + case LUA_ERRSYNTAX: + case LUA_ERRRUN: { + setobjs2s(oldtop, L->top - 1); /* error message on current top */ + break; + } + } + L->top = oldtop + 1; +} + + +void luaD_throw (lua_State *L, int errcode) { + if (L->errorJmp) { + L->errorJmp->status = errcode; + longjmp(L->errorJmp->b, 1); + } + else { + G(L)->panic(L); + exit(EXIT_FAILURE); + } +} + + +int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { + struct lua_longjmp lj; + lj.status = 0; + lj.previous = L->errorJmp; /* chain new error handler */ + L->errorJmp = &lj; + if (setjmp(lj.b) == 0) + (*f)(L, ud); + L->errorJmp = lj.previous; /* restore old error handler */ + return lj.status; +} + + +static void restore_stack_limit (lua_State *L) { + L->stack_last = L->stack+L->stacksize-1; + if (L->size_ci > LUA_MAXCALLS) { /* there was an overflow? */ + int inuse = (L->ci - L->base_ci); + if (inuse + 1 < LUA_MAXCALLS) /* can `undo' overflow? */ + luaD_reallocCI(L, LUA_MAXCALLS); + } +} + +/* }====================================================== */ + + +static void correctstack (lua_State *L, TObject *oldstack) { + CallInfo *ci; + GCObject *up; + L->top = (L->top - oldstack) + L->stack; + for (up = L->openupval; up != NULL; up = up->gch.next) + gcotouv(up)->v = (gcotouv(up)->v - oldstack) + L->stack; + for (ci = L->base_ci; ci <= L->ci; ci++) { + ci->top = (ci->top - oldstack) + L->stack; + ci->base = (ci->base - oldstack) + L->stack; + } + L->base = L->ci->base; +} + + +void luaD_reallocstack (lua_State *L, int newsize) { + TObject *oldstack = L->stack; + luaM_reallocvector(L, L->stack, L->stacksize, newsize, TObject); + L->stacksize = newsize; + L->stack_last = L->stack+newsize-1-EXTRA_STACK; + correctstack(L, oldstack); +} + + +void luaD_reallocCI (lua_State *L, int newsize) { + CallInfo *oldci = L->base_ci; + luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); + L->size_ci = cast(unsigned short, newsize); + L->ci = (L->ci - oldci) + L->base_ci; + L->end_ci = L->base_ci + L->size_ci; +} + + +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 + EXTRA_STACK); +} + + +static void luaD_growCI (lua_State *L) { + if (L->size_ci > LUA_MAXCALLS) /* overflow while handling overflow? */ + luaD_throw(L, LUA_ERRERR); + else { + luaD_reallocCI(L, 2*L->size_ci); + if (L->size_ci > LUA_MAXCALLS) + luaG_runerror(L, "stack overflow"); + } +} + + +void luaD_callhook (lua_State *L, int event, int line) { + lua_Hook hook = L->hook; + if (hook && L->allowhook) { + ptrdiff_t top = savestack(L, L->top); + ptrdiff_t ci_top = savestack(L, L->ci->top); + lua_Debug ar; + ar.event = event; + ar.currentline = line; + if (event == LUA_HOOKTAILRET) + ar.i_ci = 0; /* tail call; no debug information about it */ + else + ar.i_ci = L->ci - L->base_ci; + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + L->ci->top = L->top + LUA_MINSTACK; + L->allowhook = 0; /* cannot call hooks inside a hook */ + lua_unlock(L); + (*hook)(L, &ar); + lua_lock(L); + lua_assert(!L->allowhook); + L->allowhook = 1; + L->ci->top = restorestack(L, ci_top); + L->top = restorestack(L, top); + } +} + + +static void adjust_varargs (lua_State *L, int nfixargs, StkId base) { + int i; + Table *htab; + TObject nname; + int actual = L->top - base; /* actual number of arguments */ + if (actual < nfixargs) { + luaD_checkstack(L, nfixargs - actual); + for (; actual < nfixargs; ++actual) + setnilvalue(L->top++); + } + actual -= nfixargs; /* number of extra arguments */ + htab = luaH_new(L, actual, 1); /* create `arg' table */ + for (i=0; itop - actual + i); + /* store counter in field `n' */ + setsvalue(&nname, luaS_newliteral(L, "n")); + setnvalue(luaH_set(L, htab, &nname), cast(lua_Number, actual)); + L->top -= actual; /* remove extra elements from the stack */ + sethvalue(L->top, htab); + incr_top(L); +} + + +static StkId tryfuncTM (lua_State *L, StkId func) { + const TObject *tm = luaT_gettmbyobj(L, func, TM_CALL); + StkId p; + ptrdiff_t funcr = savestack(L, func); + if (!ttisfunction(tm)) + luaG_typeerror(L, func, "call"); + /* Open a hole inside the stack at `func' */ + for (p = L->top; p > func; p--) setobjs2s(p, p-1); + incr_top(L); + func = restorestack(L, funcr); /* previous call may change stack */ + setobj2s(func, tm); /* tag method is the new function to be called */ + return func; +} + + +StkId luaD_precall (lua_State *L, StkId func) { + LClosure *cl; + ptrdiff_t funcr = savestack(L, func); + if (!ttisfunction(func)) /* `func' is not a function? */ + func = tryfuncTM(L, func); /* check the `function' tag method */ + if (L->ci + 1 == L->end_ci) luaD_growCI(L); + else condhardstacktests(luaD_reallocCI(L, L->size_ci)); + cl = &clvalue(func)->l; + if (!cl->isC) { /* Lua function? prepare its call */ + CallInfo *ci; + Proto *p = cl->p; + if (p->is_vararg) /* varargs? */ + adjust_varargs(L, p->numparams, func+1); + luaD_checkstack(L, p->maxstacksize); + ci = ++L->ci; /* now `enter' new function */ + L->base = L->ci->base = restorestack(L, funcr) + 1; + ci->top = L->base + p->maxstacksize; + ci->u.l.savedpc = p->code; /* starting point */ + ci->u.l.tailcalls = 0; + ci->state = CI_SAVEDPC; + while (L->top < ci->top) + setnilvalue(L->top++); + L->top = ci->top; + return NULL; + } + else { /* if is a C function, call it */ + CallInfo *ci; + int n; + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + ci = ++L->ci; /* now `enter' new function */ + L->base = L->ci->base = restorestack(L, funcr) + 1; + ci->top = L->top + LUA_MINSTACK; + ci->state = CI_C; /* a C function */ + if (L->hookmask & LUA_MASKCALL) + luaD_callhook(L, LUA_HOOKCALL, -1); + lua_unlock(L); +#ifdef LUA_COMPATUPVALUES + lua_pushupvalues(L); +#endif + n = (*clvalue(L->base - 1)->c.f)(L); /* do the actual call */ + lua_lock(L); + return L->top - n; + } +} + + +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 (!(L->ci->state & CI_C)) { /* Lua function? */ + while (L->ci->u.l.tailcalls--) /* call hook for eventual tail calls */ + luaD_callhook(L, LUA_HOOKTAILRET, -1); + } + return restorestack(L, fr); +} + + +void luaD_poscall (lua_State *L, int wanted, StkId firstResult) { + StkId res; + if (L->hookmask & LUA_MASKRET) + firstResult = callrethooks(L, firstResult); + res = L->base - 1; /* res == final position of 1st result */ + L->ci--; + L->base = L->ci->base; /* restore base */ + /* move results to correct place */ + while (wanted != 0 && firstResult < L->top) { + setobjs2s(res++, firstResult++); + wanted--; + } + while (wanted-- > 0) + setnilvalue(res++); + L->top = res; +} + + +/* +** 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. +*/ +void luaD_call (lua_State *L, StkId func, int nResults) { + StkId firstResult; + lua_assert(!(L->ci->state & CI_CALLING)); + if (++L->nCcalls >= LUA_MAXCCALLS) { + if (L->nCcalls == LUA_MAXCCALLS) + luaG_runerror(L, "C stack overflow"); + else if (L->nCcalls >= (LUA_MAXCCALLS + (LUA_MAXCCALLS>>3))) + luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ + } + firstResult = luaD_precall(L, func); + if (firstResult == NULL) /* is a Lua function? */ + firstResult = luaV_execute(L); /* call it */ + luaD_poscall(L, nResults, firstResult); + L->nCcalls--; + luaC_checkGC(L); +} + + +static void resume (lua_State *L, void *ud) { + StkId firstResult; + int nargs = *cast(int *, ud); + CallInfo *ci = L->ci; + if (ci == L->base_ci) { /* no activation record? */ + lua_assert(nargs < L->top - L->base); + luaD_precall(L, L->top - (nargs + 1)); /* start coroutine */ + } + else { /* inside a yield */ + lua_assert(ci->state & CI_YIELD); + if (ci->state & CI_C) { /* `common' yield? */ + /* finish interrupted execution of `OP_CALL' */ + int nresults; + lua_assert((ci-1)->state & CI_SAVEDPC); + lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL || + GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL); + nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1; + luaD_poscall(L, nresults, L->top - nargs); /* complete it */ + if (nresults >= 0) L->top = L->ci->top; + } + else { /* yielded inside a hook: just continue its execution */ + ci->state &= ~CI_YIELD; + } + } + firstResult = luaV_execute(L); + if (firstResult != NULL) /* return? */ + luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */ +} + + +static int resume_error (lua_State *L, const char *msg) { + L->top = L->ci->base; + setsvalue2s(L->top, luaS_new(L, msg)); + incr_top(L); + lua_unlock(L); + return LUA_ERRRUN; +} + + +LUA_API int lua_resume (lua_State *L, int nargs) { + int status; + lu_byte old_allowhooks; + lua_lock(L); + if (L->ci == L->base_ci) { + if (nargs >= L->top - L->base) + return resume_error(L, "cannot resume dead coroutine"); + } + else if (!(L->ci->state & CI_YIELD)) /* not inside a yield? */ + return resume_error(L, "cannot resume non-suspended coroutine"); + old_allowhooks = L->allowhook; + lua_assert(L->errfunc == 0 && L->nCcalls == 0); + status = luaD_rawrunprotected(L, resume, &nargs); + if (status != 0) { /* error? */ + L->ci = L->base_ci; /* go back to initial level */ + L->base = L->ci->base; + L->nCcalls = 0; + luaF_close(L, L->base); /* close eventual pending closures */ + seterrorobj(L, status, L->base); + L->allowhook = old_allowhooks; + restore_stack_limit(L); + } + lua_unlock(L); + return status; +} + + +LUA_API int lua_yield (lua_State *L, int nresults) { + CallInfo *ci; + lua_lock(L); + ci = L->ci; + if (L->nCcalls > 0) + luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); + if (ci->state & CI_C) { /* usual yield */ + if ((ci-1)->state & CI_C) + luaG_runerror(L, "cannot yield a C function"); + if (L->top - nresults > L->base) { /* is there garbage in the stack? */ + int i; + for (i=0; ibase + i, L->top - nresults + i); + L->top = L->base + nresults; + } + } /* else it's an yield inside a hook: nothing to do */ + ci->state |= CI_YIELD; + lua_unlock(L); + return -1; +} + + +int luaD_pcall (lua_State *L, Pfunc func, void *u, + ptrdiff_t old_top, ptrdiff_t ef) { + int status; + unsigned short oldnCcalls = L->nCcalls; + ptrdiff_t old_ci = saveci(L, L->ci); + 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 */ + seterrorobj(L, status, oldtop); + L->nCcalls = oldnCcalls; + L->ci = restoreci(L, old_ci); + L->base = L->ci->base; + L->allowhook = old_allowhooks; + restore_stack_limit(L); + } + L->errfunc = old_errfunc; + return status; +} + + + +/* +** Execute a protected parser. +*/ +struct SParser { /* data to `f_parser' */ + ZIO *z; + Mbuffer buff; /* buffer to be used by the scanner */ + int bin; +}; + +static void f_parser (lua_State *L, void *ud) { + struct SParser *p; + Proto *tf; + Closure *cl; + luaC_checkGC(L); + p = cast(struct SParser *, ud); + tf = p->bin ? luaU_undump(L, p->z, &p->buff) : luaY_parser(L, p->z, &p->buff); + cl = luaF_newLclosure(L, 0, gt(L)); + cl->l.p = tf; + setclvalue(L->top, cl); + incr_top(L); +} + + +int luaD_protectedparser (lua_State *L, ZIO *z, int bin) { + struct SParser p; + int status; + ptrdiff_t oldtopr = savestack(L, L->top); /* save current top */ + p.z = z; p.bin = bin; + luaZ_initbuffer(L, &p.buff); + status = luaD_rawrunprotected(L, f_parser, &p); + luaZ_freebuffer(L, &p.buff); + if (status != 0) { /* error? */ + StkId oldtop = restorestack(L, oldtopr); + seterrorobj(L, status, oldtop); + } + return status; +} + + diff --git a/src/ldo.h b/src/ldo.h new file mode 100644 index 0000000..2a61bf5 --- /dev/null +++ b/src/ldo.h @@ -0,0 +1,60 @@ +/* +** $Id: ldo.h,v 1.56 2002/12/04 17:29:32 roberto Exp $ +** Stack and Call structure of Lua +** See Copyright Notice in lua.h +*/ + +#ifndef ldo_h +#define ldo_h + + +#include "lobject.h" +#include "lstate.h" +#include "lzio.h" + + +/* +** macro to control inclusion of some hard tests on stack reallocation +*/ +#ifndef HARDSTACKTESTS +#define condhardstacktests(x) { /* empty */ } +#else +#define condhardstacktests(x) x +#endif + + +#define luaD_checkstack(L,n) \ + if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TObject)) \ + luaD_growstack(L, n); \ + else condhardstacktests(luaD_reallocstack(L, L->stacksize)); + + +#define incr_top(L) {luaD_checkstack(L,1); L->top++;} + +#define savestack(L,p) ((char *)(p) - (char *)L->stack) +#define restorestack(L,n) ((TObject *)((char *)L->stack + (n))) + +#define saveci(L,p) ((char *)(p) - (char *)L->base_ci) +#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) + + +/* type of protected functions, to be ran by `runprotected' */ +typedef void (*Pfunc) (lua_State *L, void *ud); + +void luaD_resetprotection (lua_State *L); +int luaD_protectedparser (lua_State *L, ZIO *z, int bin); +void luaD_callhook (lua_State *L, int event, int line); +StkId luaD_precall (lua_State *L, StkId func); +void luaD_call (lua_State *L, StkId func, int nResults); +int luaD_pcall (lua_State *L, Pfunc func, void *u, + ptrdiff_t oldtop, ptrdiff_t ef); +void luaD_poscall (lua_State *L, int wanted, StkId firstResult); +void luaD_reallocCI (lua_State *L, int newsize); +void luaD_reallocstack (lua_State *L, int newsize); +void luaD_growstack (lua_State *L, int n); + +void luaD_throw (lua_State *L, int errcode); +int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); + + +#endif diff --git a/src/ldump.cpp b/src/ldump.cpp new file mode 100644 index 0000000..234b011 --- /dev/null +++ b/src/ldump.cpp @@ -0,0 +1,170 @@ +/* +** $Id: ldump.c,v 1.4 2003/02/11 23:52:12 lhf Exp $ +** save bytecodes +** See Copyright Notice in lua.h +*/ + +#include + +#define ldump_c + +#include "lua.h" + +#include "lobject.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lundump.h" + +#define DumpVector(b,n,size,D) DumpBlock(b,(n)*(size),D) +#define DumpLiteral(s,D) DumpBlock("" s,(sizeof(s))-1,D) + +typedef struct { + lua_State* L; + lua_Chunkwriter write; + void* data; +} DumpState; + +static void DumpBlock(const void* b, size_t size, DumpState* D) +{ + lua_unlock(D->L); + (*D->write)(D->L,b,size,D->data); + lua_lock(D->L); +} + +static void DumpByte(int y, DumpState* D) +{ + char x=(char)y; + DumpBlock(&x,sizeof(x),D); +} + +static void DumpInt(int x, DumpState* D) +{ + DumpBlock(&x,sizeof(x),D); +} + +static void DumpSize(size_t x, DumpState* D) +{ + DumpBlock(&x,sizeof(x),D); +} + +static void DumpNumber(lua_Number x, DumpState* D) +{ + DumpBlock(&x,sizeof(x),D); +} + +static void DumpString(TString* s, DumpState* D) +{ + if (s==NULL || getstr(s)==NULL) + DumpSize(0,D); + else + { + size_t size=s->tsv.len+1; /* include trailing '\0' */ + DumpSize(size,D); + DumpBlock(getstr(s),size,D); + } +} + +static void DumpCode(const Proto* f, DumpState* D) +{ + DumpInt(f->sizecode,D); + DumpVector(f->code,f->sizecode,sizeof(*f->code),D); +} + +static void DumpLocals(const Proto* f, DumpState* D) +{ + int i,n=f->sizelocvars; + DumpInt(n,D); + for (i=0; ilocvars[i].varname,D); + DumpInt(f->locvars[i].startpc,D); + DumpInt(f->locvars[i].endpc,D); + } +} + +static void DumpLines(const Proto* f, DumpState* D) +{ + DumpInt(f->sizelineinfo,D); + DumpVector(f->lineinfo,f->sizelineinfo,sizeof(*f->lineinfo),D); +} + +static void DumpUpvalues(const Proto* f, DumpState* D) +{ + int i,n=f->sizeupvalues; + DumpInt(n,D); + for (i=0; iupvalues[i],D); +} + +static void DumpFunction(const Proto* f, const TString* p, DumpState* D); + +static void DumpConstants(const Proto* f, DumpState* D) +{ + int i,n; + DumpInt(n=f->sizek,D); + for (i=0; ik[i]; + DumpByte(ttype(o),D); + switch (ttype(o)) + { + case LUA_TNUMBER: + DumpNumber(nvalue(o),D); + break; + case LUA_TSTRING: + DumpString(tsvalue(o),D); + break; + case LUA_TNIL: + break; + default: + lua_assert(0); /* cannot happen */ + break; + } + } + DumpInt(n=f->sizep,D); + for (i=0; ip[i],f->source,D); +} + +static void DumpFunction(const Proto* f, const TString* p, DumpState* D) +{ + DumpString((f->source==p) ? NULL : f->source,D); + DumpInt(f->lineDefined,D); + DumpByte(f->nups,D); + DumpByte(f->numparams,D); + DumpByte(f->is_vararg,D); + DumpByte(f->maxstacksize,D); + DumpLines(f,D); + DumpLocals(f,D); + DumpUpvalues(f,D); + DumpConstants(f,D); + DumpCode(f,D); +} + +static void DumpHeader(DumpState* D) +{ + DumpLiteral(LUA_SIGNATURE,D); + DumpByte(VERSION,D); + DumpByte(luaU_endianness(),D); + DumpByte(sizeof(int),D); + DumpByte(sizeof(size_t),D); + DumpByte(sizeof(Instruction),D); + DumpByte(SIZE_OP,D); + DumpByte(SIZE_A,D); + DumpByte(SIZE_B,D); + DumpByte(SIZE_C,D); + DumpByte(sizeof(lua_Number),D); + DumpNumber(TEST_NUMBER,D); +} + +/* +** dump function as precompiled chunk +*/ +void luaU_dump (lua_State* L, const Proto* Main, lua_Chunkwriter w, void* data) +{ + DumpState D; + D.L=L; + D.write=w; + D.data=data; + DumpHeader(&D); + DumpFunction(Main,NULL,&D); +} + diff --git a/src/lfunc.cpp b/src/lfunc.cpp new file mode 100644 index 0000000..31044fa --- /dev/null +++ b/src/lfunc.cpp @@ -0,0 +1,135 @@ +/* +** $Id: lfunc.c,v 1.67 2003/03/18 12:50:04 roberto Exp $ +** Auxiliary functions to manipulate prototypes and closures +** See Copyright Notice in lua.h +*/ + + +#include + +#define lfunc_c + +#include "lua.h" + +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" + + +#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ + cast(int, sizeof(TObject)*((n)-1))) + +#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ + cast(int, sizeof(TObject *)*((n)-1))) + + + +Closure *luaF_newCclosure (lua_State *L, int nelems) { + Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); + luaC_link(L, valtogco(c), LUA_TFUNCTION); + c->c.isC = 1; + c->c.nupvalues = cast(lu_byte, nelems); + return c; +} + + +Closure *luaF_newLclosure (lua_State *L, int nelems, TObject *e) { + Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); + luaC_link(L, valtogco(c), LUA_TFUNCTION); + c->l.isC = 0; + c->l.g = *e; + c->l.nupvalues = cast(lu_byte, nelems); + return c; +} + + +UpVal *luaF_findupval (lua_State *L, StkId level) { + GCObject **pp = &L->openupval; + UpVal *p; + UpVal *v; + while ((p = ngcotouv(*pp)) != NULL && p->v >= level) { + if (p->v == level) return p; + pp = &p->next; + } + v = luaM_new(L, UpVal); /* not found: create a new one */ + v->tt = LUA_TUPVAL; + v->marked = 1; /* open upvalues should not be collected */ + v->v = level; /* current value lives in the stack */ + v->next = *pp; /* chain it in the proper position */ + *pp = valtogco(v); + return v; +} + + +void luaF_close (lua_State *L, StkId level) { + UpVal *p; + while ((p = ngcotouv(L->openupval)) != NULL && p->v >= level) { + setobj(&p->value, p->v); /* save current value (write barrier) */ + p->v = &p->value; /* now current value lives here */ + L->openupval = p->next; /* remove from `open' list */ + luaC_link(L, valtogco(p), LUA_TUPVAL); + } +} + + +Proto *luaF_newproto (lua_State *L) { + Proto *f = luaM_new(L, Proto); + luaC_link(L, valtogco(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->source = NULL; + return f; +} + + +void luaF_freeproto (lua_State *L, Proto *f) { + luaM_freearray(L, f->code, f->sizecode, Instruction); + luaM_freearray(L, f->p, f->sizep, Proto *); + luaM_freearray(L, f->k, f->sizek, TObject); + luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); + luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); + luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); + luaM_freelem(L, f); +} + + +void luaF_freeclosure (lua_State *L, Closure *c) { + int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) : + sizeLclosure(c->l.nupvalues); + luaM_free(L, c, size); +} + + +/* +** Look for n-th local variable at line `line' in function `func'. +** Returns NULL if not found. +*/ +const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { + int i; + for (i = 0; isizelocvars && 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 */ +} + diff --git a/src/lfunc.h b/src/lfunc.h new file mode 100644 index 0000000..5d53250 --- /dev/null +++ b/src/lfunc.h @@ -0,0 +1,25 @@ +/* +** $Id: lfunc.h,v 1.21 2003/03/18 12:50:04 roberto Exp $ +** Auxiliary functions to manipulate prototypes and closures +** See Copyright Notice in lua.h +*/ + +#ifndef lfunc_h +#define lfunc_h + + +#include "lobject.h" + + +Proto *luaF_newproto (lua_State *L); +Closure *luaF_newCclosure (lua_State *L, int nelems); +Closure *luaF_newLclosure (lua_State *L, int nelems, TObject *e); +UpVal *luaF_findupval (lua_State *L, StkId level); +void luaF_close (lua_State *L, StkId level); +void luaF_freeproto (lua_State *L, Proto *f); +void luaF_freeclosure (lua_State *L, Closure *c); + +const char *luaF_getlocalname (const Proto *func, int local_number, int pc); + + +#endif diff --git a/src/lgc.cpp b/src/lgc.cpp new file mode 100644 index 0000000..5e036d3 --- /dev/null +++ b/src/lgc.cpp @@ -0,0 +1,498 @@ +/* +** $Id: lgc.c,v 1.171a 2003/04/03 13:35:34 roberto Exp $ +** Garbage Collector +** See Copyright Notice in lua.h +*/ + +#include + +#define lgc_c + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + +typedef struct GCState { + GCObject *tmark; /* list of marked objects to be traversed */ + GCObject *wk; /* list of traversed key-weak tables (to be cleared) */ + GCObject *wv; /* list of traversed value-weak tables */ + GCObject *wkv; /* list of traversed key-value weak tables */ + global_State *g; +} GCState; + + +/* +** some userful bit tricks +*/ +#define setbit(x,b) ((x) |= (1<<(b))) +#define resetbit(x,b) ((x) &= cast(lu_byte, ~(1<<(b)))) +#define testbit(x,b) ((x) & (1<<(b))) + +#define unmark(x) resetbit((x)->gch.marked, 0) +#define ismarked(x) ((x)->gch.marked & ((1<<4)|1)) + +#define stringmark(s) setbit((s)->tsv.marked, 0) + + +#define isfinalized(u) (!testbit((u)->uv.marked, 1)) +#define markfinalized(u) resetbit((u)->uv.marked, 1) + + +#define KEYWEAKBIT 1 +#define VALUEWEAKBIT 2 +#define KEYWEAK (1<gch.marked, 0); /* mark object */ + switch (o->gch.tt) { + case LUA_TUSERDATA: { + markvalue(st, gcotou(o)->uv.metatable); + break; + } + case LUA_TFUNCTION: { + gcotocl(o)->c.gclist = st->tmark; + st->tmark = o; + break; + } + case LUA_TTABLE: { + gcotoh(o)->gclist = st->tmark; + st->tmark = o; + break; + } + case LUA_TTHREAD: { + gcototh(o)->gclist = st->tmark; + st->tmark = o; + break; + } + case LUA_TPROTO: { + gcotop(o)->gclist = st->tmark; + st->tmark = o; + break; + } + default: lua_assert(o->gch.tt == LUA_TSTRING); + } +} + + +static void marktmu (GCState *st) { + GCObject *u; + for (u = st->g->tmudata; u; u = u->gch.next) { + unmark(u); /* may be marked, if left from previous GC */ + reallymarkobject(st, u); + } +} + + +/* move `dead' udata that need finalization to list `tmudata' */ +size_t luaC_separateudata (lua_State *L) { + size_t deadmem = 0; + GCObject **p = &G(L)->rootudata; + GCObject *curr; + GCObject *collected = NULL; /* to collect udata with gc event */ + GCObject **lastcollected = &collected; + while ((curr = *p) != NULL) { + lua_assert(curr->gch.tt == LUA_TUSERDATA); + if (ismarked(curr) || isfinalized(gcotou(curr))) + p = &curr->gch.next; /* don't bother with them */ + + else if (fasttm(L, gcotou(curr)->uv.metatable, TM_GC) == NULL) { + markfinalized(gcotou(curr)); /* don't need finalization */ + p = &curr->gch.next; + } + else { /* must call its gc method */ + deadmem += sizeudata(gcotou(curr)->uv.len); + *p = curr->gch.next; + curr->gch.next = NULL; /* link `curr' at the end of `collected' list */ + *lastcollected = curr; + lastcollected = &curr->gch.next; + } + } + /* insert collected udata with gc event into `tmudata' list */ + *lastcollected = G(L)->tmudata; + G(L)->tmudata = collected; + return deadmem; +} + + +static void removekey (Node *n) { + setnilvalue(gval(n)); /* remove corresponding value ... */ + if (iscollectable(gkey(n))) + setttype(gkey(n), LUA_TNONE); /* dead key; remove it */ +} + + +static void traversetable (GCState *st, Table *h) { + int i; + int weakkey = 0; + int weakvalue = 0; + const TObject *mode; + markvalue(st, h->metatable); + lua_assert(h->lsizenode || h->node == st->g->dummynode); + mode = gfasttm(st->g, h->metatable, TM_MODE); + if (mode && ttisstring(mode)) { /* is there a weak mode? */ + weakkey = (strchr(svalue(mode), 'k') != NULL); + weakvalue = (strchr(svalue(mode), 'v') != NULL); + if (weakkey || weakvalue) { /* is really weak? */ + GCObject **weaklist; + h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ + h->marked |= cast(lu_byte, (weakkey << KEYWEAKBIT) | + (weakvalue << VALUEWEAKBIT)); + weaklist = (weakkey && weakvalue) ? &st->wkv : + (weakkey) ? &st->wk : + &st->wv; + h->gclist = *weaklist; /* must be cleared after GC, ... */ + *weaklist = valtogco(h); /* ... so put in the appropriate list */ + } + } + if (!weakvalue) { + i = h->sizearray; + while (i--) + markobject(st, &h->array[i]); + } + i = sizenode(h); + while (i--) { + Node *n = gnode(h, i); + if (!ttisnil(gval(n))) { + lua_assert(!ttisnil(gkey(n))); + condmarkobject(st, gkey(n), !weakkey); + condmarkobject(st, gval(n), !weakvalue); + } + } +} + + +static void traverseproto (GCState *st, Proto *f) { + int i; + stringmark(f->source); + for (i=0; isizek; i++) { /* mark literal strings */ + if (ttisstring(f->k+i)) + stringmark(tsvalue(f->k+i)); + } + for (i=0; isizeupvalues; i++) /* mark upvalue names */ + stringmark(f->upvalues[i]); + for (i=0; isizep; i++) /* mark nested protos */ + markvalue(st, f->p[i]); + for (i=0; isizelocvars; i++) /* mark local-variable names */ + stringmark(f->locvars[i].varname); + lua_assert(luaG_checkcode(f)); +} + + + +static void traverseclosure (GCState *st, Closure *cl) { + if (cl->c.isC) { + int i; + for (i=0; ic.nupvalues; i++) /* mark its upvalues */ + markobject(st, &cl->c.upvalue[i]); + } + else { + int i; + lua_assert(cl->l.nupvalues == cl->l.p->nups); + markvalue(st, hvalue(&cl->l.g)); + markvalue(st, cl->l.p); + for (i=0; il.nupvalues; i++) { /* mark its upvalues */ + UpVal *u = cl->l.upvals[i]; + if (!u->marked) { + markobject(st, &u->value); + u->marked = 1; + } + } + } +} + + +static void checkstacksizes (lua_State *L, StkId max) { + int used = L->ci - L->base_ci; /* number of `ci' in use */ + if (4*used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) + luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ + else condhardstacktests(luaD_reallocCI(L, L->size_ci)); + used = max - L->stack; /* part of stack in use */ + if (4*used < L->stacksize && 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) + luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ + else condhardstacktests(luaD_reallocstack(L, L->stacksize)); +} + + +static void traversestack (GCState *st, lua_State *L1) { + StkId o, lim; + CallInfo *ci; + markobject(st, gt(L1)); + lim = L1->top; + for (ci = L1->base_ci; ci <= L1->ci; ci++) { + lua_assert(ci->top <= L1->stack_last); + lua_assert(ci->state & (CI_C | CI_HASFRAME | CI_SAVEDPC)); + if (lim < ci->top) + lim = ci->top; + } + for (o = L1->stack; o < L1->top; o++) + markobject(st, o); + for (; o <= lim; o++) + setnilvalue(o); + checkstacksizes(L1, lim); +} + + +static void propagatemarks (GCState *st) { + while (st->tmark) { /* traverse marked objects */ + switch (st->tmark->gch.tt) { + case LUA_TTABLE: { + Table *h = gcotoh(st->tmark); + st->tmark = h->gclist; + traversetable(st, h); + break; + } + case LUA_TFUNCTION: { + Closure *cl = gcotocl(st->tmark); + st->tmark = cl->c.gclist; + traverseclosure(st, cl); + break; + } + case LUA_TTHREAD: { + lua_State *th = gcototh(st->tmark); + st->tmark = th->gclist; + traversestack(st, th); + break; + } + case LUA_TPROTO: { + Proto *p = gcotop(st->tmark); + st->tmark = p->gclist; + traverseproto(st, p); + break; + } + default: lua_assert(0); + } + } +} + + +static int valismarked (const TObject *o) { + if (ttisstring(o)) + stringmark(tsvalue(o)); /* strings are `values', so are never weak */ + return !iscollectable(o) || testbit(o->value.gc->gch.marked, 0); +} + + +/* +** clear collected keys from weaktables +*/ +static void cleartablekeys (GCObject *l) { + while (l) { + Table *h = gcotoh(l); + int i = sizenode(h); + lua_assert(h->marked & KEYWEAK); + while (i--) { + Node *n = gnode(h, i); + if (!valismarked(gkey(n))) /* key was collected? */ + removekey(n); /* remove entry from table */ + } + l = h->gclist; + } +} + + +/* +** clear collected values from weaktables +*/ +static void cleartablevalues (GCObject *l) { + while (l) { + Table *h = gcotoh(l); + int i = h->sizearray; + lua_assert(h->marked & VALUEWEAK); + while (i--) { + TObject *o = &h->array[i]; + if (!valismarked(o)) /* value was collected? */ + setnilvalue(o); /* remove value */ + } + i = sizenode(h); + while (i--) { + Node *n = gnode(h, i); + if (!valismarked(gval(n))) /* value was collected? */ + removekey(n); /* remove entry from table */ + } + l = h->gclist; + } +} + + +static void freeobj (lua_State *L, GCObject *o) { + switch (o->gch.tt) { + case LUA_TPROTO: luaF_freeproto(L, gcotop(o)); break; + case LUA_TFUNCTION: luaF_freeclosure(L, gcotocl(o)); break; + case LUA_TUPVAL: luaM_freelem(L, gcotouv(o)); break; + case LUA_TTABLE: luaH_free(L, gcotoh(o)); break; + case LUA_TTHREAD: { + lua_assert(gcototh(o) != L && gcototh(o) != G(L)->mainthread); + luaE_freethread(L, gcototh(o)); + break; + } + case LUA_TSTRING: { + luaM_free(L, o, sizestring(gcotots(o)->tsv.len)); + break; + } + case LUA_TUSERDATA: { + luaM_free(L, o, sizeudata(gcotou(o)->uv.len)); + break; + } + default: lua_assert(0); + } +} + + +static int sweeplist (lua_State *L, GCObject **p, int limit) { + GCObject *curr; + int count = 0; /* number of collected items */ + while ((curr = *p) != NULL) { + if (curr->gch.marked > limit) { + unmark(curr); + p = &curr->gch.next; + } + else { + count++; + *p = curr->gch.next; + freeobj(L, curr); + } + } + return count; +} + + +static void sweepstrings (lua_State *L, int all) { + int i; + for (i=0; istrt.size; i++) { /* for each list */ + G(L)->strt.nuse -= sweeplist(L, &G(L)->strt.hash[i], all); + } +} + + +static void checkSizes (lua_State *L, size_t deadmem) { + /* check size of string hash */ + if (G(L)->strt.nuse < cast(ls_nstr, G(L)->strt.size/4) && + G(L)->strt.size > MINSTRTABSIZE*2) + luaS_resize(L, G(L)->strt.size/2); /* table is too big */ + /* check size of buffer */ + if (luaZ_sizebuffer(&G(L)->buff) > LUA_MINBUFFER*2) { /* buffer too big? */ + size_t newsize = luaZ_sizebuffer(&G(L)->buff) / 2; + luaZ_resizebuffer(L, &G(L)->buff, newsize); + } + G(L)->GCthreshold = 2*G(L)->nblocks - deadmem; /* new threshold */ +} + + +static void do1gcTM (lua_State *L, Udata *udata) { + const TObject *tm = fasttm(L, udata->uv.metatable, TM_GC); + if (tm != NULL) { + setobj2s(L->top, tm); + setuvalue(L->top+1, udata); + L->top += 2; + luaD_call(L, L->top - 2, 0); + } +} + + +void luaC_callGCTM (lua_State *L) { + lu_byte oldah = L->allowhook; + L->allowhook = 0; /* stop debug hooks during GC tag methods */ + L->top++; /* reserve space to keep udata while runs its gc method */ + while (G(L)->tmudata != NULL) { + GCObject *o = G(L)->tmudata; + Udata *udata = gcotou(o); + G(L)->tmudata = udata->uv.next; /* remove udata from `tmudata' */ + udata->uv.next = G(L)->rootudata; /* return it to `root' list */ + G(L)->rootudata = o; + setuvalue(L->top - 1, udata); /* keep a reference to it */ + unmark(o); + markfinalized(udata); + do1gcTM(L, udata); + } + L->top--; + L->allowhook = oldah; /* restore hooks */ +} + + +void luaC_sweep (lua_State *L, int all) { + if (all) all = 256; /* larger than any mark */ + sweeplist(L, &G(L)->rootudata, all); + sweepstrings(L, all); + sweeplist(L, &G(L)->rootgc, all); +} + + +/* mark root set */ +static void markroot (GCState *st, lua_State *L) { + global_State *g = st->g; + markobject(st, defaultmeta(L)); + markobject(st, registry(L)); + traversestack(st, g->mainthread); + if (L != g->mainthread) /* another thread is running? */ + markvalue(st, L); /* cannot collect it */ +} + + +static size_t mark (lua_State *L) { + size_t deadmem; + GCState st; + GCObject *wkv; + st.g = G(L); + st.tmark = NULL; + st.wkv = st.wk = st.wv = NULL; + markroot(&st, L); + propagatemarks(&st); /* mark all reachable objects */ + cleartablevalues(st.wkv); + cleartablevalues(st.wv); + wkv = st.wkv; /* keys must be cleared after preserving udata */ + st.wkv = NULL; + st.wv = NULL; + deadmem = luaC_separateudata(L); /* separate userdata to be preserved */ + marktmu(&st); /* mark `preserved' userdata */ + propagatemarks(&st); /* remark, to propagate `preserveness' */ + cleartablekeys(wkv); + /* `propagatemarks' may resuscitate some weak tables; clear them too */ + cleartablekeys(st.wk); + cleartablevalues(st.wv); + cleartablekeys(st.wkv); + cleartablevalues(st.wkv); + return deadmem; +} + + +void luaC_collectgarbage (lua_State *L) { + size_t deadmem = mark(L); + luaC_sweep(L, 0); + checkSizes(L, deadmem); + luaC_callGCTM(L); +} + + +void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { + o->gch.next = G(L)->rootgc; + G(L)->rootgc = o; + o->gch.marked = 0; + o->gch.tt = tt; +} + diff --git a/src/lgc.h b/src/lgc.h new file mode 100644 index 0000000..3f4d748 --- /dev/null +++ b/src/lgc.h @@ -0,0 +1,25 @@ +/* +** $Id: lgc.h,v 1.19a 2003/02/28 19:45:15 roberto Exp $ +** Garbage Collector +** See Copyright Notice in lua.h +*/ + +#ifndef lgc_h +#define lgc_h + + +#include "lobject.h" + + +#define luaC_checkGC(L) { lua_assert(!(L->ci->state & CI_CALLING)); \ + if (G(L)->nblocks >= G(L)->GCthreshold) luaC_collectgarbage(L); } + + +size_t luaC_separateudata (lua_State *L); +void luaC_callGCTM (lua_State *L); +void luaC_sweep (lua_State *L, int all); +void luaC_collectgarbage (lua_State *L); +void luaC_link (lua_State *L, GCObject *o, lu_byte tt); + + +#endif diff --git a/src/lib/Makefile b/src/lib/Makefile new file mode 100644 index 0000000..3c6c07a --- /dev/null +++ b/src/lib/Makefile @@ -0,0 +1,27 @@ +# makefile for Lua standard library + +LUA= ../.. + +include $(LUA)/config + +EXTRA_DEFS= $(POPEN) $(TMPNAM) $(DEGREES) $(LOADLIB) + +OBJS= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o ltablib.o lstrlib.o loadlib.o +SRCS= lauxlib.c lbaselib.c ldblib.c liolib.c lmathlib.c ltablib.c lstrlib.c loadlib.c + +T= $(LIB)/liblualib.a + +all: $T + +$T: $(OBJS) + $(AR) $@ $(OBJS) + $(RANLIB) $@ + +clean: + rm -f $(OBJS) $T + +co: + co -q -f -M $(SRCS) + +klean: clean + rm -f $(SRCS) diff --git a/src/lib/README b/src/lib/README new file mode 100644 index 0000000..c5600b8 --- /dev/null +++ b/src/lib/README @@ -0,0 +1,8 @@ +This is the standard Lua library. + +The code of the standard library can be read as an example of how to export +C functions to Lua. The easiest library to read is lmathlib.c. + +The library is implemented entirely on top of the official Lua API as declared +in lua.h, using lauxlib.c, which contains several useful functions for writing +libraries. We encourage developers to use lauxlib.c in their own libraries. diff --git a/src/lib/lauxlib.cpp b/src/lib/lauxlib.cpp new file mode 100644 index 0000000..ee2d133 --- /dev/null +++ b/src/lib/lauxlib.cpp @@ -0,0 +1,591 @@ +/* +** $Id: lauxlib.c,v 1.100 2003/04/07 14:35:00 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include + + +/* This file uses only the official API of Lua. +** Any function declared here could be written as an application function. +*/ + +#define lauxlib_c + +#include "lua.h" + +#include "lauxlib.h" + + +/* number of prereserved references (for internal use) */ +#define RESERVED_REFS 2 + +/* reserved references */ +#define FREELIST_REF 1 /* free list of references */ +#define ARRAYSIZE_REF 2 /* array sizes */ + + +/* convert a stack index to positive */ +#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ + lua_gettop(L) + (i) + 1) + + +/* +** {====================================================== +** Error-report functions +** ======================================================= +*/ + + +LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { + lua_Debug ar; + lua_getstack(L, 0, &ar); + 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 `%s' on bad self (%s)", ar.name, extramsg); + } + if (ar.name == NULL) + ar.name = "?"; + return luaL_error(L, "bad argument #%d to `%s' (%s)", + narg, ar.name, extramsg); +} + + +LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { + const char *msg = lua_pushfstring(L, "%s expected, got %s", + tname, lua_typename(L, lua_type(L,narg))); + return luaL_argerror(L, narg, msg); +} + + +static void tag_error (lua_State *L, int narg, int tag) { + luaL_typerror(L, narg, lua_typename(L, tag)); +} + + +LUALIB_API void luaL_where (lua_State *L, int level) { + lua_Debug ar; + if (lua_getstack(L, level, &ar)) { /* check function at level */ + lua_getinfo(L, "Snl", &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... */ +} + + +LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + luaL_where(L, 1); + lua_pushvfstring(L, fmt, argp); + va_end(argp); + lua_concat(L, 2); + return lua_error(L); +} + +/* }====================================================== */ + + +LUALIB_API int luaL_findstring (const char *name, const char *const list[]) { + int i; + for (i=0; list[i]; i++) + if (strcmp(list[i], name) == 0) + return i; + return -1; /* name not found */ +} + + +LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { + lua_pushstring(L, tname); + lua_rawget(L, LUA_REGISTRYINDEX); /* 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_pushstring(L, tname); + lua_pushvalue(L, -2); + lua_rawset(L, LUA_REGISTRYINDEX); /* registry.name = metatable */ + lua_pushvalue(L, -1); + lua_pushstring(L, tname); + lua_rawset(L, LUA_REGISTRYINDEX); /* registry[metatable] = name */ + return 1; +} + + +LUALIB_API void luaL_getmetatable (lua_State *L, const char *tname) { + lua_pushstring(L, tname); + lua_rawget(L, LUA_REGISTRYINDEX); +} + + +LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { + const char *tn; + if (!lua_getmetatable(L, ud)) return NULL; /* no metatable? */ + lua_rawget(L, LUA_REGISTRYINDEX); /* get registry[metatable] */ + tn = lua_tostring(L, -1); + if (tn && (strcmp(tn, tname) == 0)) { + lua_pop(L, 1); + return lua_touserdata(L, ud); + } + else { + lua_pop(L, 1); + return NULL; + } +} + + +LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { + if (!lua_checkstack(L, space)) + luaL_error(L, "stack overflow (%s)", mes); +} + + +LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { + if (lua_type(L, narg) != t) + tag_error(L, narg, t); +} + + +LUALIB_API void luaL_checkany (lua_State *L, int narg) { + if (lua_type(L, narg) == LUA_TNONE) + luaL_argerror(L, narg, "value expected"); +} + + +LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { + const char *s = lua_tostring(L, narg); + if (!s) tag_error(L, narg, LUA_TSTRING); + if (len) *len = lua_strlen(L, narg); + return s; +} + + +LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, + const char *def, size_t *len) { + if (lua_isnoneornil(L, narg)) { + if (len) + *len = (def ? strlen(def) : 0); + return def; + } + else return luaL_checklstring(L, narg, len); +} + + +LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { + lua_Number d = lua_tonumber(L, narg); + if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ + tag_error(L, narg, LUA_TNUMBER); + return d; +} + + +LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { + if (lua_isnoneornil(L, narg)) return def; + else return luaL_checknumber(L, narg); +} + + +LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { + if (!lua_getmetatable(L, obj)) /* no metatable? */ + return 0; + lua_pushstring(L, event); + lua_rawget(L, -2); + if (lua_isnil(L, -1)) { + lua_pop(L, 2); /* remove metatable and metafield */ + return 0; + } + else { + lua_remove(L, -2); /* remove only metatable */ + return 1; + } +} + + +LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { + obj = abs_index(L, obj); + if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ + return 0; + lua_pushvalue(L, obj); + lua_call(L, 1, 1); + return 1; +} + + +LUALIB_API void luaL_openlib (lua_State *L, const char *libname, + const luaL_reg *l, int nup) { + if (libname) { + lua_pushstring(L, libname); + lua_gettable(L, LUA_GLOBALSINDEX); /* check whether lib already exists */ + if (lua_isnil(L, -1)) { /* no? */ + lua_pop(L, 1); + lua_newtable(L); /* create it */ + lua_pushstring(L, libname); + lua_pushvalue(L, -2); + lua_settable(L, LUA_GLOBALSINDEX); /* register it with given name */ + } + lua_insert(L, -(nup+1)); /* move library table to below upvalues */ + } + for (; l->name; l++) { + int i; + lua_pushstring(L, l->name); + for (i=0; ifunc, nup); + lua_settable(L, -(nup+3)); + } + lua_pop(L, nup); /* remove upvalues */ +} + + + +/* +** {====================================================== +** getn-setn: size for arrays +** ======================================================= +*/ + +static int checkint (lua_State *L, int topop) { + int n = (int)lua_tonumber(L, -1); + if (n == 0 && !lua_isnumber(L, -1)) n = -1; + lua_pop(L, topop); + return n; +} + + +static void getsizes (lua_State *L) { + lua_rawgeti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF); + 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, "__mode"); + lua_pushliteral(L, "k"); + lua_rawset(L, -3); /* metatable(N).__mode = "k" */ + lua_pushvalue(L, -1); + lua_rawseti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF); /* store in register */ + } +} + + +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_pushnumber(L, (lua_Number)n); + lua_rawset(L, t); + } + else { /* use `sizes' */ + getsizes(L); + lua_pushvalue(L, t); + lua_pushnumber(L, (lua_Number)n); + lua_rawset(L, -3); /* sizes[t] = n */ + lua_pop(L, 1); /* remove `sizes' */ + } +} + + +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; + for (n = 1; ; n++) { /* else must count elements */ + lua_rawgeti(L, t, n); + if (lua_isnil(L, -1)) break; + lua_pop(L, 1); + } + lua_pop(L, 1); + return n - 1; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + + +#define bufflen(B) ((B)->p - (B)->buffer) +#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) + +#define LIMIT (LUA_MINSTACK/2) + + +static int emptybuffer (luaL_Buffer *B) { + size_t l = bufflen(B); + if (l == 0) return 0; /* put nothing on stack */ + else { + lua_pushlstring(B->L, B->buffer, l); + B->p = B->buffer; + B->lvl++; + return 1; + } +} + + +static void adjuststack (luaL_Buffer *B) { + if (B->lvl > 1) { + lua_State *L = B->L; + int toget = 1; /* number of levels to concat */ + size_t toplen = lua_strlen(L, -1); + do { + size_t l = lua_strlen(L, -(toget+1)); + if (B->lvl - toget + 1 >= LIMIT || toplen > l) { + toplen += l; + toget++; + } + else break; + } while (toget < B->lvl); + lua_concat(L, toget); + B->lvl = B->lvl - toget + 1; + } +} + + +LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { + if (emptybuffer(B)) + adjuststack(B); + return B->buffer; +} + + +LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { + while (l--) + luaL_putchar(B, *s++); +} + + +LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { + luaL_addlstring(B, s, strlen(s)); +} + + +LUALIB_API void luaL_pushresult (luaL_Buffer *B) { + emptybuffer(B); + lua_concat(B->L, B->lvl); + B->lvl = 1; +} + + +LUALIB_API void luaL_addvalue (luaL_Buffer *B) { + lua_State *L = B->L; + size_t vl = lua_strlen(L, -1); + if (vl <= bufffree(B)) { /* fit into buffer? */ + memcpy(B->p, lua_tostring(L, -1), vl); /* put it there */ + B->p += vl; + lua_pop(L, 1); /* remove from stack */ + } + else { + if (emptybuffer(B)) + lua_insert(L, -2); /* put buffer before new value */ + B->lvl++; /* add new value into B stack */ + adjuststack(B); + } +} + + +LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { + B->L = L; + B->p = B->buffer; + B->lvl = 0; +} + +/* }====================================================== */ + + +LUALIB_API int luaL_ref (lua_State *L, int t) { + int ref; + t = abs_index(L, t); + if (lua_isnil(L, -1)) { + lua_pop(L, 1); /* remove from stack */ + return LUA_REFNIL; /* `nil' has a unique fixed reference */ + } + lua_rawgeti(L, t, FREELIST_REF); /* get first free element */ + ref = (int)lua_tonumber(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 = luaL_getn(L, t); + if (ref < RESERVED_REFS) + ref = RESERVED_REFS; /* skip reserved references */ + ref++; /* create new reference */ + luaL_setn(L, t, ref); + } + lua_rawseti(L, t, ref); + return ref; +} + + +LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { + if (ref >= 0) { + t = abs_index(L, t); + lua_rawgeti(L, t, FREELIST_REF); + lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */ + lua_pushnumber(L, (lua_Number)ref); + lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ + } +} + + + +/* +** {====================================================== +** Load functions +** ======================================================= +*/ + +typedef struct LoadF { + FILE *f; + char buff[LUAL_BUFFERSIZE]; +} LoadF; + + +static const char *getF (lua_State *L, void *ud, size_t *size) { + LoadF *lf = (LoadF *)ud; + (void)L; + if (feof(lf->f)) return NULL; + *size = fread(lf->buff, 1, LUAL_BUFFERSIZE, lf->f); + return (*size > 0) ? lf->buff : NULL; +} + + +static int errfile (lua_State *L, int fnameindex) { + const char *filename = lua_tostring(L, fnameindex) + 1; + lua_pushfstring(L, "cannot read %s: %s", filename, strerror(errno)); + lua_remove(L, fnameindex); + return LUA_ERRFILE; +} + + +LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { + LoadF lf; + int status, readstatus; + int c; + int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ + 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, fnameindex); /* unable to open file */ + c = ungetc(getc(lf.f), lf.f); + if (!(isspace(c) || isprint(c)) && lf.f != stdin) { /* binary file? */ + fclose(lf.f); + lf.f = fopen(filename, "rb"); /* reopen in binary mode */ + if (lf.f == NULL) return errfile(L, fnameindex); /* unable to reopen file */ + } + status = lua_load(L, getF, &lf, lua_tostring(L, -1)); + readstatus = ferror(lf.f); + if (lf.f != stdin) fclose(lf.f); /* close file (even in case of errors) */ + if (readstatus) { + lua_settop(L, fnameindex); /* ignore results from `lua_load' */ + return errfile(L, fnameindex); + } + lua_remove(L, fnameindex); + return status; +} + + +typedef struct LoadS { + const char *s; + size_t size; +} LoadS; + + +static const char *getS (lua_State *L, void *ud, size_t *size) { + LoadS *ls = (LoadS *)ud; + (void)L; + if (ls->size == 0) return NULL; + *size = ls->size; + ls->size = 0; + return ls->s; +} + + +LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, + const char *name) { + LoadS ls; + ls.s = buff; + ls.size = size; + return lua_load(L, getS, &ls, name); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** compatibility code +** ======================================================= +*/ + + +static void callalert (lua_State *L, int status) { + if (status != 0) { + lua_getglobal(L, "_ALERT"); + if (lua_isfunction(L, -1)) { + lua_insert(L, -2); + lua_call(L, 1, 0); + } + else { /* no _ALERT function; print it on stderr */ + fprintf(stderr, "%s\n", lua_tostring(L, -2)); + lua_pop(L, 2); /* remove error message and _ALERT */ + } + } +} + + +static int aux_do (lua_State *L, int status) { + if (status == 0) { /* parse OK? */ + status = lua_pcall(L, 0, LUA_MULTRET, 0); /* call main */ + } + callalert(L, status); + return status; +} + + +LUALIB_API int lua_dofile (lua_State *L, const char *filename) { + return aux_do(L, luaL_loadfile(L, filename)); +} + + +LUALIB_API int lua_dobuffer (lua_State *L, const char *buff, size_t size, + const char *name) { + return aux_do(L, luaL_loadbuffer(L, buff, size, name)); +} + + +LUALIB_API int lua_dostring (lua_State *L, const char *str) { + return lua_dobuffer(L, str, strlen(str), str); +} + +/* }====================================================== */ diff --git a/src/lib/lbaselib.c b/src/lib/lbaselib.c new file mode 100644 index 0000000..b6a4bae --- /dev/null +++ b/src/lib/lbaselib.c @@ -0,0 +1,675 @@ +/* +** $Id: lbaselib.c,v 1.130b 2003/04/03 13:35:34 roberto Exp $ +** Basic library +** See Copyright Notice in lua.h +*/ + + + +#include +#include +#include +#include + +#define lbaselib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + + +/* +** If your system does not support `stdout', you can just remove this function. +** If you need, you can define your own `print' function, following this +** model but changing `fputs' to put the strings at a proper place +** (a console window or a log file, for instance). +*/ +static int luaB_print (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + int i; + lua_getglobal(L, "tostring"); + for (i=1; i<=n; i++) { + const char *s; + 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, "`tostring' must return a string to `print'"); + if (i>1) fputs("\t", stdout); + fputs(s, stdout); + lua_pop(L, 1); /* pop result */ + } + fputs("\n", stdout); + return 0; +} + + +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)) { + lua_pushnumber(L, lua_tonumber(L, 1)); + return 1; + } + } + else { + const char *s1 = luaL_checkstring(L, 1); + char *s2; + unsigned long n; + luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); + n = strtoul(s1, &s2, base); + if (s1 != s2) { /* at least one valid digit? */ + while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ + if (*s2 == '\0') { /* no invalid trailing characters? */ + lua_pushnumber(L, (lua_Number)n); + return 1; + } + } + } + lua_pushnil(L); /* else not a number */ + return 1; +} + + +static int luaB_error (lua_State *L) { + int level = luaL_optint(L, 2, 1); + luaL_checkany(L, 1); + if (!lua_isstring(L, 1) || level == 0) + lua_pushvalue(L, 1); /* propagate error message without changes */ + else { /* add extra information */ + luaL_where(L, level); + lua_pushvalue(L, 1); + lua_concat(L, 2); + } + return lua_error(L); +} + + +static int luaB_getmetatable (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_getmetatable(L, 1)) { + lua_pushnil(L); + return 1; /* no metatable */ + } + luaL_getmetafield(L, 1, "__metatable"); + return 1; /* returns either __metatable field (if present) or metatable */ +} + + +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")) + luaL_error(L, "cannot change a protected metatable"); + lua_settop(L, 2); + lua_setmetatable(L, 1); + return 1; +} + + +static void getfunc (lua_State *L) { + if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); + else { + lua_Debug ar; + int level = luaL_optint(L, 1, 1); + luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); + if (lua_getstack(L, level, &ar) == 0) + luaL_argerror(L, 1, "invalid level"); + lua_getinfo(L, "f", &ar); + if (lua_isnil(L, -1)) + luaL_error(L, "no function environment for tail call at level %d", + level); + } +} + + +static int aux_getfenv (lua_State *L) { + lua_getfenv(L, -1); + lua_pushliteral(L, "__fenv"); + lua_rawget(L, -2); + return !lua_isnil(L, -1); +} + + +static int luaB_getfenv (lua_State *L) { + getfunc(L); + if (!aux_getfenv(L)) /* __fenv not defined? */ + lua_pop(L, 1); /* remove it, to return real environment */ + return 1; +} + + +static int luaB_setfenv (lua_State *L) { + luaL_checktype(L, 2, LUA_TTABLE); + getfunc(L); + if (aux_getfenv(L)) /* __fenv defined? */ + luaL_error(L, "`setfenv' cannot change a protected environment"); + else + lua_pop(L, 2); /* remove __fenv and real environment table */ + lua_pushvalue(L, 2); + if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) + lua_replace(L, LUA_GLOBALSINDEX); + else if (lua_setfenv(L, -2) == 0) + luaL_error(L, "`setfenv' cannot change environment of given function"); + return 0; +} + + +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; +} + + +static int luaB_rawget (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + lua_rawget(L, 1); + return 1; +} + +static int luaB_rawset (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + luaL_checkany(L, 3); + lua_rawset(L, 1); + return 1; +} + + +static int luaB_gcinfo (lua_State *L) { + lua_pushnumber(L, (lua_Number)lua_getgccount(L)); + lua_pushnumber(L, (lua_Number)lua_getgcthreshold(L)); + return 2; +} + + +static int luaB_collectgarbage (lua_State *L) { + lua_setgcthreshold(L, luaL_optint(L, 1, 0)); + return 0; +} + + +static int luaB_type (lua_State *L) { + luaL_checkany(L, 1); + lua_pushstring(L, lua_typename(L, lua_type(L, 1))); + return 1; +} + + +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)) + return 2; + else { + lua_pushnil(L); + return 1; + } +} + + +static int luaB_pairs (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_pushliteral(L, "next"); + lua_rawget(L, LUA_GLOBALSINDEX); /* return generator, */ + lua_pushvalue(L, 1); /* state, */ + lua_pushnil(L); /* and initial value */ + return 3; +} + + +static int luaB_ipairs (lua_State *L) { + lua_Number i = lua_tonumber(L, 2); + luaL_checktype(L, 1, LUA_TTABLE); + if (i == 0 && lua_isnone(L, 2)) { /* `for' start? */ + lua_pushliteral(L, "ipairs"); + lua_rawget(L, LUA_GLOBALSINDEX); /* return generator, */ + lua_pushvalue(L, 1); /* state, */ + lua_pushnumber(L, 0); /* and initial value */ + return 3; + } + else { /* `for' step */ + i++; /* next value */ + lua_pushnumber(L, i); + lua_rawgeti(L, 1, (int)i); + return (lua_isnil(L, -1)) ? 0 : 2; + } +} + + +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 */ + } +} + + +static int luaB_loadstring (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + const char *chunkname = luaL_optstring(L, 2, s); + return load_aux(L, luaL_loadbuffer(L, s, l, chunkname)); +} + + +static int luaB_loadfile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + return load_aux(L, luaL_loadfile(L, fname)); +} + + +static int luaB_dofile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + int n = lua_gettop(L); + int status = luaL_loadfile(L, fname); + if (status != 0) lua_error(L); + lua_call(L, 0, LUA_MULTRET); + return lua_gettop(L) - n; +} + + +static int luaB_assert (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_toboolean(L, 1)) + return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); + lua_settop(L, 1); + return 1; +} + + +static int luaB_unpack (lua_State *L) { + int n, i; + luaL_checktype(L, 1, LUA_TTABLE); + n = luaL_getn(L, 1); + luaL_checkstack(L, n, "table too big to unpack"); + for (i=1; i<=n; i++) /* push arg[1...n] */ + lua_rawgeti(L, 1, i); + return n; +} + + +static int luaB_pcall (lua_State *L) { + int status; + luaL_checkany(L, 1); + status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); + lua_pushboolean(L, (status == 0)); + lua_insert(L, 1); + return lua_gettop(L); /* return status + all results */ +} + + +static int luaB_xpcall (lua_State *L) { + int status; + luaL_checkany(L, 2); + lua_settop(L, 2); + lua_insert(L, 1); /* put error function under function to be called */ + status = lua_pcall(L, 0, LUA_MULTRET, 1); + lua_pushboolean(L, (status == 0)); + lua_replace(L, 1); + return lua_gettop(L); /* return status + all results */ +} + + +static int luaB_tostring (lua_State *L) { + char buff[128]; + luaL_checkany(L, 1); + if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ + return 1; /* use its value */ + switch (lua_type(L, 1)) { + case LUA_TNUMBER: + lua_pushstring(L, lua_tostring(L, 1)); + return 1; + case LUA_TSTRING: + lua_pushvalue(L, 1); + return 1; + case LUA_TBOOLEAN: + lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); + return 1; + case LUA_TTABLE: + sprintf(buff, "table: %p", lua_topointer(L, 1)); + break; + case LUA_TFUNCTION: + sprintf(buff, "function: %p", lua_topointer(L, 1)); + break; + case LUA_TUSERDATA: + case LUA_TLIGHTUSERDATA: + sprintf(buff, "userdata: %p", lua_touserdata(L, 1)); + break; + case LUA_TTHREAD: + sprintf(buff, "thread: %p", (void *)lua_tothread(L, 1)); + break; + case LUA_TNIL: + lua_pushliteral(L, "nil"); + return 1; + } + lua_pushstring(L, buff); + return 1; +} + + +static int luaB_newproxy (lua_State *L) { + lua_settop(L, 1); + lua_newuserdata(L, 0); /* create proxy */ + if (lua_toboolean(L, 1) == 0) + return 1; /* no metatable */ + else if (lua_isboolean(L, 1)) { + lua_newtable(L); /* create a new metatable `m' ... */ + lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */ + lua_pushboolean(L, 1); + lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */ + } + else { + int validproxy = 0; /* to check if weaktable[metatable(u)] == true */ + if (lua_getmetatable(L, 1)) { + lua_rawget(L, lua_upvalueindex(1)); + validproxy = lua_toboolean(L, -1); + lua_pop(L, 1); /* remove value */ + } + luaL_argcheck(L, validproxy, 1, "boolean or proxy expected"); + lua_getmetatable(L, 1); /* metatable is valid; get it */ + } + lua_setmetatable(L, 2); + return 1; +} + + +/* +** {====================================================== +** `require' function +** ======================================================= +*/ + + +/* name of global that holds table with loaded packages */ +#define REQTAB "_LOADED" + +/* name of global that holds the search path for packages */ +#define LUA_PATH "LUA_PATH" + +#ifndef LUA_PATH_SEP +#define LUA_PATH_SEP ';' +#endif + +#ifndef LUA_PATH_MARK +#define LUA_PATH_MARK '?' +#endif + +#ifndef LUA_PATH_DEFAULT +#define LUA_PATH_DEFAULT "?;?.lua" +#endif + + +static const char *getpath (lua_State *L) { + const char *path; + lua_getglobal(L, LUA_PATH); /* try global variable */ + path = lua_tostring(L, -1); + lua_pop(L, 1); + if (path) return path; + path = getenv(LUA_PATH); /* else try environment variable */ + if (path) return path; + return LUA_PATH_DEFAULT; /* else use default */ +} + + +static const char *pushnextpath (lua_State *L, const char *path) { + const char *l; + if (*path == '\0') return NULL; /* no more paths */ + if (*path == LUA_PATH_SEP) path++; /* skip separator */ + l = strchr(path, LUA_PATH_SEP); /* find next separator */ + if (l == NULL) l = path+strlen(path); + lua_pushlstring(L, path, l - path); /* directory name */ + return l; +} + + +static void pushcomposename (lua_State *L) { + const char *path = lua_tostring(L, -1); + const char *wild; + int n = 1; + while ((wild = strchr(path, LUA_PATH_MARK)) != NULL) { + /* is there stack space for prefix, name, and eventual last sufix? */ + luaL_checkstack(L, 3, "too many marks in a path component"); + lua_pushlstring(L, path, wild - path); /* push prefix */ + lua_pushvalue(L, 1); /* push package name (in place of MARK) */ + path = wild + 1; /* continue after MARK */ + n += 2; + } + lua_pushstring(L, path); /* push last sufix (`n' already includes this) */ + lua_concat(L, n); +} + + +static int luaB_require (lua_State *L) { + const char *path; + int status = LUA_ERRFILE; /* not found (yet) */ + luaL_checkstring(L, 1); + lua_settop(L, 1); + lua_getglobal(L, REQTAB); + if (!lua_istable(L, 2)) return luaL_error(L, "`" REQTAB "' is not a table"); + path = getpath(L); + lua_pushvalue(L, 1); /* check package's name in book-keeping table */ + lua_rawget(L, 2); + if (lua_toboolean(L, -1)) /* is it there? */ + return 1; /* package is already loaded; return its result */ + else { /* must load it */ + while (status == LUA_ERRFILE) { + lua_settop(L, 3); /* reset stack position */ + if ((path = pushnextpath(L, path)) == NULL) break; + pushcomposename(L); + status = luaL_loadfile(L, lua_tostring(L, -1)); /* try to load it */ + } + } + switch (status) { + case 0: { + lua_getglobal(L, "_REQUIREDNAME"); /* save previous name */ + lua_insert(L, -2); /* put it below function */ + lua_pushvalue(L, 1); + lua_setglobal(L, "_REQUIREDNAME"); /* set new name */ + lua_call(L, 0, 1); /* run loaded module */ + lua_insert(L, -2); /* put result below previous name */ + lua_setglobal(L, "_REQUIREDNAME"); /* reset to previous name */ + if (lua_isnil(L, -1)) { /* no/nil return? */ + lua_pushboolean(L, 1); + lua_replace(L, -2); /* replace to true */ + } + lua_pushvalue(L, 1); + lua_pushvalue(L, -2); + lua_rawset(L, 2); /* mark it as loaded */ + return 1; /* return value */ + } + case LUA_ERRFILE: { /* file not found */ + return luaL_error(L, "could not load package `%s' from path `%s'", + lua_tostring(L, 1), getpath(L)); + } + default: { + return luaL_error(L, "error loading package `%s' (%s)", + lua_tostring(L, 1), lua_tostring(L, -1)); + } + } +} + +/* }====================================================== */ + + +static const luaL_reg base_funcs[] = { + {"error", luaB_error}, + {"getmetatable", luaB_getmetatable}, + {"setmetatable", luaB_setmetatable}, + {"getfenv", luaB_getfenv}, + {"setfenv", luaB_setfenv}, + {"next", luaB_next}, + {"ipairs", luaB_ipairs}, + {"pairs", luaB_pairs}, + {"print", luaB_print}, + {"tonumber", luaB_tonumber}, + {"tostring", luaB_tostring}, + {"type", luaB_type}, + {"assert", luaB_assert}, + {"unpack", luaB_unpack}, + {"rawequal", luaB_rawequal}, + {"rawget", luaB_rawget}, + {"rawset", luaB_rawset}, + {"pcall", luaB_pcall}, + {"xpcall", luaB_xpcall}, + {"collectgarbage", luaB_collectgarbage}, + {"gcinfo", luaB_gcinfo}, + {"loadfile", luaB_loadfile}, + {"dofile", luaB_dofile}, + {"loadstring", luaB_loadstring}, + {"require", luaB_require}, + {NULL, NULL} +}; + + +/* +** {====================================================== +** Coroutine library +** ======================================================= +*/ + +static int auxresume (lua_State *L, lua_State *co, int narg) { + int status; + if (!lua_checkstack(co, narg)) + luaL_error(L, "too many arguments to resume"); + lua_xmove(L, co, narg); + status = lua_resume(co, narg); + if (status == 0) { + int nres = lua_gettop(co); + if (!lua_checkstack(L, nres)) + luaL_error(L, "too many results to resume"); + lua_xmove(co, L, nres); /* move yielded values */ + return nres; + } + else { + lua_xmove(co, L, 1); /* move error message */ + return -1; /* error flag */ + } +} + + +static int luaB_coresume (lua_State *L) { + lua_State *co = lua_tothread(L, 1); + int r; + luaL_argcheck(L, co, 1, "coroutine expected"); + r = auxresume(L, co, lua_gettop(L) - 1); + if (r < 0) { + lua_pushboolean(L, 0); + lua_insert(L, -2); + return 2; /* return false + error message */ + } + else { + lua_pushboolean(L, 1); + lua_insert(L, -(r + 1)); + return r + 1; /* return true + `resume' returns */ + } +} + + +static int luaB_auxwrap (lua_State *L) { + lua_State *co = lua_tothread(L, lua_upvalueindex(1)); + int r = auxresume(L, co, lua_gettop(L)); + if (r < 0) { + if (lua_isstring(L, -1)) { /* error object is a string? */ + luaL_where(L, 1); /* add extra info */ + lua_insert(L, -2); + lua_concat(L, 2); + } + lua_error(L); /* propagate error */ + } + return r; +} + + +static int luaB_cocreate (lua_State *L) { + lua_State *NL = lua_newthread(L); + luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, + "Lua function expected"); + lua_pushvalue(L, 1); /* move function to top */ + lua_xmove(L, NL, 1); /* move function from L to NL */ + return 1; +} + + +static int luaB_cowrap (lua_State *L) { + luaB_cocreate(L); + lua_pushcclosure(L, luaB_auxwrap, 1); + return 1; +} + + +static int luaB_yield (lua_State *L) { + return lua_yield(L, lua_gettop(L)); +} + + +static int luaB_costatus (lua_State *L) { + lua_State *co = lua_tothread(L, 1); + luaL_argcheck(L, co, 1, "coroutine expected"); + if (L == co) lua_pushliteral(L, "running"); + else { + lua_Debug ar; + if (lua_getstack(co, 0, &ar) == 0 && lua_gettop(co) == 0) + lua_pushliteral(L, "dead"); + else + lua_pushliteral(L, "suspended"); + } + return 1; +} + + +static const luaL_reg co_funcs[] = { + {"create", luaB_cocreate}, + {"wrap", luaB_cowrap}, + {"resume", luaB_coresume}, + {"yield", luaB_yield}, + {"status", luaB_costatus}, + {NULL, NULL} +}; + +/* }====================================================== */ + + + +static void base_open (lua_State *L) { + lua_pushliteral(L, "_G"); + lua_pushvalue(L, LUA_GLOBALSINDEX); + luaL_openlib(L, NULL, base_funcs, 0); /* open lib into global table */ + lua_pushliteral(L, "_VERSION"); + lua_pushliteral(L, LUA_VERSION); + lua_rawset(L, -3); /* set global _VERSION */ + /* `newproxy' needs a weaktable as upvalue */ + lua_pushliteral(L, "newproxy"); + lua_newtable(L); /* new table `w' */ + lua_pushvalue(L, -1); /* `w' will be its own metatable */ + lua_setmetatable(L, -2); + lua_pushliteral(L, "__mode"); + lua_pushliteral(L, "k"); + lua_rawset(L, -3); /* metatable(w).__mode = "k" */ + lua_pushcclosure(L, luaB_newproxy, 1); + lua_rawset(L, -3); /* set global `newproxy' */ + lua_rawset(L, -1); /* set global _G */ +} + + +LUALIB_API int luaopen_base (lua_State *L) { + base_open(L); + luaL_openlib(L, LUA_COLIBNAME, co_funcs, 0); + lua_newtable(L); + lua_setglobal(L, REQTAB); + return 0; +} + diff --git a/src/lib/ldblib.c b/src/lib/ldblib.c new file mode 100644 index 0000000..6dc9b64 --- /dev/null +++ b/src/lib/ldblib.c @@ -0,0 +1,299 @@ +/* +** $Id: ldblib.c,v 1.80 2003/04/03 13:35:34 roberto Exp $ +** Interface from Lua to its debug API +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +#define ldblib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + +static void settabss (lua_State *L, const char *i, const char *v) { + lua_pushstring(L, i); + lua_pushstring(L, v); + lua_rawset(L, -3); +} + + +static void settabsi (lua_State *L, const char *i, int v) { + lua_pushstring(L, i); + lua_pushnumber(L, (lua_Number)v); + lua_rawset(L, -3); +} + + +static int getinfo (lua_State *L) { + lua_Debug ar; + const char *options = luaL_optstring(L, 2, "flnSu"); + if (lua_isnumber(L, 1)) { + if (!lua_getstack(L, (int)(lua_tonumber(L, 1)), &ar)) { + lua_pushnil(L); /* level out of range */ + return 1; + } + } + else if (lua_isfunction(L, 1)) { + lua_pushfstring(L, ">%s", options); + options = lua_tostring(L, -1); + lua_pushvalue(L, 1); + } + else + return luaL_argerror(L, 1, "function or level expected"); + if (!lua_getinfo(L, options, &ar)) + return luaL_argerror(L, 2, "invalid option"); + lua_newtable(L); + for (; *options; options++) { + switch (*options) { + case 'S': + settabss(L, "source", ar.source); + settabss(L, "short_src", ar.short_src); + settabsi(L, "linedefined", ar.linedefined); + settabss(L, "what", ar.what); + break; + case 'l': + settabsi(L, "currentline", ar.currentline); + break; + case 'u': + settabsi(L, "nups", ar.nups); + break; + case 'n': + settabss(L, "name", ar.name); + settabss(L, "namewhat", ar.namewhat); + break; + case 'f': + lua_pushliteral(L, "func"); + lua_pushvalue(L, -3); + lua_rawset(L, -3); + break; + } + } + return 1; /* return table */ +} + + +static int getlocal (lua_State *L) { + lua_Debug ar; + const char *name; + if (!lua_getstack(L, luaL_checkint(L, 1), &ar)) /* level out of range? */ + return luaL_argerror(L, 1, "level out of range"); + name = lua_getlocal(L, &ar, luaL_checkint(L, 2)); + if (name) { + lua_pushstring(L, name); + lua_pushvalue(L, -2); + return 2; + } + else { + lua_pushnil(L); + return 1; + } +} + + +static int setlocal (lua_State *L) { + lua_Debug ar; + if (!lua_getstack(L, luaL_checkint(L, 1), &ar)) /* level out of range? */ + return luaL_argerror(L, 1, "level out of range"); + luaL_checkany(L, 3); + lua_pushstring(L, lua_setlocal(L, &ar, luaL_checkint(L, 2))); + return 1; +} + + +static int auxupvalue (lua_State *L, int get) { + const char *name; + int n = luaL_checkint(L, 2); + luaL_checktype(L, 1, LUA_TFUNCTION); + if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */ + name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); + if (name == NULL) return 0; + lua_pushstring(L, name); + lua_insert(L, -(get+1)); + return get + 1; +} + + +static int getupvalue (lua_State *L) { + return auxupvalue(L, 1); +} + + +static int setupvalue (lua_State *L) { + luaL_checkany(L, 3); + return auxupvalue(L, 0); +} + + + +static const char KEY_HOOK = 'h'; + + +static void hookf (lua_State *L, lua_Debug *ar) { + static const char *const hooknames[] = + {"call", "return", "line", "count", "tail return"}; + lua_pushlightuserdata(L, (void *)&KEY_HOOK); + lua_rawget(L, LUA_REGISTRYINDEX); + if (lua_isfunction(L, -1)) { + lua_pushstring(L, hooknames[(int)ar->event]); + if (ar->currentline >= 0) + lua_pushnumber(L, (lua_Number)ar->currentline); + else lua_pushnil(L); + lua_assert(lua_getinfo(L, "lS", ar)); + lua_call(L, 2, 0); + } + else + lua_pop(L, 1); /* pop result from gettable */ +} + + +static int makemask (const char *smask, int count) { + int mask = 0; + if (strchr(smask, 'c')) mask |= LUA_MASKCALL; + if (strchr(smask, 'r')) mask |= LUA_MASKRET; + if (strchr(smask, 'l')) mask |= LUA_MASKLINE; + if (count > 0) mask |= LUA_MASKCOUNT; + return mask; +} + + +static char *unmakemask (int mask, char *smask) { + int i = 0; + if (mask & LUA_MASKCALL) smask[i++] = 'c'; + if (mask & LUA_MASKRET) smask[i++] = 'r'; + if (mask & LUA_MASKLINE) smask[i++] = 'l'; + smask[i] = '\0'; + return smask; +} + + +static int sethook (lua_State *L) { + if (lua_isnoneornil(L, 1)) { + lua_settop(L, 1); + lua_sethook(L, NULL, 0, 0); /* turn off hooks */ + } + else { + const char *smask = luaL_checkstring(L, 2); + int count = luaL_optint(L, 3, 0); + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_sethook(L, hookf, makemask(smask, count), count); + } + lua_pushlightuserdata(L, (void *)&KEY_HOOK); + lua_pushvalue(L, 1); + lua_rawset(L, LUA_REGISTRYINDEX); /* set new hook */ + return 0; +} + + +static int gethook (lua_State *L) { + char buff[5]; + int mask = lua_gethookmask(L); + lua_Hook hook = lua_gethook(L); + if (hook != NULL && hook != hookf) /* external hook? */ + lua_pushliteral(L, "external hook"); + else { + lua_pushlightuserdata(L, (void *)&KEY_HOOK); + lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */ + } + lua_pushstring(L, unmakemask(mask, buff)); + lua_pushnumber(L, (lua_Number)lua_gethookcount(L)); + return 3; +} + + +static int debug (lua_State *L) { + for (;;) { + char buffer[250]; + fputs("lua_debug> ", stderr); + if (fgets(buffer, sizeof(buffer), stdin) == 0 || + strcmp(buffer, "cont\n") == 0) + return 0; + lua_dostring(L, buffer); + lua_settop(L, 0); /* remove eventual returns */ + } +} + + +#define LEVELS1 12 /* size of the first part of the stack */ +#define LEVELS2 10 /* size of the second part of the stack */ + +static int errorfb (lua_State *L) { + int level = 1; /* skip level 0 (it's this function) */ + int firstpart = 1; /* still before eventual `...' */ + lua_Debug ar; + if (lua_gettop(L) == 0) + lua_pushliteral(L, ""); + else if (!lua_isstring(L, 1)) return 1; /* no string message */ + else lua_pushliteral(L, "\n"); + lua_pushliteral(L, "stack traceback:"); + while (lua_getstack(L, level++, &ar)) { + if (level > LEVELS1 && firstpart) { + /* no more than `LEVELS2' more levels? */ + if (!lua_getstack(L, level+LEVELS2, &ar)) + level--; /* keep going */ + else { + lua_pushliteral(L, "\n\t..."); /* too many levels */ + while (lua_getstack(L, level+LEVELS2, &ar)) /* find last levels */ + level++; + } + firstpart = 0; + continue; + } + lua_pushliteral(L, "\n\t"); + lua_getinfo(L, "Snl", &ar); + lua_pushfstring(L, "%s:", ar.short_src); + if (ar.currentline > 0) + lua_pushfstring(L, "%d:", ar.currentline); + switch (*ar.namewhat) { + case 'g': /* global */ + case 'l': /* local */ + case 'f': /* field */ + case 'm': /* method */ + lua_pushfstring(L, " in function `%s'", ar.name); + break; + default: { + 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)); + } + lua_concat(L, lua_gettop(L)); + return 1; +} + + +static const luaL_reg dblib[] = { + {"getlocal", getlocal}, + {"getinfo", getinfo}, + {"gethook", gethook}, + {"getupvalue", getupvalue}, + {"sethook", sethook}, + {"setlocal", setlocal}, + {"setupvalue", setupvalue}, + {"debug", debug}, + {"traceback", errorfb}, + {NULL, NULL} +}; + + +LUALIB_API int luaopen_debug (lua_State *L) { + luaL_openlib(L, LUA_DBLIBNAME, dblib, 0); + lua_pushliteral(L, "_TRACEBACK"); + lua_pushcfunction(L, errorfb); + lua_settable(L, LUA_GLOBALSINDEX); + return 1; +} + diff --git a/src/lib/liolib.c b/src/lib/liolib.c new file mode 100644 index 0000000..96b3883 --- /dev/null +++ b/src/lib/liolib.c @@ -0,0 +1,750 @@ +/* +** $Id: liolib.c,v 2.39a 2003/03/19 21:16:12 roberto Exp $ +** Standard I/O (and system) library +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include +#include + +#define liolib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + +/* +** by default, gcc does not get `tmpname' +*/ +#ifndef USE_TMPNAME +#ifdef __GNUC__ +#define USE_TMPNAME 0 +#else +#define USE_TMPNAME 1 +#endif +#endif + + +/* +** by default, posix systems get `popen' +*/ +#ifndef USE_POPEN +#ifdef _POSIX_C_SOURCE +#if _POSIX_C_SOURCE >= 2 +#define USE_POPEN 1 +#endif +#endif +#endif + +#ifndef USE_POPEN +#define USE_POPEN 0 +#endif + + + + +/* +** {====================================================== +** FILE Operations +** ======================================================= +*/ + + +#if !USE_POPEN +#define pclose(f) (-1) +#endif + + +#define FILEHANDLE "FILE*" + +#define IO_INPUT "_input" +#define IO_OUTPUT "_output" + + +static int pushresult (lua_State *L, int i, const char *filename) { + if (i) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushnil(L); + if (filename) + lua_pushfstring(L, "%s: %s", filename, strerror(errno)); + else + lua_pushfstring(L, "%s", strerror(errno)); + lua_pushnumber(L, errno); + return 3; + } +} + + +static FILE **topfile (lua_State *L, int findex) { + FILE **f = (FILE **)luaL_checkudata(L, findex, FILEHANDLE); + if (f == NULL) luaL_argerror(L, findex, "bad file"); + return f; +} + + +static int io_type (lua_State *L) { + FILE **f = (FILE **)luaL_checkudata(L, 1, FILEHANDLE); + if (f == NULL) lua_pushnil(L); + else if (*f == NULL) + lua_pushliteral(L, "closed file"); + else + lua_pushliteral(L, "file"); + return 1; +} + + +static FILE *tofile (lua_State *L, int findex) { + FILE **f = topfile(L, findex); + if (*f == NULL) + luaL_error(L, "attempt to use a closed file"); + return *f; +} + + + +/* +** When creating file handles, always creates a `closed' file handle +** before opening the actual file; so, if there is a memory error, the +** file is not left opened. +*/ +static FILE **newfile (lua_State *L) { + FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); + *pf = NULL; /* file handle is currently `closed' */ + luaL_getmetatable(L, FILEHANDLE); + lua_setmetatable(L, -2); + return pf; +} + + +/* +** assumes that top of the stack is the `io' library, and next is +** the `io' metatable +*/ +static void registerfile (lua_State *L, FILE *f, const char *name, + const char *impname) { + lua_pushstring(L, name); + *newfile(L) = f; + if (impname) { + lua_pushstring(L, impname); + lua_pushvalue(L, -2); + lua_settable(L, -6); /* metatable[impname] = file */ + } + lua_settable(L, -3); /* io[name] = file */ +} + + +static int aux_close (lua_State *L) { + FILE *f = tofile(L, 1); + if (f == stdin || f == stdout || f == stderr) + return 0; /* file cannot be closed */ + else { + int ok = (pclose(f) != -1) || (fclose(f) == 0); + if (ok) + *(FILE **)lua_touserdata(L, 1) = NULL; /* mark file as closed */ + return ok; + } +} + + +static int io_close (lua_State *L) { + if (lua_isnone(L, 1) && lua_type(L, lua_upvalueindex(1)) == LUA_TTABLE) { + lua_pushstring(L, IO_OUTPUT); + lua_rawget(L, lua_upvalueindex(1)); + } + return pushresult(L, aux_close(L), NULL); +} + + +static int io_gc (lua_State *L) { + FILE **f = topfile(L, 1); + if (*f != NULL) /* ignore closed files */ + aux_close(L); + return 0; +} + + +static int io_tostring (lua_State *L) { + char buff[128]; + FILE **f = topfile(L, 1); + if (*f == NULL) + strcpy(buff, "closed"); + else + sprintf(buff, "%p", lua_touserdata(L, 1)); + lua_pushfstring(L, "file (%s)", buff); + return 1; +} + + +static int io_open (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; +} + + +static int io_popen (lua_State *L) { +#if !USE_POPEN + luaL_error(L, "`popen' not supported"); + return 0; +#else + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf = newfile(L); + *pf = popen(filename, mode); + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; +#endif +} + + +static int io_tmpfile (lua_State *L) { + FILE **pf = newfile(L); + *pf = tmpfile(); + return (*pf == NULL) ? pushresult(L, 0, NULL) : 1; +} + + +static FILE *getiofile (lua_State *L, const char *name) { + lua_pushstring(L, name); + lua_rawget(L, lua_upvalueindex(1)); + return tofile(L, -1); +} + + +static int g_iofile (lua_State *L, const char *name, const char *mode) { + if (!lua_isnoneornil(L, 1)) { + const char *filename = lua_tostring(L, 1); + lua_pushstring(L, name); + if (filename) { + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + if (*pf == NULL) { + lua_pushfstring(L, "%s: %s", filename, strerror(errno)); + luaL_argerror(L, 1, lua_tostring(L, -1)); + } + } + else { + tofile(L, 1); /* check that it's a valid file handle */ + lua_pushvalue(L, 1); + } + lua_rawset(L, lua_upvalueindex(1)); + } + /* return current value */ + lua_pushstring(L, name); + lua_rawget(L, lua_upvalueindex(1)); + return 1; +} + + +static int io_input (lua_State *L) { + return g_iofile(L, IO_INPUT, "r"); +} + + +static int io_output (lua_State *L) { + return g_iofile(L, IO_OUTPUT, "w"); +} + + +static int io_readline (lua_State *L); + + +static void aux_lines (lua_State *L, int idx, int close) { + lua_pushliteral(L, FILEHANDLE); + lua_rawget(L, LUA_REGISTRYINDEX); + lua_pushvalue(L, idx); + lua_pushboolean(L, close); /* close/not close file when finished */ + lua_pushcclosure(L, io_readline, 3); +} + + +static int f_lines (lua_State *L) { + tofile(L, 1); /* check that it's a valid file handle */ + aux_lines(L, 1, 0); + return 1; +} + + +static int io_lines (lua_State *L) { + if (lua_isnoneornil(L, 1)) { /* no arguments? */ + lua_pushstring(L, IO_INPUT); + lua_rawget(L, lua_upvalueindex(1)); /* will iterate over default input */ + return f_lines(L); + } + else { + const char *filename = luaL_checkstring(L, 1); + FILE **pf = newfile(L); + *pf = fopen(filename, "r"); + luaL_argcheck(L, *pf, 1, strerror(errno)); + aux_lines(L, lua_gettop(L), 1); + return 1; + } +} + + +/* +** {====================================================== +** READ +** ======================================================= +*/ + + +static int read_number (lua_State *L, FILE *f) { + lua_Number d; + if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { + lua_pushnumber(L, d); + return 1; + } + else return 0; /* read fails */ +} + + +static int test_eof (lua_State *L, FILE *f) { + int c = getc(f); + ungetc(c, f); + lua_pushlstring(L, NULL, 0); + return (c != EOF); +} + + +static int read_line (lua_State *L, FILE *f) { + luaL_Buffer b; + luaL_buffinit(L, &b); + for (;;) { + size_t l; + char *p = luaL_prepbuffer(&b); + if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ + luaL_pushresult(&b); /* close buffer */ + return (lua_strlen(L, -1) > 0); /* check whether read something */ + } + l = strlen(p); + if (p[l-1] != '\n') + luaL_addsize(&b, l); + else { + luaL_addsize(&b, l - 1); /* do not include `eol' */ + luaL_pushresult(&b); /* close buffer */ + return 1; /* read at least an `eol' */ + } + } +} + + +static int read_chars (lua_State *L, FILE *f, size_t n) { + size_t rlen; /* how much to read */ + size_t nr; /* number of chars actually read */ + luaL_Buffer b; + luaL_buffinit(L, &b); + rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ + do { + char *p = luaL_prepbuffer(&b); + if (rlen > n) rlen = n; /* cannot read more than asked */ + nr = fread(p, sizeof(char), rlen, f); + luaL_addsize(&b, 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_strlen(L, -1) > 0); +} + + +static int g_read (lua_State *L, FILE *f, int first) { + int nargs = lua_gettop(L) - 1; + int success; + int n; + 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-- && success; n++) { + if (lua_type(L, n) == LUA_TNUMBER) { + size_t l = (size_t)lua_tonumber(L, n); + success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); + } + else { + const char *p = lua_tostring(L, n); + luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); + switch (p[1]) { + 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, ~((size_t)0)); /* read MAX_SIZE_T chars */ + success = 1; /* always success */ + break; + case 'w': /* word */ + return luaL_error(L, "obsolete option `*w' to `read'"); + default: + return luaL_argerror(L, n, "invalid format"); + } + } + } + } + if (!success) { + lua_pop(L, 1); /* remove last result */ + lua_pushnil(L); /* push nil instead */ + } + return n - first; +} + + +static int io_read (lua_State *L) { + return g_read(L, getiofile(L, IO_INPUT), 1); +} + + +static int f_read (lua_State *L) { + return g_read(L, tofile(L, 1), 2); +} + + +static int io_readline (lua_State *L) { + FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(2)); + if (f == NULL) /* file is already closed? */ + luaL_error(L, "file is already closed"); + if (read_line(L, f)) return 1; + else { /* EOF */ + if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ + lua_settop(L, 0); + lua_pushvalue(L, lua_upvalueindex(2)); + aux_close(L); /* close it */ + } + return 0; + } +} + +/* }====================================================== */ + + +static int g_write (lua_State *L, FILE *f, int arg) { + int nargs = lua_gettop(L) - 1; + int status = 1; + for (; nargs--; arg++) { + if (lua_type(L, arg) == LUA_TNUMBER) { + /* optimization: could be done exactly as for strings */ + status = status && + fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; + } + else { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + status = status && (fwrite(s, sizeof(char), l, f) == l); + } + } + return pushresult(L, status, NULL); +} + + +static int io_write (lua_State *L) { + return g_write(L, getiofile(L, IO_OUTPUT), 1); +} + + +static int f_write (lua_State *L) { + return g_write(L, tofile(L, 1), 2); +} + + +static int f_seek (lua_State *L) { + static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; + static const char *const modenames[] = {"set", "cur", "end", NULL}; + FILE *f = tofile(L, 1); + int op = luaL_findstring(luaL_optstring(L, 2, "cur"), modenames); + long offset = luaL_optlong(L, 3, 0); + luaL_argcheck(L, op != -1, 2, "invalid mode"); + op = fseek(f, offset, mode[op]); + if (op) + return pushresult(L, 0, NULL); /* error */ + else { + lua_pushnumber(L, ftell(f)); + return 1; + } +} + + +static int io_flush (lua_State *L) { + return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); +} + + +static int f_flush (lua_State *L) { + return pushresult(L, fflush(tofile(L, 1)) == 0, NULL); +} + + +static const luaL_reg iolib[] = { + {"input", io_input}, + {"output", io_output}, + {"lines", io_lines}, + {"close", io_close}, + {"flush", io_flush}, + {"open", io_open}, + {"popen", io_popen}, + {"read", io_read}, + {"tmpfile", io_tmpfile}, + {"type", io_type}, + {"write", io_write}, + {NULL, NULL} +}; + + +static const luaL_reg flib[] = { + {"flush", f_flush}, + {"read", f_read}, + {"lines", f_lines}, + {"seek", f_seek}, + {"write", f_write}, + {"close", io_close}, + {"__gc", io_gc}, + {"__tostring", io_tostring}, + {NULL, NULL} +}; + + +static void createmeta (lua_State *L) { + luaL_newmetatable(L, FILEHANDLE); /* create new metatable for file handles */ + /* file methods */ + lua_pushliteral(L, "__index"); + lua_pushvalue(L, -2); /* push metatable */ + lua_rawset(L, -3); /* metatable.__index = metatable */ + luaL_openlib(L, NULL, flib, 0); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Other O.S. Operations +** ======================================================= +*/ + +static int io_execute (lua_State *L) { + lua_pushnumber(L, system(luaL_checkstring(L, 1))); + return 1; +} + + +static int io_remove (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + return pushresult(L, remove(filename) == 0, filename); +} + + +static int io_rename (lua_State *L) { + const char *fromname = luaL_checkstring(L, 1); + const char *toname = luaL_checkstring(L, 2); + return pushresult(L, rename(fromname, toname) == 0, fromname); +} + + +static int io_tmpname (lua_State *L) { +#if !USE_TMPNAME + luaL_error(L, "`tmpname' not supported"); + return 0; +#else + char buff[L_tmpnam]; + if (tmpnam(buff) != buff) + return luaL_error(L, "unable to generate a unique filename in `tmpname'"); + lua_pushstring(L, buff); + return 1; +#endif +} + + +static int io_getenv (lua_State *L) { + lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ + return 1; +} + + +static int io_clock (lua_State *L) { + lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); + return 1; +} + + +/* +** {====================================================== +** Time/Date operations +** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, +** wday=%w+1, yday=%j, isdst=? } +** ======================================================= +*/ + +static void setfield (lua_State *L, const char *key, int value) { + lua_pushstring(L, key); + lua_pushnumber(L, value); + lua_rawset(L, -3); +} + +static void setboolfield (lua_State *L, const char *key, int value) { + lua_pushstring(L, key); + lua_pushboolean(L, value); + lua_rawset(L, -3); +} + +static int getboolfield (lua_State *L, const char *key) { + int res; + lua_pushstring(L, key); + lua_gettable(L, -2); + res = lua_toboolean(L, -1); + lua_pop(L, 1); + return res; +} + + +static int getfield (lua_State *L, const char *key, int d) { + int res; + lua_pushstring(L, key); + lua_gettable(L, -2); + if (lua_isnumber(L, -1)) + res = (int)(lua_tonumber(L, -1)); + else { + if (d == -2) + return luaL_error(L, "field `%s' missing in date table", key); + res = d; + } + lua_pop(L, 1); + return res; +} + + +static int io_date (lua_State *L) { + const char *s = luaL_optstring(L, 1, "%c"); + time_t t = (time_t)(luaL_optnumber(L, 2, -1)); + struct tm *stm; + if (t == (time_t)(-1)) /* no time given? */ + t = time(NULL); /* use current time */ + if (*s == '!') { /* UTC? */ + stm = gmtime(&t); + s++; /* skip `!' */ + } + else + stm = localtime(&t); + if (stm == NULL) /* invalid date? */ + lua_pushnil(L); + else if (strcmp(s, "*t") == 0) { + lua_newtable(L); + setfield(L, "sec", stm->tm_sec); + setfield(L, "min", stm->tm_min); + setfield(L, "hour", stm->tm_hour); + setfield(L, "day", stm->tm_mday); + setfield(L, "month", stm->tm_mon+1); + setfield(L, "year", stm->tm_year+1900); + setfield(L, "wday", stm->tm_wday+1); + setfield(L, "yday", stm->tm_yday+1); + setboolfield(L, "isdst", stm->tm_isdst); + } + else { + char b[256]; + if (strftime(b, sizeof(b), s, stm)) + lua_pushstring(L, b); + else + return luaL_error(L, "`date' format too long"); + } + return 1; +} + + +static int io_time (lua_State *L) { + if (lua_isnoneornil(L, 1)) /* called without args? */ + lua_pushnumber(L, time(NULL)); /* return current time */ + else { + time_t t; + struct tm ts; + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 1); /* make sure table is at the top */ + ts.tm_sec = getfield(L, "sec", 0); + ts.tm_min = getfield(L, "min", 0); + ts.tm_hour = getfield(L, "hour", 12); + ts.tm_mday = getfield(L, "day", -2); + ts.tm_mon = getfield(L, "month", -2) - 1; + ts.tm_year = getfield(L, "year", -2) - 1900; + ts.tm_isdst = getboolfield(L, "isdst"); + t = mktime(&ts); + if (t == (time_t)(-1)) + lua_pushnil(L); + else + lua_pushnumber(L, t); + } + return 1; +} + + +static int io_difftime (lua_State *L) { + lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), + (time_t)(luaL_optnumber(L, 2, 0)))); + return 1; +} + +/* }====================================================== */ + + +static int io_setloc (lua_State *L) { + static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, + LC_NUMERIC, LC_TIME}; + static const char *const catnames[] = {"all", "collate", "ctype", "monetary", + "numeric", "time", NULL}; + const char *l = lua_tostring(L, 1); + int op = luaL_findstring(luaL_optstring(L, 2, "all"), catnames); + luaL_argcheck(L, l || lua_isnoneornil(L, 1), 1, "string expected"); + luaL_argcheck(L, op != -1, 2, "invalid option"); + lua_pushstring(L, setlocale(cat[op], l)); + return 1; +} + + +static int io_exit (lua_State *L) { + exit(luaL_optint(L, 1, EXIT_SUCCESS)); + return 0; /* to avoid warnings */ +} + +static const luaL_reg syslib[] = { + {"clock", io_clock}, + {"date", io_date}, + {"difftime", io_difftime}, + {"execute", io_execute}, + {"exit", io_exit}, + {"getenv", io_getenv}, + {"remove", io_remove}, + {"rename", io_rename}, + {"setlocale", io_setloc}, + {"time", io_time}, + {"tmpname", io_tmpname}, + {NULL, NULL} +}; + +/* }====================================================== */ + + + +LUALIB_API int luaopen_io (lua_State *L) { + luaL_openlib(L, LUA_OSLIBNAME, syslib, 0); + createmeta(L); + lua_pushvalue(L, -1); + luaL_openlib(L, LUA_IOLIBNAME, iolib, 1); + /* put predefined file handles into `io' table */ + registerfile(L, stdin, "stdin", IO_INPUT); + registerfile(L, stdout, "stdout", IO_OUTPUT); + registerfile(L, stderr, "stderr", NULL); + return 1; +} + diff --git a/src/lib/lmathlib.c b/src/lib/lmathlib.c new file mode 100644 index 0000000..f074a56 --- /dev/null +++ b/src/lib/lmathlib.c @@ -0,0 +1,246 @@ +/* +** $Id: lmathlib.c,v 1.56 2003/03/11 12:30:37 roberto Exp $ +** Standard mathematical library +** See Copyright Notice in lua.h +*/ + + +#include +#include + +#define lmathlib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#undef PI +#define PI (3.14159265358979323846) +#define RADIANS_PER_DEGREE (PI/180.0) + + + +/* +** If you want Lua to operate in degrees (instead of radians), +** define USE_DEGREES +*/ +#ifdef USE_DEGREES +#define FROMRAD(a) ((a)/RADIANS_PER_DEGREE) +#define TORAD(a) ((a)*RADIANS_PER_DEGREE) +#else +#define FROMRAD(a) (a) +#define TORAD(a) (a) +#endif + + +static int math_abs (lua_State *L) { + lua_pushnumber(L, fabs(luaL_checknumber(L, 1))); + return 1; +} + +static int math_sin (lua_State *L) { + lua_pushnumber(L, sin(TORAD(luaL_checknumber(L, 1)))); + return 1; +} + +static int math_cos (lua_State *L) { + lua_pushnumber(L, cos(TORAD(luaL_checknumber(L, 1)))); + return 1; +} + +static int math_tan (lua_State *L) { + lua_pushnumber(L, tan(TORAD(luaL_checknumber(L, 1)))); + return 1; +} + +static int math_asin (lua_State *L) { + lua_pushnumber(L, FROMRAD(asin(luaL_checknumber(L, 1)))); + return 1; +} + +static int math_acos (lua_State *L) { + lua_pushnumber(L, FROMRAD(acos(luaL_checknumber(L, 1)))); + return 1; +} + +static int math_atan (lua_State *L) { + lua_pushnumber(L, FROMRAD(atan(luaL_checknumber(L, 1)))); + return 1; +} + +static int math_atan2 (lua_State *L) { + lua_pushnumber(L, FROMRAD(atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)))); + return 1; +} + +static int math_ceil (lua_State *L) { + lua_pushnumber(L, ceil(luaL_checknumber(L, 1))); + return 1; +} + +static int math_floor (lua_State *L) { + lua_pushnumber(L, floor(luaL_checknumber(L, 1))); + return 1; +} + +static int math_mod (lua_State *L) { + lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + return 1; +} + +static int math_sqrt (lua_State *L) { + lua_pushnumber(L, sqrt(luaL_checknumber(L, 1))); + return 1; +} + +static int math_pow (lua_State *L) { + lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + return 1; +} + +static int math_log (lua_State *L) { + lua_pushnumber(L, log(luaL_checknumber(L, 1))); + return 1; +} + +static int math_log10 (lua_State *L) { + lua_pushnumber(L, log10(luaL_checknumber(L, 1))); + return 1; +} + +static int math_exp (lua_State *L) { + lua_pushnumber(L, exp(luaL_checknumber(L, 1))); + return 1; +} + +static int math_deg (lua_State *L) { + lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE); + return 1; +} + +static int math_rad (lua_State *L) { + lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE); + return 1; +} + +static int math_frexp (lua_State *L) { + int e; + lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e)); + lua_pushnumber(L, e); + return 2; +} + +static int math_ldexp (lua_State *L) { + lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2))); + return 1; +} + + + +static int math_min (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + lua_Number dmin = luaL_checknumber(L, 1); + int i; + for (i=2; i<=n; i++) { + lua_Number d = luaL_checknumber(L, i); + if (d < dmin) + dmin = d; + } + lua_pushnumber(L, dmin); + return 1; +} + + +static int math_max (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + lua_Number dmax = luaL_checknumber(L, 1); + int i; + for (i=2; i<=n; i++) { + lua_Number d = luaL_checknumber(L, i); + if (d > dmax) + dmax = d; + } + lua_pushnumber(L, dmax); + return 1; +} + + +static int math_random (lua_State *L) { + /* the `%' avoids the (rare) case of r==1, and is needed also because on + some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */ + lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX; + switch (lua_gettop(L)) { /* check number of arguments */ + case 0: { /* no arguments */ + lua_pushnumber(L, r); /* Number between 0 and 1 */ + break; + } + case 1: { /* only upper limit */ + int u = luaL_checkint(L, 1); + luaL_argcheck(L, 1<=u, 1, "interval is empty"); + lua_pushnumber(L, (int)floor(r*u)+1); /* int between 1 and `u' */ + break; + } + case 2: { /* lower and upper limits */ + int l = luaL_checkint(L, 1); + int u = luaL_checkint(L, 2); + luaL_argcheck(L, l<=u, 2, "interval is empty"); + lua_pushnumber(L, (int)floor(r*(u-l+1))+l); /* int between `l' and `u' */ + break; + } + default: return luaL_error(L, "wrong number of arguments"); + } + return 1; +} + + +static int math_randomseed (lua_State *L) { + srand(luaL_checkint(L, 1)); + return 0; +} + + +static const luaL_reg mathlib[] = { + {"abs", math_abs}, + {"sin", math_sin}, + {"cos", math_cos}, + {"tan", math_tan}, + {"asin", math_asin}, + {"acos", math_acos}, + {"atan", math_atan}, + {"atan2", math_atan2}, + {"ceil", math_ceil}, + {"floor", math_floor}, + {"mod", math_mod}, + {"frexp", math_frexp}, + {"ldexp", math_ldexp}, + {"sqrt", math_sqrt}, + {"min", math_min}, + {"max", math_max}, + {"log", math_log}, + {"log10", math_log10}, + {"exp", math_exp}, + {"deg", math_deg}, + {"pow", math_pow}, + {"rad", math_rad}, + {"random", math_random}, + {"randomseed", math_randomseed}, + {NULL, NULL} +}; + + +/* +** Open math library +*/ +LUALIB_API int luaopen_math (lua_State *L) { + luaL_openlib(L, LUA_MATHLIBNAME, mathlib, 0); + lua_pushliteral(L, "pi"); + lua_pushnumber(L, PI); + lua_settable(L, -3); + lua_pushliteral(L, "__pow"); + lua_pushcfunction(L, math_pow); + lua_settable(L, LUA_GLOBALSINDEX); + return 1; +} + diff --git a/src/lib/loadlib.c b/src/lib/loadlib.c new file mode 100644 index 0000000..ac4d697 --- /dev/null +++ b/src/lib/loadlib.c @@ -0,0 +1,205 @@ +/* +** $Id: loadlib.c,v 1.4 2003/04/07 20:11:53 roberto Exp $ +** Dynamic library loader for Lua +** See Copyright Notice in lua.h +* +* This Lua library exports a single function, called loadlib, which is +* called from Lua as loadlib(lib,init), where lib is the full name of the +* library to be loaded (including the complete path) and init is the name +* of a function to be called after the library is loaded. Typically, this +* function will register other functions, thus making the complete library +* available to Lua. The init function is *not* automatically called by +* loadlib. Instead, loadlib returns the init function as a Lua function +* that the client can call when it thinks is appropriate. In the case of +* errors, loadlib returns nil and two strings describing the error. +* The first string is supplied by the operating system; it should be +* informative and useful for error messages. The second string is "open", +* "init", or "absent" to identify the error and is meant to be used for +* making decisions without having to look into the first string (whose +* format is system-dependent). +* +* This module contains an implementation of loadlib for Unix systems that +* have dlfcn, an implementation for Windows, and a stub for other systems. +* See the list at the end of this file for some links to available +* implementations of dlfcn and interfaces to other native dynamic loaders +* on top of which loadlib could be implemented. +* +*/ + +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" + + +#undef LOADLIB + + +#ifdef USE_DLOPEN +#define LOADLIB +/* +* This is an implementation of loadlib based on the dlfcn interface. +* The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, +* NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least +* as an emulation layer on top of native functions. +*/ + +#include + +static int loadlib(lua_State *L) +{ + const char *path=luaL_checkstring(L,1); + const char *init=luaL_checkstring(L,2); + void *lib=dlopen(path,RTLD_NOW); + if (lib!=NULL) + { + lua_CFunction f=(lua_CFunction) dlsym(lib,init); + if (f!=NULL) + { + lua_pushlightuserdata(L,lib); + lua_pushcclosure(L,f,1); + return 1; + } + } + /* else return appropriate error messages */ + lua_pushnil(L); + lua_pushstring(L,dlerror()); + lua_pushstring(L,(lib!=NULL) ? "init" : "open"); + if (lib!=NULL) dlclose(lib); + return 3; +} + +#endif + + + +/* +** In Windows, default is to use dll; otherwise, default is not to use dll +*/ +#ifndef USE_DLL +#ifdef _WIN32 +#define USE_DLL 1 +#else +#define USE_DLL 0 +#endif +#endif + + +#if USE_DLL +#define LOADLIB +/* +* This is an implementation of loadlib for Windows using native functions. +*/ + +#include + +static void pusherror(lua_State *L) +{ + int error=GetLastError(); + char buffer[128]; + if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, + 0, error, 0, buffer, sizeof(buffer), 0)) + lua_pushstring(L,buffer); + else + lua_pushfstring(L,"system error %d\n",error); +} + +static int loadlib(lua_State *L) +{ + const char *path=luaL_checkstring(L,1); + const char *init=luaL_checkstring(L,2); + HINSTANCE lib=LoadLibrary(path); + if (lib!=NULL) + { + lua_CFunction f=(lua_CFunction) GetProcAddress(lib,init); + if (f!=NULL) + { + lua_pushlightuserdata(L,lib); + lua_pushcclosure(L,f,1); + return 1; + } + } + lua_pushnil(L); + pusherror(L); + lua_pushstring(L,(lib!=NULL) ? "init" : "open"); + if (lib!=NULL) FreeLibrary(lib); + return 3; +} + +#endif + + + +#ifndef LOADLIB +/* Fallback for other systems */ + +/* +** Those systems support dlopen, so they should have defined USE_DLOPEN. +** The default (no)implementation gives them a special error message. +*/ +#ifdef linux +#define LOADLIB +#endif + +#ifdef sun +#define LOADLIB +#endif + +#ifdef sgi +#define LOADLIB +#endif + +#ifdef BSD +#define LOADLIB +#endif + +#ifdef _WIN32 +#define LOADLIB +#endif + +#ifdef LOADLIB +#undef LOADLIB +#define LOADLIB "`loadlib' not installed (check your Lua configuration)" +#else +#define LOADLIB "`loadlib' not supported" +#endif + +static int loadlib(lua_State *L) +{ + lua_pushnil(L); + lua_pushliteral(L,LOADLIB); + lua_pushliteral(L,"absent"); + return 3; +} +#endif + +LUALIB_API int luaopen_loadlib (lua_State *L) +{ + lua_register(L,"loadlib",loadlib); + return 0; +} + +/* +* Here are some links to available implementations of dlfcn and +* interfaces to other native dynamic loaders on top of which loadlib +* could be implemented. Please send contributions and corrections to us. +* +* AIX +* Starting with AIX 4.2, dlfcn is included in the base OS. +* There is also an emulation package available. +* http://www.faqs.org/faqs/aix-faq/part4/section-21.html +* +* HPUX +* HPUX 11 has dlfcn. For HPUX 10 use shl_*. +* http://www.geda.seul.org/mailinglist/geda-dev37/msg00094.html +* http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html +* +* Macintosh, Windows +* http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html +* +* Mac OS X/Darwin +* http://www.opendarwin.org/projects/dlcompat/ +* +* GLIB has wrapper code for BeOS, OS2, Unix and Windows +* http://cvs.gnome.org/lxr/source/glib/gmodule/ +* +*/ diff --git a/src/lib/lstrlib.c b/src/lib/lstrlib.c new file mode 100644 index 0000000..8752e3a --- /dev/null +++ b/src/lib/lstrlib.c @@ -0,0 +1,770 @@ +/* +** $Id: lstrlib.c,v 1.98 2003/04/03 13:35:34 roberto Exp $ +** Standard library for string operations and pattern-matching +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include + +#define lstrlib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* macro to `unsign' a character */ +#ifndef uchar +#define uchar(c) ((unsigned char)(c)) +#endif + + +typedef long sint32; /* a signed version for size_t */ + + +static int str_len (lua_State *L) { + size_t l; + luaL_checklstring(L, 1, &l); + lua_pushnumber(L, (lua_Number)l); + return 1; +} + + +static sint32 posrelat (sint32 pos, size_t len) { + /* relative string position: negative means back from end */ + return (pos>=0) ? pos : (sint32)len+pos+1; +} + + +static int str_sub (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + sint32 start = posrelat(luaL_checklong(L, 2), l); + sint32 end = posrelat(luaL_optlong(L, 3, -1), l); + if (start < 1) start = 1; + if (end > (sint32)l) end = (sint32)l; + if (start <= end) + lua_pushlstring(L, s+start-1, end-start+1); + else lua_pushliteral(L, ""); + return 1; +} + + +static int str_lower (lua_State *L) { + size_t l; + size_t i; + luaL_Buffer b; + const char *s = luaL_checklstring(L, 1, &l); + luaL_buffinit(L, &b); + for (i=0; i 0) + luaL_addlstring(&b, s, l); + luaL_pushresult(&b); + return 1; +} + + +static int str_byte (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + sint32 pos = posrelat(luaL_optlong(L, 2, 1), l); + if (pos <= 0 || (size_t)(pos) > l) /* index out of range? */ + return 0; /* no answer */ + lua_pushnumber(L, uchar(s[pos-1])); + return 1; +} + + +static int str_char (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + int i; + luaL_Buffer b; + luaL_buffinit(L, &b); + for (i=1; i<=n; i++) { + int c = luaL_checkint(L, i); + luaL_argcheck(L, uchar(c) == c, i, "invalid value"); + luaL_putchar(&b, uchar(c)); + } + luaL_pushresult(&b); + return 1; +} + + +static int writer (lua_State *L, const void* b, size_t size, void* B) { + (void)L; + luaL_addlstring((luaL_Buffer*) B, (const char *)b, size); + return 1; +} + + +static int str_dump (lua_State *L) { + luaL_Buffer b; + luaL_checktype(L, 1, LUA_TFUNCTION); + luaL_buffinit(L,&b); + if (!lua_dump(L, writer, &b)) + luaL_error(L, "unable to dump given function"); + luaL_pushresult(&b); + return 1; +} + + + +/* +** {====================================================== +** PATTERN MATCHING +** ======================================================= +*/ + +#ifndef MAX_CAPTURES +#define MAX_CAPTURES 32 /* arbitrary limit */ +#endif + + +#define CAP_UNFINISHED (-1) +#define CAP_POSITION (-2) + +typedef struct MatchState { + const char *src_init; /* init of source string */ + const char *src_end; /* end (`\0') of source string */ + lua_State *L; + int level; /* total number of captures (finished or unfinished) */ + struct { + const char *init; + sint32 len; + } capture[MAX_CAPTURES]; +} MatchState; + + +#define ESC '%' +#define SPECIALS "^$*+?.([%-" + + +static int check_capture (MatchState *ms, int l) { + l -= '1'; + if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED) + return luaL_error(ms->L, "invalid capture index"); + return l; +} + + +static int capture_to_close (MatchState *ms) { + int level = ms->level; + for (level--; level>=0; level--) + if (ms->capture[level].len == CAP_UNFINISHED) return level; + return luaL_error(ms->L, "invalid pattern capture"); +} + + +static const char *luaI_classend (MatchState *ms, const char *p) { + switch (*p++) { + case ESC: { + if (*p == '\0') + luaL_error(ms->L, "malformed pattern (ends with `%')"); + return p+1; + } + case '[': { + if (*p == '^') p++; + do { /* look for a `]' */ + if (*p == '\0') + luaL_error(ms->L, "malformed pattern (missing `]')"); + if (*(p++) == ESC && *p != '\0') + p++; /* skip escapes (e.g. `%]') */ + } while (*p != ']'); + return p+1; + } + default: { + return p; + } + } +} + + +static int match_class (int c, int cl) { + int res; + switch (tolower(cl)) { + case 'a' : res = isalpha(c); break; + case 'c' : res = iscntrl(c); break; + case 'd' : res = isdigit(c); break; + case 'l' : res = islower(c); break; + case 'p' : res = ispunct(c); break; + case 's' : res = isspace(c); break; + case 'u' : res = isupper(c); break; + case 'w' : res = isalnum(c); break; + case 'x' : res = isxdigit(c); break; + case 'z' : res = (c == 0); break; + default: return (cl == c); + } + return (islower(cl) ? res : !res); +} + + +static int matchbracketclass (int c, const char *p, const char *ec) { + int sig = 1; + if (*(p+1) == '^') { + sig = 0; + p++; /* skip the `^' */ + } + while (++p < ec) { + if (*p == ESC) { + p++; + if (match_class(c, *p)) + return sig; + } + else if ((*(p+1) == '-') && (p+2 < ec)) { + p+=2; + if (uchar(*(p-2)) <= c && c <= uchar(*p)) + return sig; + } + else if (uchar(*p) == c) return sig; + } + return !sig; +} + + +static int luaI_singlematch (int c, const char *p, const char *ep) { + switch (*p) { + case '.': return 1; /* matches any char */ + case ESC: return match_class(c, *(p+1)); + case '[': return matchbracketclass(c, p, ep-1); + default: return (uchar(*p) == c); + } +} + + +static const char *match (MatchState *ms, const char *s, const char *p); + + +static const char *matchbalance (MatchState *ms, const char *s, + const char *p) { + if (*p == 0 || *(p+1) == 0) + luaL_error(ms->L, "unbalanced pattern"); + if (*s != *p) return NULL; + else { + int b = *p; + int e = *(p+1); + int cont = 1; + while (++s < ms->src_end) { + if (*s == e) { + if (--cont == 0) return s+1; + } + else if (*s == b) cont++; + } + } + return NULL; /* string ends out of balance */ +} + + +static const char *max_expand (MatchState *ms, const char *s, + const char *p, const char *ep) { + sint32 i = 0; /* counts maximum expand for item */ + while ((s+i)src_end && luaI_singlematch(uchar(*(s+i)), p, ep)) + i++; + /* keeps trying to match with the maximum repetitions */ + while (i>=0) { + const char *res = match(ms, (s+i), ep+1); + if (res) return res; + i--; /* else didn't match; reduce 1 repetition to try again */ + } + return NULL; +} + + +static const char *min_expand (MatchState *ms, const char *s, + const char *p, const char *ep) { + for (;;) { + const char *res = match(ms, s, ep+1); + if (res != NULL) + return res; + else if (ssrc_end && luaI_singlematch(uchar(*s), p, ep)) + s++; /* try with one more repetition */ + else return NULL; + } +} + + +static const char *start_capture (MatchState *ms, const char *s, + const char *p, int what) { + const char *res; + int level = ms->level; + if (level >= MAX_CAPTURES) luaL_error(ms->L, "too many captures"); + ms->capture[level].init = s; + ms->capture[level].len = what; + ms->level = level+1; + if ((res=match(ms, s, p)) == NULL) /* match failed? */ + ms->level--; /* undo capture */ + return res; +} + + +static const char *end_capture (MatchState *ms, const char *s, + const char *p) { + int l = capture_to_close(ms); + const char *res; + ms->capture[l].len = s - ms->capture[l].init; /* close capture */ + if ((res = match(ms, s, p)) == NULL) /* match failed? */ + ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ + return res; +} + + +static const char *match_capture (MatchState *ms, const char *s, int l) { + size_t len; + l = check_capture(ms, l); + len = ms->capture[l].len; + if ((size_t)(ms->src_end-s) >= len && + memcmp(ms->capture[l].init, s, len) == 0) + return s+len; + else return NULL; +} + + +static const char *match (MatchState *ms, const char *s, const char *p) { + init: /* using goto's to optimize tail recursion */ + switch (*p) { + case '(': { /* start capture */ + if (*(p+1) == ')') /* position capture? */ + return start_capture(ms, s, p+2, CAP_POSITION); + else + return start_capture(ms, s, p+1, CAP_UNFINISHED); + } + case ')': { /* end capture */ + return end_capture(ms, s, p+1); + } + case ESC: { + switch (*(p+1)) { + case 'b': { /* balanced string? */ + s = matchbalance(ms, s, p+2); + if (s == NULL) return NULL; + p+=4; goto init; /* else return match(ms, s, p+4); */ + } + case 'f': { /* frontier? */ + const char *ep; char previous; + p += 2; + if (*p != '[') + luaL_error(ms->L, "missing `[' after `%%f' in pattern"); + ep = luaI_classend(ms, p); /* points to what is next */ + previous = (s == ms->src_init) ? '\0' : *(s-1); + if (matchbracketclass(uchar(previous), p, ep-1) || + !matchbracketclass(uchar(*s), p, ep-1)) return NULL; + p=ep; goto init; /* else return match(ms, s, ep); */ + } + default: { + if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ + s = match_capture(ms, s, *(p+1)); + if (s == NULL) return NULL; + p+=2; goto init; /* else return match(ms, s, p+2) */ + } + goto dflt; /* case default */ + } + } + } + case '\0': { /* end of pattern */ + return s; /* match succeeded */ + } + case '$': { + if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ + return (s == ms->src_end) ? s : NULL; /* check end of string */ + else goto dflt; + } + default: dflt: { /* it is a pattern item */ + const char *ep = luaI_classend(ms, p); /* points to what is next */ + int m = ssrc_end && luaI_singlematch(uchar(*s), p, ep); + switch (*ep) { + case '?': { /* optional */ + const char *res; + if (m && ((res=match(ms, s+1, ep+1)) != NULL)) + return res; + p=ep+1; goto init; /* else return match(ms, s, ep+1); */ + } + case '*': { /* 0 or more repetitions */ + return max_expand(ms, s, p, ep); + } + case '+': { /* 1 or more repetitions */ + return (m ? max_expand(ms, s+1, p, ep) : NULL); + } + case '-': { /* 0 or more repetitions (minimum) */ + return min_expand(ms, s, p, ep); + } + default: { + if (!m) return NULL; + s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ + } + } + } + } +} + + + +static const char *lmemfind (const char *s1, size_t l1, + const char *s2, size_t l2) { + if (l2 == 0) return s1; /* empty strings are everywhere */ + else if (l2 > l1) return NULL; /* avoids a negative `l1' */ + else { + const char *init; /* to search for a `*s2' inside `s1' */ + l2--; /* 1st char will be checked by `memchr' */ + l1 = l1-l2; /* `s2' cannot be found after that */ + while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { + init++; /* 1st char is already checked */ + if (memcmp(init, s2+1, l2) == 0) + return init-1; + else { /* correct `l1' and `s1' to try again */ + l1 -= init-s1; + s1 = init; + } + } + return NULL; /* not found */ + } +} + + +static void push_onecapture (MatchState *ms, int i) { + int l = ms->capture[i].len; + if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); + if (l == CAP_POSITION) + lua_pushnumber(ms->L, (lua_Number)(ms->capture[i].init - ms->src_init + 1)); + else + lua_pushlstring(ms->L, ms->capture[i].init, l); +} + + +static int push_captures (MatchState *ms, const char *s, const char *e) { + int i; + luaL_checkstack(ms->L, ms->level, "too many captures"); + if (ms->level == 0 && s) { /* no explicit captures? */ + lua_pushlstring(ms->L, s, e-s); /* return whole match */ + return 1; + } + else { /* return all captures */ + for (i=0; ilevel; i++) + push_onecapture(ms, i); + return ms->level; /* number of strings pushed */ + } +} + + +static int str_find (lua_State *L) { + size_t l1, l2; + const char *s = luaL_checklstring(L, 1, &l1); + const char *p = luaL_checklstring(L, 2, &l2); + sint32 init = posrelat(luaL_optlong(L, 3, 1), l1) - 1; + if (init < 0) init = 0; + else if ((size_t)(init) > l1) init = (sint32)l1; + if (lua_toboolean(L, 4) || /* explicit request? */ + strpbrk(p, SPECIALS) == NULL) { /* or no special characters? */ + /* do a plain search */ + const char *s2 = lmemfind(s+init, l1-init, p, l2); + if (s2) { + lua_pushnumber(L, (lua_Number)(s2-s+1)); + lua_pushnumber(L, (lua_Number)(s2-s+l2)); + return 2; + } + } + else { + MatchState ms; + int anchor = (*p == '^') ? (p++, 1) : 0; + const char *s1=s+init; + ms.L = L; + ms.src_init = s; + ms.src_end = s+l1; + do { + const char *res; + ms.level = 0; + if ((res=match(&ms, s1, p)) != NULL) { + lua_pushnumber(L, (lua_Number)(s1-s+1)); /* start */ + lua_pushnumber(L, (lua_Number)(res-s)); /* end */ + return push_captures(&ms, NULL, 0) + 2; + } + } while (s1++L; + if (lua_isstring(L, 3)) { + const char *news = lua_tostring(L, 3); + size_t l = lua_strlen(L, 3); + size_t i; + for (i=0; i= 3 && (lua_isstring(L, 3) || lua_isfunction(L, 3)), + 3, "string or function expected"); + luaL_buffinit(L, &b); + ms.L = L; + ms.src_init = src; + ms.src_end = src+srcl; + while (n < max_s) { + const char *e; + ms.level = 0; + e = match(&ms, src, p); + if (e) { + n++; + add_s(&ms, &b, src, e); + } + if (e && e>src) /* non empty match? */ + src = e; /* skip it */ + else if (src < ms.src_end) + luaL_putchar(&b, *src++); + else break; + if (anchor) break; + } + luaL_addlstring(&b, src, ms.src_end-src); + luaL_pushresult(&b); + lua_pushnumber(L, (lua_Number)n); /* number of substitutions */ + return 2; +} + +/* }====================================================== */ + + +/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ +#define MAX_ITEM 512 +/* maximum size of each format specification (such as '%-099.99d') */ +#define MAX_FORMAT 20 + + +static void luaI_addquoted (lua_State *L, luaL_Buffer *b, int arg) { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + luaL_putchar(b, '"'); + while (l--) { + switch (*s) { + case '"': case '\\': case '\n': { + luaL_putchar(b, '\\'); + luaL_putchar(b, *s); + break; + } + case '\0': { + luaL_addlstring(b, "\\000", 4); + break; + } + default: { + luaL_putchar(b, *s); + break; + } + } + s++; + } + luaL_putchar(b, '"'); +} + + +static const char *scanformat (lua_State *L, const char *strfrmt, + char *form, int *hasprecision) { + const char *p = strfrmt; + while (strchr("-+ #0", *p)) p++; /* skip flags */ + if (isdigit(uchar(*p))) p++; /* skip width */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + if (*p == '.') { + p++; + *hasprecision = 1; + if (isdigit(uchar(*p))) p++; /* skip precision */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + } + if (isdigit(uchar(*p))) + luaL_error(L, "invalid format (width or precision too long)"); + if (p-strfrmt+2 > MAX_FORMAT) /* +2 to include `%' and the specifier */ + luaL_error(L, "invalid format (too long)"); + form[0] = '%'; + strncpy(form+1, strfrmt, p-strfrmt+1); + form[p-strfrmt+2] = 0; + return p; +} + + +static int str_format (lua_State *L) { + int arg = 1; + size_t sfl; + const char *strfrmt = luaL_checklstring(L, arg, &sfl); + const char *strfrmt_end = strfrmt+sfl; + luaL_Buffer b; + luaL_buffinit(L, &b); + while (strfrmt < strfrmt_end) { + if (*strfrmt != '%') + luaL_putchar(&b, *strfrmt++); + else if (*++strfrmt == '%') + luaL_putchar(&b, *strfrmt++); /* %% */ + else { /* format item */ + char form[MAX_FORMAT]; /* to store the format (`%...') */ + char buff[MAX_ITEM]; /* to store the formatted item */ + int hasprecision = 0; + if (isdigit(uchar(*strfrmt)) && *(strfrmt+1) == '$') + return luaL_error(L, "obsolete option (d$) to `format'"); + arg++; + strfrmt = scanformat(L, strfrmt, form, &hasprecision); + switch (*strfrmt++) { + case 'c': case 'd': case 'i': { + sprintf(buff, form, luaL_checkint(L, arg)); + break; + } + case 'o': case 'u': case 'x': case 'X': { + sprintf(buff, form, (unsigned int)(luaL_checknumber(L, arg))); + break; + } + case 'e': case 'E': case 'f': + case 'g': case 'G': { + sprintf(buff, form, luaL_checknumber(L, arg)); + break; + } + case 'q': { + luaI_addquoted(L, &b, arg); + continue; /* skip the `addsize' at the end */ + } + case 's': { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + if (!hasprecision && l >= 100) { + /* no precision and string is too long to be formatted; + keep original string */ + lua_pushvalue(L, arg); + luaL_addvalue(&b); + continue; /* skip the `addsize' at the end */ + } + else { + sprintf(buff, form, s); + break; + } + } + default: { /* also treat cases `pnLlh' */ + return luaL_error(L, "invalid option to `format'"); + } + } + luaL_addlstring(&b, buff, strlen(buff)); + } + } + luaL_pushresult(&b); + return 1; +} + + +static const luaL_reg strlib[] = { + {"len", str_len}, + {"sub", str_sub}, + {"lower", str_lower}, + {"upper", str_upper}, + {"char", str_char}, + {"rep", str_rep}, + {"byte", str_byte}, + {"format", str_format}, + {"dump", str_dump}, + {"find", str_find}, + {"gfind", gfind}, + {"gsub", str_gsub}, + {NULL, NULL} +}; + + +/* +** Open string library +*/ +LUALIB_API int luaopen_string (lua_State *L) { + luaL_openlib(L, LUA_STRLIBNAME, strlib, 0); + return 1; +} + diff --git a/src/lib/ltablib.c b/src/lib/ltablib.c new file mode 100644 index 0000000..c9bb2d1 --- /dev/null +++ b/src/lib/ltablib.c @@ -0,0 +1,250 @@ +/* +** $Id: ltablib.c,v 1.21 2003/04/03 13:35:34 roberto Exp $ +** Library for Table Manipulation +** See Copyright Notice in lua.h +*/ + + +#include + +#define ltablib_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) + + +static int luaB_foreachi (lua_State *L) { + int i; + int n = aux_getn(L, 1); + luaL_checktype(L, 2, LUA_TFUNCTION); + for (i=1; i<=n; i++) { + lua_pushvalue(L, 2); /* function */ + lua_pushnumber(L, (lua_Number)i); /* 1st argument */ + lua_rawgeti(L, 1, i); /* 2nd argument */ + lua_call(L, 2, 1); + if (!lua_isnil(L, -1)) + return 1; + lua_pop(L, 1); /* remove nil result */ + } + return 0; +} + + +static int luaB_foreach (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checktype(L, 2, LUA_TFUNCTION); + lua_pushnil(L); /* first key */ + for (;;) { + if (lua_next(L, 1) == 0) + return 0; + lua_pushvalue(L, 2); /* function */ + lua_pushvalue(L, -3); /* key */ + lua_pushvalue(L, -3); /* value */ + lua_call(L, 2, 1); + if (!lua_isnil(L, -1)) + return 1; + lua_pop(L, 2); /* remove value and result */ + } +} + + +static int luaB_getn (lua_State *L) { + lua_pushnumber(L, (lua_Number)aux_getn(L, 1)); + return 1; +} + + +static int luaB_setn (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_setn(L, 1, luaL_checkint(L, 2)); + return 0; +} + + +static int luaB_tinsert (lua_State *L) { + int v = lua_gettop(L); /* number of arguments */ + int n = aux_getn(L, 1) + 1; + int pos; /* where to insert new element */ + if (v == 2) /* called with only 2 arguments */ + pos = n; /* insert new element at the end */ + else { + pos = luaL_checkint(L, 2); /* 2nd argument is the position */ + if (pos > n) n = pos; /* `grow' array if necessary */ + v = 3; /* function may be called with more than 3 args */ + } + luaL_setn(L, 1, n); /* new size */ + while (--n >= pos) { /* move up elements */ + lua_rawgeti(L, 1, n); + lua_rawseti(L, 1, n+1); /* t[n+1] = t[n] */ + } + lua_pushvalue(L, v); + lua_rawseti(L, 1, pos); /* t[pos] = v */ + return 0; +} + + +static int luaB_tremove (lua_State *L) { + int n = aux_getn(L, 1); + int pos = luaL_optint(L, 2, n); + if (n <= 0) return 0; /* table is `empty' */ + luaL_setn(L, 1, n-1); /* t.n = n-1 */ + lua_rawgeti(L, 1, pos); /* result = t[pos] */ + for ( ;pos= P */ + while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { + if (i>u) luaL_error(L, "invalid order function for sorting"); + lua_pop(L, 1); /* remove a[i] */ + } + /* repeat --j until a[j] <= P */ + while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { + if (j +#include + +#define llex_c + +#include "lua.h" + +#include "ldo.h" +#include "llex.h" +#include "lobject.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "lzio.h" + + + +#define next(LS) (LS->current = zgetc(LS->z)) + + + +/* ORDER RESERVED */ +static const char *const token2string [] = { + "and", "break", "do", "else", "elseif", + "end", "false", "for", "function", "if", + "in", "local", "nil", "not", "or", "repeat", + "return", "then", "true", "until", "while", "*name", + "..", "...", "==", ">=", "<=", "~=", + "*number", "*string", "" +}; + + +void luaX_init (lua_State *L) { + int i; + for (i=0; itsv.reserved = cast(lu_byte, i+1); /* reserved word */ + } +} + + +#define MAXSRC 80 + + +void luaX_checklimit (LexState *ls, int val, int limit, const char *msg) { + if (val > limit) { + msg = luaO_pushfstring(ls->L, "too many %s (limit=%d)", msg, limit); + luaX_syntaxerror(ls, msg); + } +} + + +void luaX_errorline (LexState *ls, const char *s, const char *token, int line) { + lua_State *L = ls->L; + char buff[MAXSRC]; + luaO_chunkid(buff, getstr(ls->source), MAXSRC); + luaO_pushfstring(L, "%s:%d: %s near `%s'", buff, line, s, token); + luaD_throw(L, LUA_ERRSYNTAX); +} + + +static void luaX_error (LexState *ls, const char *s, const char *token) { + luaX_errorline(ls, s, token, ls->linenumber); +} + + +void luaX_syntaxerror (LexState *ls, const char *msg) { + const char *lasttoken; + switch (ls->t.token) { + case TK_NAME: + lasttoken = getstr(ls->t.seminfo.ts); + break; + case TK_STRING: + case TK_NUMBER: + lasttoken = luaZ_buffer(ls->buff); + break; + default: + lasttoken = luaX_token2str(ls, ls->t.token); + break; + } + luaX_error(ls, msg, lasttoken); +} + + +const char *luaX_token2str (LexState *ls, int token) { + if (token < FIRST_RESERVED) { + lua_assert(token == (unsigned char)token); + return luaO_pushfstring(ls->L, "%c", token); + } + else + return token2string[token-FIRST_RESERVED]; +} + + +static void luaX_lexerror (LexState *ls, const char *s, int token) { + if (token == TK_EOS) + luaX_error(ls, s, luaX_token2str(ls, token)); + else + luaX_error(ls, s, luaZ_buffer(ls->buff)); +} + + +static void inclinenumber (LexState *LS) { + next(LS); /* skip `\n' */ + ++LS->linenumber; + luaX_checklimit(LS, LS->linenumber, MAX_INT, "lines in a chunk"); +} + + +void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source) { + LS->L = L; + LS->lookahead.token = TK_EOS; /* no look-ahead token */ + LS->z = z; + LS->fs = NULL; + LS->linenumber = 1; + LS->lastline = 1; + LS->source = source; + next(LS); /* read first char */ + if (LS->current == '#') { + do { /* skip first line */ + next(LS); + } while (LS->current != '\n' && LS->current != EOZ); + } +} + + + +/* +** ======================================================= +** LEXICAL ANALYZER +** ======================================================= +*/ + + +/* use buffer to store names, literal strings and numbers */ + +/* extra space to allocate when growing buffer */ +#define EXTRABUFF 32 + +/* maximum number of chars that can be read without checking buffer size */ +#define MAXNOCHECK 5 + +#define checkbuffer(LS, len) \ + if (((len)+MAXNOCHECK)*sizeof(char) > luaZ_sizebuffer((LS)->buff)) \ + luaZ_openspace((LS)->L, (LS)->buff, (len)+EXTRABUFF) + +#define save(LS, c, l) \ + (luaZ_buffer((LS)->buff)[l++] = cast(char, c)) +#define save_and_next(LS, l) (save(LS, LS->current, l), next(LS)) + + +static size_t readname (LexState *LS) { + size_t l = 0; + checkbuffer(LS, l); + do { + checkbuffer(LS, l); + save_and_next(LS, l); + } while (isalnum(LS->current) || LS->current == '_'); + save(LS, '\0', l); + return l-1; +} + + +/* LUA_NUMBER */ +static void read_numeral (LexState *LS, int comma, SemInfo *seminfo) { + size_t l = 0; + checkbuffer(LS, l); + if (comma) save(LS, '.', l); + while (isdigit(LS->current)) { + checkbuffer(LS, l); + save_and_next(LS, l); + } + if (LS->current == '.') { + save_and_next(LS, l); + if (LS->current == '.') { + save_and_next(LS, l); + save(LS, '\0', l); + luaX_lexerror(LS, + "ambiguous syntax (decimal point x string concatenation)", + TK_NUMBER); + } + } + while (isdigit(LS->current)) { + checkbuffer(LS, l); + save_and_next(LS, l); + } + if (LS->current == 'e' || LS->current == 'E') { + save_and_next(LS, l); /* read `E' */ + if (LS->current == '+' || LS->current == '-') + save_and_next(LS, l); /* optional exponent sign */ + while (isdigit(LS->current)) { + checkbuffer(LS, l); + save_and_next(LS, l); + } + } + save(LS, '\0', l); + if (!luaO_str2d(luaZ_buffer(LS->buff), &seminfo->r)) + luaX_lexerror(LS, "malformed number", TK_NUMBER); +} + + +static void read_long_string (LexState *LS, SemInfo *seminfo) { + int cont = 0; + size_t l = 0; + checkbuffer(LS, l); + save(LS, '[', l); /* save first `[' */ + save_and_next(LS, l); /* pass the second `[' */ + if (LS->current == '\n') /* string starts with a newline? */ + inclinenumber(LS); /* skip it */ + for (;;) { + checkbuffer(LS, l); + switch (LS->current) { + case EOZ: + save(LS, '\0', l); + luaX_lexerror(LS, (seminfo) ? "unfinished long string" : + "unfinished long comment", TK_EOS); + break; /* to avoid warnings */ + case '[': + save_and_next(LS, l); + if (LS->current == '[') { + cont++; + save_and_next(LS, l); + } + continue; + case ']': + save_and_next(LS, l); + if (LS->current == ']') { + if (cont == 0) goto endloop; + cont--; + save_and_next(LS, l); + } + continue; + case '\n': + save(LS, '\n', l); + inclinenumber(LS); + if (!seminfo) l = 0; /* reset buffer to avoid wasting space */ + continue; + default: + save_and_next(LS, l); + } + } endloop: + save_and_next(LS, l); /* skip the second `]' */ + save(LS, '\0', l); + if (seminfo) + seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 2, l - 5); +} + + +static void read_string (LexState *LS, int del, SemInfo *seminfo) { + size_t l = 0; + checkbuffer(LS, l); + save_and_next(LS, l); + while (LS->current != del) { + checkbuffer(LS, l); + switch (LS->current) { + case EOZ: + save(LS, '\0', l); + luaX_lexerror(LS, "unfinished string", TK_EOS); + break; /* to avoid warnings */ + case '\n': + save(LS, '\0', l); + luaX_lexerror(LS, "unfinished string", TK_STRING); + break; /* to avoid warnings */ + case '\\': + next(LS); /* do not save the `\' */ + switch (LS->current) { + case 'a': save(LS, '\a', l); next(LS); break; + case 'b': save(LS, '\b', l); next(LS); break; + case 'f': save(LS, '\f', l); next(LS); break; + case 'n': save(LS, '\n', l); next(LS); break; + case 'r': save(LS, '\r', l); next(LS); break; + case 't': save(LS, '\t', l); next(LS); break; + case 'v': save(LS, '\v', l); next(LS); break; + case '\n': save(LS, '\n', l); inclinenumber(LS); break; + case EOZ: break; /* will raise an error next loop */ + default: { + if (!isdigit(LS->current)) + save_and_next(LS, l); /* handles \\, \", \', and \? */ + else { /* \xxx */ + int c = 0; + int i = 0; + do { + c = 10*c + (LS->current-'0'); + next(LS); + } while (++i<3 && isdigit(LS->current)); + if (c > UCHAR_MAX) { + save(LS, '\0', l); + luaX_lexerror(LS, "escape sequence too large", TK_STRING); + } + save(LS, c, l); + } + } + } + break; + default: + save_and_next(LS, l); + } + } + save_and_next(LS, l); /* skip delimiter */ + save(LS, '\0', l); + seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 1, l - 3); +} + + +int luaX_lex (LexState *LS, SemInfo *seminfo) { + for (;;) { + switch (LS->current) { + + case '\n': { + inclinenumber(LS); + continue; + } + case '-': { + next(LS); + if (LS->current != '-') return '-'; + /* else is a comment */ + next(LS); + if (LS->current == '[' && (next(LS), LS->current == '[')) + read_long_string(LS, NULL); /* long comment */ + else /* short comment */ + while (LS->current != '\n' && LS->current != EOZ) + next(LS); + continue; + } + case '[': { + next(LS); + if (LS->current != '[') return '['; + else { + read_long_string(LS, seminfo); + return TK_STRING; + } + } + case '=': { + next(LS); + if (LS->current != '=') return '='; + else { next(LS); return TK_EQ; } + } + case '<': { + next(LS); + if (LS->current != '=') return '<'; + else { next(LS); return TK_LE; } + } + case '>': { + next(LS); + if (LS->current != '=') return '>'; + else { next(LS); return TK_GE; } + } + case '~': { + next(LS); + if (LS->current != '=') return '~'; + else { next(LS); return TK_NE; } + } + case '"': + case '\'': { + read_string(LS, LS->current, seminfo); + return TK_STRING; + } + case '.': { + next(LS); + if (LS->current == '.') { + next(LS); + if (LS->current == '.') { + next(LS); + return TK_DOTS; /* ... */ + } + else return TK_CONCAT; /* .. */ + } + else if (!isdigit(LS->current)) return '.'; + else { + read_numeral(LS, 1, seminfo); + return TK_NUMBER; + } + } + case EOZ: { + return TK_EOS; + } + default: { + if (isspace(LS->current)) { + next(LS); + continue; + } + else if (isdigit(LS->current)) { + read_numeral(LS, 0, seminfo); + return TK_NUMBER; + } + else if (isalpha(LS->current) || LS->current == '_') { + /* identifier or reserved word */ + size_t l = readname(LS); + TString *ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff), l); + if (ts->tsv.reserved > 0) /* reserved word? */ + return ts->tsv.reserved - 1 + FIRST_RESERVED; + seminfo->ts = ts; + return TK_NAME; + } + else { + int c = LS->current; + if (iscntrl(c)) + luaX_error(LS, "invalid control char", + luaO_pushfstring(LS->L, "char(%d)", c)); + next(LS); + return c; /* single-char tokens (+ - / ...) */ + } + } + } + } +} + +#undef next diff --git a/src/llex.h b/src/llex.h new file mode 100644 index 0000000..740e3f6 --- /dev/null +++ b/src/llex.h @@ -0,0 +1,75 @@ +/* +** $Id: llex.h,v 1.47 2003/02/28 17:19:47 roberto Exp $ +** Lexical Analyzer +** See Copyright Notice in lua.h +*/ + +#ifndef llex_h +#define llex_h + +#include "lobject.h" +#include "lzio.h" + + +#define FIRST_RESERVED 257 + +/* maximum length of a reserved word */ +#define TOKEN_LEN (sizeof("function")/sizeof(char)) + + +/* +* WARNING: if you change the order of this enumeration, +* grep "ORDER RESERVED" +*/ +enum RESERVED { + /* terminal symbols denoted by reserved words */ + TK_AND = FIRST_RESERVED, TK_BREAK, + TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, + TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, + TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, + /* other terminal symbols */ + TK_NAME, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, + TK_STRING, TK_EOS +}; + +/* number of reserved words */ +#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) + + +typedef union { + lua_Number r; + TString *ts; +} SemInfo; /* semantics information */ + + +typedef struct Token { + int token; + SemInfo seminfo; +} Token; + + +typedef struct LexState { + int current; /* current character (charint) */ + int linenumber; /* input line counter */ + int lastline; /* line of last token `consumed' */ + Token t; /* current token */ + Token lookahead; /* look ahead token */ + struct FuncState *fs; /* `FuncState' is private to the parser */ + struct lua_State *L; + ZIO *z; /* input stream */ + Mbuffer *buff; /* buffer for tokens */ + TString *source; /* current source name */ + int nestlevel; /* level of nested non-terminals */ +} LexState; + + +void luaX_init (lua_State *L); +void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source); +int luaX_lex (LexState *LS, SemInfo *seminfo); +void luaX_checklimit (LexState *ls, int val, int limit, const char *msg); +void luaX_syntaxerror (LexState *ls, const char *s); +void luaX_errorline (LexState *ls, const char *s, const char *token, int line); +const char *luaX_token2str (LexState *ls, int token); + + +#endif diff --git a/src/llimits.h b/src/llimits.h new file mode 100644 index 0000000..343c922 --- /dev/null +++ b/src/llimits.h @@ -0,0 +1,185 @@ +/* +** $Id: llimits.h,v 1.52 2003/02/20 19:33:23 roberto Exp $ +** Limits, basic types, and some other `installation-dependent' definitions +** See Copyright Notice in lua.h +*/ + +#ifndef llimits_h +#define llimits_h + + +#include +#include + + +#include "lua.h" + + +/* +** try to find number of bits in an integer +*/ +#ifndef BITS_INT +/* avoid overflows in comparison */ +#if INT_MAX-20 < 32760 +#define BITS_INT 16 +#else +#if INT_MAX > 2147483640L +/* machine has at least 32 bits */ +#define BITS_INT 32 +#else +#error "you must define BITS_INT with number of bits in an integer" +#endif +#endif +#endif + + +/* +** the following types define integer types for values that may not +** fit in a `small int' (16 bits), but may waste space in a +** `large long' (64 bits). The current definitions should work in +** any machine, but may not be optimal. +*/ + +/* an unsigned integer to hold hash values */ +typedef unsigned int lu_hash; +/* its signed equivalent */ +typedef int ls_hash; + +/* an unsigned integer big enough to count the total memory used by Lua; */ +/* it should be at least as large as size_t */ +typedef unsigned long lu_mem; + +#define MAX_LUMEM ULONG_MAX + + +/* an integer big enough to count the number of strings in use */ +typedef long ls_nstr; + +/* chars used as small naturals (so that `char' is reserved for characters) */ +typedef unsigned char lu_byte; + + +#define MAX_SIZET ((size_t)(~(size_t)0)-2) + + +#define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ + +/* +** conversion of pointer to integer +** this is for hashing only; there is no problem if the integer +** cannot hold the whole pointer value +*/ +#define IntPoint(p) ((lu_hash)(p)) + + + +/* type to ensure maximum alignment */ +#ifndef LUSER_ALIGNMENT_T +typedef union { double u; void *s; long l; } L_Umaxalign; +#else +typedef LUSER_ALIGNMENT_T L_Umaxalign; +#endif + + +/* result of `usual argument conversion' over lua_Number */ +#ifndef LUA_UACNUMBER +typedef double l_uacNumber; +#else +typedef LUA_UACNUMBER l_uacNumber; +#endif + + +#ifndef lua_assert +#define lua_assert(c) /* empty */ +#endif + + +#ifndef check_exp +#define check_exp(c,e) (e) +#endif + + +#ifndef UNUSED +#define UNUSED(x) ((void)(x)) /* to avoid warnings */ +#endif + + +#ifndef cast +#define cast(t, exp) ((t)(exp)) +#endif + + + +/* +** type for virtual-machine instructions +** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) +*/ +typedef unsigned long Instruction; + + +/* maximum depth for calls (unsigned short) */ +#ifndef LUA_MAXCALLS +#define LUA_MAXCALLS 4096 +#endif + + +/* +** maximum depth for C calls (unsigned short): Not too big, or may +** overflow the C stack... +*/ + +#ifndef LUA_MAXCCALLS +#define LUA_MAXCCALLS 200 +#endif + + +/* maximum size for the C stack */ +#ifndef LUA_MAXCSTACK +#define LUA_MAXCSTACK 2048 +#endif + + +/* maximum stack for a Lua function */ +#define MAXSTACK 250 + + +/* maximum number of variables declared in a function */ +#ifndef MAXVARS +#define MAXVARS 200 /* arbitrary limit ( + +#define lmem_c + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "tier0/memdbgon.h" + + +/* +** definition for realloc function. It must assure that l_realloc(NULL, +** 0, x) allocates a new block (ANSI C assures that). (`os' is the old +** block size; some allocators may use that.) +*/ +#ifndef l_realloc +#define l_realloc(b,os,s) realloc(b,s) +#endif + +/* +** definition for free function. (`os' is the old block size; some +** allocators may use that.) +*/ +#ifndef l_free +#define l_free(b,os) free(b) +#endif + + +#define MINSIZEARRAY 4 + + +void *luaM_growaux (lua_State *L, void *block, int *size, int size_elems, + int limit, const char *errormsg) { + void *newblock; + int newsize = (*size)*2; + if (newsize < MINSIZEARRAY) + newsize = MINSIZEARRAY; /* minimum size */ + else if (*size >= limit/2) { /* cannot double it? */ + if (*size < limit - MINSIZEARRAY) /* try something smaller... */ + newsize = limit; /* still have at least MINSIZEARRAY free places */ + else luaG_runerror(L, errormsg); + } + newblock = luaM_realloc(L, block, + cast(lu_mem, *size)*cast(lu_mem, size_elems), + cast(lu_mem, newsize)*cast(lu_mem, size_elems)); + *size = newsize; /* update only when everything else is OK */ + return newblock; +} + + +/* +** generic allocation routine. +*/ +void *luaM_realloc (lua_State *L, void *block, lu_mem oldsize, lu_mem size) { + lua_assert((oldsize == 0) == (block == NULL)); + if (size == 0) { + if (block != NULL) { + l_free(block, oldsize); + block = NULL; + } + else return NULL; /* avoid `nblocks' computations when oldsize==size==0 */ + } + else if (size >= MAX_SIZET) + luaG_runerror(L, "memory allocation error: block too big"); + else { + block = l_realloc(block, oldsize, size); + if (block == NULL) { + if (L) + luaD_throw(L, LUA_ERRMEM); + else return NULL; /* error before creating state! */ + } + } + if (L) { + lua_assert(G(L) != NULL && G(L)->nblocks > 0); + G(L)->nblocks -= oldsize; + G(L)->nblocks += size; + } + return block; +} + diff --git a/src/lmem.h b/src/lmem.h new file mode 100644 index 0000000..1bb4fde --- /dev/null +++ b/src/lmem.h @@ -0,0 +1,44 @@ +/* +** $Id: lmem.h,v 1.26 2002/05/01 20:40:42 roberto Exp $ +** Interface to Memory Manager +** See Copyright Notice in lua.h +*/ + +#ifndef lmem_h +#define lmem_h + + +#include + +#include "llimits.h" +#include "lua.h" + +#define MEMERRMSG "not enough memory" + + +void *luaM_realloc (lua_State *L, void *oldblock, lu_mem oldsize, lu_mem size); + +void *luaM_growaux (lua_State *L, void *block, int *size, int size_elem, + int limit, const char *errormsg); + +#define luaM_free(L, b, s) luaM_realloc(L, (b), (s), 0) +#define luaM_freelem(L, b) luaM_realloc(L, (b), sizeof(*(b)), 0) +#define luaM_freearray(L, b, n, t) luaM_realloc(L, (b), \ + cast(lu_mem, n)*cast(lu_mem, sizeof(t)), 0) + +#define luaM_malloc(L, t) luaM_realloc(L, NULL, 0, (t)) +#define luaM_new(L, t) cast(t *, luaM_malloc(L, sizeof(t))) +#define luaM_newvector(L, n,t) cast(t *, luaM_malloc(L, \ + cast(lu_mem, n)*cast(lu_mem, sizeof(t)))) + +#define luaM_growvector(L,v,nelems,size,t,limit,e) \ + if (((nelems)+1) > (size)) \ + ((v)=cast(t *, luaM_growaux(L,v,&(size),sizeof(t),limit,e))) + +#define luaM_reallocvector(L, v,oldn,n,t) \ + ((v)=cast(t *, luaM_realloc(L, v,cast(lu_mem, oldn)*cast(lu_mem, sizeof(t)), \ + cast(lu_mem, n)*cast(lu_mem, sizeof(t))))) + + +#endif + diff --git a/src/lobject.cpp b/src/lobject.cpp new file mode 100644 index 0000000..9522b6e --- /dev/null +++ b/src/lobject.cpp @@ -0,0 +1,195 @@ +/* +** $Id: lobject.c,v 1.97 2003/04/03 13:35:34 roberto Exp $ +** Some generic functions over Lua objects +** See Copyright Notice in lua.h +*/ + +#include +#include +#include +#include + +#define lobject_c + +#include "lua.h" + +#include "ldo.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "lvm.h" + + +/* function to convert a string to a lua_Number */ +#ifndef lua_str2number +#define lua_str2number(s,p) strtod((s), (p)) +#endif + + +const TObject luaO_nilobject = {LUA_TNIL, {NULL}}; + + +/* +** converts an integer to a "floating point byte", represented as +** (mmmmmxxx), where the real value is (xxx) * 2^(mmmmm) +*/ +int luaO_int2fb (unsigned int x) { + int m = 0; /* mantissa */ + while (x >= (1<<3)) { + x = (x+1) >> 1; + m++; + } + return (m << 3) | cast(int, x); +} + + +int luaO_log2 (unsigned int x) { + static const lu_byte log_8[255] = { + 0, + 1,1, + 2,2,2,2, + 3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 + }; + if (x >= 0x00010000) { + if (x >= 0x01000000) return log_8[((x>>24) & 0xff) - 1]+24; + else return log_8[((x>>16) & 0xff) - 1]+16; + } + else { + if (x >= 0x00000100) return log_8[((x>>8) & 0xff) - 1]+8; + else if (x) return log_8[(x & 0xff) - 1]; + return -1; /* special `log' for 0 */ + } +} + + +int luaO_rawequalObj (const TObject *t1, const TObject *t2) { + if (ttype(t1) != ttype(t2)) return 0; + else switch (ttype(t1)) { + case LUA_TNIL: + return 1; + case LUA_TNUMBER: + return nvalue(t1) == nvalue(t2); + case LUA_TBOOLEAN: + return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ + case LUA_TLIGHTUSERDATA: + return pvalue(t1) == pvalue(t2); + default: + lua_assert(iscollectable(t1)); + return gcvalue(t1) == gcvalue(t2); + } +} + + +int luaO_str2d (const char *s, lua_Number *result) { + char *endptr; + lua_Number res = lua_str2number(s, &endptr); + if (endptr == s) return 0; /* no conversion */ + while (isspace((unsigned char)(*endptr))) endptr++; + if (*endptr != '\0') return 0; /* invalid trailing characters? */ + *result = res; + return 1; +} + + + +static void pushstr (lua_State *L, const char *str) { + setsvalue2s(L->top, luaS_new(L, str)); + incr_top(L); +} + + +/* this function handles only `%d', `%c', %f, and `%s' formats */ +const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { + int n = 1; + pushstr(L, ""); + for (;;) { + const char *e = strchr(fmt, '%'); + if (e == NULL) break; + setsvalue2s(L->top, luaS_newlstr(L, fmt, e-fmt)); + incr_top(L); + switch (*(e+1)) { + case 's': + pushstr(L, va_arg(argp, char *)); + break; + case 'c': { + char buff[2]; + buff[0] = cast(char, va_arg(argp, int)); + buff[1] = '\0'; + pushstr(L, buff); + break; + } + case 'd': + setnvalue(L->top, cast(lua_Number, va_arg(argp, int))); + incr_top(L); + break; + case 'f': + setnvalue(L->top, cast(lua_Number, va_arg(argp, l_uacNumber))); + incr_top(L); + break; + case '%': + pushstr(L, "%"); + break; + default: lua_assert(0); + } + n += 2; + fmt = e+2; + } + pushstr(L, fmt); + luaV_concat(L, n+1, L->top - L->base - 1); + L->top -= n; + return svalue(L->top - 1); +} + + +const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { + const char *msg; + va_list argp; + va_start(argp, fmt); + msg = luaO_pushvfstring(L, fmt, argp); + va_end(argp); + return msg; +} + + +void luaO_chunkid (char *out, const char *source, int bufflen) { + if (*source == '=') { + strncpy(out, source+1, bufflen); /* remove first char */ + out[bufflen-1] = '\0'; /* ensures null termination */ + } + else { /* out = "source", or "...source" */ + if (*source == '@') { + int l; + source++; /* skip the `@' */ + bufflen -= sizeof(" `...' "); + l = strlen(source); + strcpy(out, ""); + if (l>bufflen) { + source += (l-bufflen); /* get last part of file name */ + strcat(out, "..."); + } + strcat(out, source); + } + else { /* out = [string "string"] */ + int len = strcspn(source, "\n"); /* stop at first newline */ + bufflen -= sizeof(" [string \"...\"] "); + if (len > bufflen) len = bufflen; + strcpy(out, "[string \""); + if (source[len] != '\0') { /* must truncate? */ + strncat(out, source, len); + strcat(out, "..."); + } + else + strcat(out, source); + strcat(out, "\"]"); + } + } +} diff --git a/src/lobject.h b/src/lobject.h new file mode 100644 index 0000000..321a7e0 --- /dev/null +++ b/src/lobject.h @@ -0,0 +1,336 @@ +/* +** $Id: lobject.h,v 1.159 2003/03/18 12:50:04 roberto Exp $ +** Type definitions for Lua objects +** See Copyright Notice in lua.h +*/ + +#ifndef lobject_h +#define lobject_h + + +#include "llimits.h" +#include "lua.h" + + +/* tags for values visible from Lua */ +#define NUM_TAGS LUA_TTHREAD + + +/* +** Extra tags for non-values +*/ +#define LUA_TPROTO (NUM_TAGS+1) +#define LUA_TUPVAL (NUM_TAGS+2) + + +/* +** Union of all collectable objects +*/ +typedef union GCObject GCObject; + + +/* +** Common Header for all collectable objects (in macro form, to be +** included in other objects) +*/ +#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked + + +/* +** Common header in struct form +*/ +typedef struct GCheader { + CommonHeader; +} GCheader; + + + + +/* +** Union of all Lua values +*/ +typedef union { + GCObject *gc; + void *p; + lua_Number n; + int b; +} Value; + + +/* +** Lua values (or `tagged objects') +*/ +typedef struct lua_TObject { + int tt; + Value value; +} TObject; + + +/* Macros to test type */ +#define ttisnil(o) (ttype(o) == LUA_TNIL) +#define ttisnumber(o) (ttype(o) == LUA_TNUMBER) +#define ttisstring(o) (ttype(o) == LUA_TSTRING) +#define ttistable(o) (ttype(o) == LUA_TTABLE) +#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) +#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN) +#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA) +#define ttisthread(o) (ttype(o) == LUA_TTHREAD) +#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) + +/* Macros to access values */ +#define ttype(o) ((o)->tt) +#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) +#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) +#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) +#define tsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) +#define uvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) +#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl) +#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h) +#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b) +#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th) + +#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) + +/* Macros to set values */ +#define setnvalue(obj,x) \ + { TObject *i_o=(obj); i_o->tt=LUA_TNUMBER; i_o->value.n=(x); } + +#define chgnvalue(obj,x) \ + check_exp(ttype(obj)==LUA_TNUMBER, (obj)->value.n=(x)) + +#define setpvalue(obj,x) \ + { TObject *i_o=(obj); i_o->tt=LUA_TLIGHTUSERDATA; i_o->value.p=(x); } + +#define setbvalue(obj,x) \ + { TObject *i_o=(obj); i_o->tt=LUA_TBOOLEAN; i_o->value.b=(x); } + +#define setsvalue(obj,x) \ + { TObject *i_o=(obj); i_o->tt=LUA_TSTRING; \ + i_o->value.gc=cast(GCObject *, (x)); \ + lua_assert(i_o->value.gc->gch.tt == LUA_TSTRING); } + +#define setuvalue(obj,x) \ + { TObject *i_o=(obj); i_o->tt=LUA_TUSERDATA; \ + i_o->value.gc=cast(GCObject *, (x)); \ + lua_assert(i_o->value.gc->gch.tt == LUA_TUSERDATA); } + +#define setthvalue(obj,x) \ + { TObject *i_o=(obj); i_o->tt=LUA_TTHREAD; \ + i_o->value.gc=cast(GCObject *, (x)); \ + lua_assert(i_o->value.gc->gch.tt == LUA_TTHREAD); } + +#define setclvalue(obj,x) \ + { TObject *i_o=(obj); i_o->tt=LUA_TFUNCTION; \ + i_o->value.gc=cast(GCObject *, (x)); \ + lua_assert(i_o->value.gc->gch.tt == LUA_TFUNCTION); } + +#define sethvalue(obj,x) \ + { TObject *i_o=(obj); i_o->tt=LUA_TTABLE; \ + i_o->value.gc=cast(GCObject *, (x)); \ + lua_assert(i_o->value.gc->gch.tt == LUA_TTABLE); } + +#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) + + + +/* +** for internal debug only +*/ +#define checkconsistency(obj) \ + lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt)) + + +#define setobj(obj1,obj2) \ + { const TObject *o2=(obj2); TObject *o1=(obj1); \ + checkconsistency(o2); \ + o1->tt=o2->tt; o1->value = o2->value; } + + +/* +** different types of sets, according to destination +*/ + +/* from stack to (same) stack */ +#define setobjs2s setobj +/* to stack (not from same stack) */ +#define setobj2s setobj +#define setsvalue2s setsvalue +/* from table to same table */ +#define setobjt2t setobj +/* to table */ +#define setobj2t setobj +/* to new object */ +#define setobj2n setobj +#define setsvalue2n setsvalue + +#define setttype(obj, tt) (ttype(obj) = (tt)) + + +#define iscollectable(o) (ttype(o) >= LUA_TSTRING) + + + +typedef TObject *StkId; /* index to stack elements */ + + +/* +** String headers for string table +*/ +typedef union TString { + L_Umaxalign dummy; /* ensures maximum alignment for strings */ + struct { + CommonHeader; + lu_byte reserved; + lu_hash hash; + size_t len; + } tsv; +} TString; + + +#define getstr(ts) cast(const char *, (ts) + 1) +#define svalue(o) getstr(tsvalue(o)) + + + +typedef union Udata { + L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ + struct { + CommonHeader; + struct Table *metatable; + size_t len; + } uv; +} Udata; + + + + +/* +** Function Prototypes +*/ +typedef struct Proto { + CommonHeader; + TObject *k; /* constants used by the function */ + Instruction *code; + struct Proto **p; /* functions defined inside the function */ + int *lineinfo; /* map from opcodes to source lines */ + struct LocVar *locvars; /* information about local variables */ + TString **upvalues; /* upvalue names */ + TString *source; + int sizeupvalues; + int sizek; /* size of `k' */ + int sizecode; + int sizelineinfo; + int sizep; /* size of `p' */ + int sizelocvars; + int lineDefined; + GCObject *gclist; + lu_byte nups; /* number of upvalues */ + lu_byte numparams; + lu_byte is_vararg; + lu_byte maxstacksize; +} Proto; + + +typedef struct LocVar { + TString *varname; + int startpc; /* first point where variable is active */ + int endpc; /* first point where variable is dead */ +} LocVar; + + + +/* +** Upvalues +*/ + +typedef struct UpVal { + CommonHeader; + TObject *v; /* points to stack or to its own value */ + TObject value; /* the value (when closed) */ +} UpVal; + + +/* +** Closures +*/ + +#define ClosureHeader \ + CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist + +typedef struct CClosure { + ClosureHeader; + lua_CFunction f; + TObject upvalue[1]; +} CClosure; + + +typedef struct LClosure { + ClosureHeader; + struct Proto *p; + TObject g; /* global table for this closure */ + UpVal *upvals[1]; +} LClosure; + + +typedef union Closure { + CClosure c; + LClosure l; +} Closure; + + +#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC) +#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC) + + +/* +** Tables +*/ + +typedef struct Node { + TObject i_key; + TObject i_val; + struct Node *next; /* for chaining */ +} Node; + + +typedef struct Table { + CommonHeader; + lu_byte flags; /* 1<

lsizenode)) + + + +extern const TObject luaO_nilobject; + +int luaO_log2 (unsigned int x); +int luaO_int2fb (unsigned int x); +#define fb2int(x) (((x) & 7) << ((x) >> 3)) + +int luaO_rawequalObj (const TObject *t1, const TObject *t2); +int luaO_str2d (const char *s, lua_Number *result); + +const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp); +const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); +void luaO_chunkid (char *out, const char *source, int len); + + +#endif diff --git a/src/lopcodes.cpp b/src/lopcodes.cpp new file mode 100644 index 0000000..993e426 --- /dev/null +++ b/src/lopcodes.cpp @@ -0,0 +1,102 @@ +/* +** $Id: lopcodes.c,v 1.22 2002/12/04 17:38:31 roberto Exp $ +** extracted automatically from lopcodes.h by mkprint.lua +** DO NOT EDIT +** See Copyright Notice in lua.h +*/ + + +#define lopcodes_c + +#include "lua.h" + +#include "lobject.h" +#include "lopcodes.h" + + +#ifdef LUA_OPNAMES + +const char *const luaP_opnames[] = { + "MOVE", + "LOADK", + "LOADBOOL", + "LOADNIL", + "GETUPVAL", + "GETGLOBAL", + "GETTABLE", + "SETGLOBAL", + "SETUPVAL", + "SETTABLE", + "NEWTABLE", + "SELF", + "ADD", + "SUB", + "MUL", + "DIV", + "POW", + "UNM", + "NOT", + "CONCAT", + "JMP", + "EQ", + "LT", + "LE", + "TEST", + "CALL", + "TAILCALL", + "RETURN", + "FORLOOP", + "TFORLOOP", + "TFORPREP", + "SETLIST", + "SETLISTO", + "CLOSE", + "CLOSURE" +}; + +#endif + +#define opmode(t,b,bk,ck,sa,k,m) (((t)<>1) /* `sBx' is signed */ +#else +#define MAXARG_Bx MAX_INT +#define MAXARG_sBx MAX_INT +#endif + + +#define MAXARG_A ((1<>POS_A)) +#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ + ((cast(Instruction, u)<>POS_B) & MASK1(SIZE_B,0))) +#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ + ((cast(Instruction, b)<>POS_C) & MASK1(SIZE_C,0))) +#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ + ((cast(Instruction, b)<>POS_Bx) & MASK1(SIZE_Bx,0))) +#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \ + ((cast(Instruction, b)< C) then R(A) := R(B) else pc++ */ + +OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ +OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ +OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ + +OP_FORLOOP,/* A sBx R(A)+=R(A+2); if R(A) =) R(A)*/ +OP_CLOSURE/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ +} OpCode; + + +#define NUM_OPCODES (cast(int, OP_CLOSURE+1)) + + + +/*=========================================================================== + Notes: + (1) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, + and can be 0: OP_CALL then sets `top' to last_result+1, so + next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. + + (2) In OP_RETURN, if (B == 0) then return up to `top' + + (3) For comparisons, B specifies what conditions the test should accept. + + (4) All `skips' (pc++) assume that next instruction is a jump +===========================================================================*/ + + +/* +** masks for instruction properties +*/ +enum OpModeMask { + OpModeBreg = 2, /* B is a register */ + OpModeBrk, /* B is a register/constant */ + OpModeCrk, /* C is a register/constant */ + OpModesetA, /* instruction set register A */ + OpModeK, /* Bx is a constant */ + OpModeT /* operator is a test */ + +}; + + +extern const lu_byte luaP_opmodes[NUM_OPCODES]; + +#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) +#define testOpMode(m, b) (luaP_opmodes[m] & (1 << (b))) + + +#ifdef LUA_OPNAMES +extern const char *const luaP_opnames[]; /* opcode names */ +#endif + + + +/* number of list items to accumulate before a SETLIST instruction */ +/* (must be a power of 2) */ +#define LFIELDS_PER_FLUSH 32 + + +#endif diff --git a/src/lparser.cpp b/src/lparser.cpp new file mode 100644 index 0000000..99bd302 --- /dev/null +++ b/src/lparser.cpp @@ -0,0 +1,1333 @@ +/* +** $Id: lparser.c,v 1.208a 2003/04/03 13:35:34 roberto Exp $ +** Lua Parser +** See Copyright Notice in lua.h +*/ + + +#include + +#define lparser_c + +#include "lua.h" + +#include "lcode.h" +#include "ldebug.h" +#include "lfunc.h" +#include "llex.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" + + + + +#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) + + +#define enterlevel(ls) if (++(ls)->nestlevel > LUA_MAXPARSERLEVEL) \ + luaX_syntaxerror(ls, "too many syntax levels"); +#define leavelevel(ls) ((ls)->nestlevel--) + + +/* +** nodes for block list (list of active blocks) +*/ +typedef struct BlockCnt { + struct BlockCnt *previous; /* chain */ + int breaklist; /* list of jumps out of this loop */ + int nactvar; /* # active local variables outside the breakable structure */ + int upval; /* true if some variable in the block is an upvalue */ + int isbreakable; /* true if `block' is a loop */ +} BlockCnt; + + + +/* +** prototypes for recursive non-terminal functions +*/ +static void chunk (LexState *ls); +static void expr (LexState *ls, expdesc *v); + + + +static void next (LexState *ls) { + ls->lastline = ls->linenumber; + if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ + ls->t = ls->lookahead; /* use this one */ + ls->lookahead.token = TK_EOS; /* and discharge it */ + } + else + ls->t.token = luaX_lex(ls, &ls->t.seminfo); /* read next token */ +} + + +static void lookahead (LexState *ls) { + lua_assert(ls->lookahead.token == TK_EOS); + ls->lookahead.token = luaX_lex(ls, &ls->lookahead.seminfo); +} + + +static void error_expected (LexState *ls, int token) { + luaX_syntaxerror(ls, + luaO_pushfstring(ls->L, "`%s' expected", luaX_token2str(ls, token))); +} + + +static int testnext (LexState *ls, int c) { + if (ls->t.token == c) { + next(ls); + return 1; + } + else return 0; +} + + +static void check (LexState *ls, int c) { + if (!testnext(ls, c)) + error_expected(ls, c); +} + + +#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } + + + +static void check_match (LexState *ls, int what, int who, int where) { + if (!testnext(ls, what)) { + if (where == ls->linenumber) + error_expected(ls, what); + else { + luaX_syntaxerror(ls, luaO_pushfstring(ls->L, + "`%s' expected (to close `%s' at line %d)", + luaX_token2str(ls, what), luaX_token2str(ls, who), where)); + } + } +} + + +static TString *str_checkname (LexState *ls) { + TString *ts; + check_condition(ls, (ls->t.token == TK_NAME), " expected"); + ts = ls->t.seminfo.ts; + next(ls); + return ts; +} + + +static void init_exp (expdesc *e, expkind k, int i) { + e->f = e->t = NO_JUMP; + e->k = k; + e->info = i; +} + + +static void codestring (LexState *ls, expdesc *e, TString *s) { + init_exp(e, VK, luaK_stringK(ls->fs, s)); +} + + +static void checkname(LexState *ls, expdesc *e) { + codestring(ls, e, str_checkname(ls)); +} + + +static int luaI_registerlocalvar (LexState *ls, TString *varname) { + FuncState *fs = ls->fs; + Proto *f = fs->f; + luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, + LocVar, MAX_INT, ""); + f->locvars[fs->nlocvars].varname = varname; + return fs->nlocvars++; +} + + +static void new_localvar (LexState *ls, TString *name, int n) { + FuncState *fs = ls->fs; + luaX_checklimit(ls, fs->nactvar+n+1, MAXVARS, "local variables"); + fs->actvar[fs->nactvar+n] = luaI_registerlocalvar(ls, name); +} + + +static void adjustlocalvars (LexState *ls, int nvars) { + FuncState *fs = ls->fs; + fs->nactvar += nvars; + for (; nvars; nvars--) { + getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc; + } +} + + +static void removevars (LexState *ls, int tolevel) { + FuncState *fs = ls->fs; + while (fs->nactvar > tolevel) + getlocvar(fs, --fs->nactvar).endpc = fs->pc; +} + + +static void new_localvarstr (LexState *ls, const char *name, int n) { + new_localvar(ls, luaS_new(ls->L, name), n); +} + + +static void create_local (LexState *ls, const char *name) { + new_localvarstr(ls, name, 0); + adjustlocalvars(ls, 1); +} + + +static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { + int i; + Proto *f = fs->f; + for (i=0; inups; i++) { + if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->info) { + lua_assert(fs->f->upvalues[i] == name); + return i; + } + } + /* new one */ + luaX_checklimit(fs->ls, f->nups + 1, MAXUPVALUES, "upvalues"); + luaM_growvector(fs->L, fs->f->upvalues, f->nups, fs->f->sizeupvalues, + TString *, MAX_INT, ""); + fs->f->upvalues[f->nups] = name; + fs->upvalues[f->nups] = *v; + return f->nups++; +} + + +static int searchvar (FuncState *fs, TString *n) { + int i; + for (i=fs->nactvar-1; i >= 0; i--) { + if (n == getlocvar(fs, i).varname) + return i; + } + return -1; /* not found */ +} + + +static void markupval (FuncState *fs, int level) { + BlockCnt *bl = fs->bl; + while (bl && bl->nactvar > level) bl = bl->previous; + if (bl) bl->upval = 1; +} + + +static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { + if (fs == NULL) /* no more levels? */ + init_exp(var, VGLOBAL, NO_REG); /* default is global variable */ + else { + int v = searchvar(fs, n); /* look up at current level */ + if (v >= 0) { + init_exp(var, VLOCAL, v); + if (!base) + markupval(fs, v); /* local will be used as an upval */ + } + else { /* not found at current level; try upper one */ + singlevaraux(fs->prev, n, var, 0); + if (var->k == VGLOBAL) { + if (base) + var->info = luaK_stringK(fs, n); /* info points to global name */ + } + else { /* LOCAL or UPVAL */ + var->info = indexupvalue(fs, n, var); + var->k = VUPVAL; /* upvalue in this level */ + } + } + } +} + + +static TString *singlevar (LexState *ls, expdesc *var, int base) { + TString *varname = str_checkname(ls); + singlevaraux(ls->fs, varname, var, base); + return varname; +} + + +static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { + FuncState *fs = ls->fs; + int extra = nvars - nexps; + if (e->k == VCALL) { + extra++; /* includes call itself */ + if (extra <= 0) extra = 0; + else luaK_reserveregs(fs, extra-1); + luaK_setcallreturns(fs, e, extra); /* call provides the difference */ + } + else { + if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ + if (extra > 0) { + int reg = fs->freereg; + luaK_reserveregs(fs, extra); + luaK_nil(fs, reg, extra); + } + } +} + + +static void code_params (LexState *ls, int nparams, int dots) { + FuncState *fs = ls->fs; + adjustlocalvars(ls, nparams); + luaX_checklimit(ls, fs->nactvar, MAXPARAMS, "parameters"); + fs->f->numparams = cast(lu_byte, fs->nactvar); + fs->f->is_vararg = cast(lu_byte, dots); + if (dots) + create_local(ls, "arg"); + luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ +} + + +static void enterblock (FuncState *fs, BlockCnt *bl, int isbreakable) { + bl->breaklist = NO_JUMP; + bl->isbreakable = isbreakable; + bl->nactvar = fs->nactvar; + bl->upval = 0; + bl->previous = fs->bl; + fs->bl = bl; + lua_assert(fs->freereg == fs->nactvar); +} + + +static void leaveblock (FuncState *fs) { + BlockCnt *bl = fs->bl; + fs->bl = bl->previous; + removevars(fs->ls, bl->nactvar); + if (bl->upval) + luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); + lua_assert(bl->nactvar == fs->nactvar); + fs->freereg = fs->nactvar; /* free registers */ + luaK_patchtohere(fs, bl->breaklist); +} + + +static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { + FuncState *fs = ls->fs; + Proto *f = fs->f; + int i; + luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, + MAXARG_Bx, "constant table overflow"); + f->p[fs->np++] = func->f; + init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); + for (i=0; if->nups; i++) { + OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; + luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0); + } +} + + +static void open_func (LexState *ls, FuncState *fs) { + Proto *f = luaF_newproto(ls->L); + fs->f = f; + fs->prev = ls->fs; /* linked list of funcstates */ + fs->ls = ls; + fs->L = ls->L; + ls->fs = fs; + fs->pc = 0; + fs->lasttarget = 0; + fs->jpc = NO_JUMP; + fs->freereg = 0; + fs->nk = 0; + fs->h = luaH_new(ls->L, 0, 0); + fs->np = 0; + fs->nlocvars = 0; + fs->nactvar = 0; + fs->bl = NULL; + f->source = ls->source; + f->maxstacksize = 2; /* registers 0/1 are always valid */ +} + + +static void close_func (LexState *ls) { + lua_State *L = ls->L; + FuncState *fs = ls->fs; + Proto *f = fs->f; + removevars(ls, 0); + luaK_codeABC(fs, OP_RETURN, 0, 1, 0); /* final return */ + luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); + f->sizecode = fs->pc; + luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); + f->sizelineinfo = fs->pc; + luaM_reallocvector(L, f->k, f->sizek, fs->nk, TObject); + f->sizek = fs->nk; + luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); + f->sizep = fs->np; + luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); + f->sizelocvars = fs->nlocvars; + luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *); + f->sizeupvalues = f->nups; + lua_assert(luaG_checkcode(f)); + lua_assert(fs->bl == NULL); + ls->fs = fs->prev; +} + + +Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff) { + struct LexState lexstate; + struct FuncState funcstate; + lexstate.buff = buff; + lexstate.nestlevel = 0; + luaX_setinput(L, &lexstate, z, luaS_new(L, zname(z))); + open_func(&lexstate, &funcstate); + next(&lexstate); /* read first token */ + chunk(&lexstate); + check_condition(&lexstate, (lexstate.t.token == TK_EOS), " expected"); + close_func(&lexstate); + lua_assert(funcstate.prev == NULL); + lua_assert(funcstate.f->nups == 0); + lua_assert(lexstate.nestlevel == 0); + return funcstate.f; +} + + + +/*============================================================*/ +/* GRAMMAR RULES */ +/*============================================================*/ + + +static void luaY_field (LexState *ls, expdesc *v) { + /* field -> ['.' | ':'] NAME */ + FuncState *fs = ls->fs; + expdesc key; + luaK_exp2anyreg(fs, v); + next(ls); /* skip the dot or colon */ + checkname(ls, &key); + luaK_indexed(fs, v, &key); +} + + +static void luaY_index (LexState *ls, expdesc *v) { + /* index -> '[' expr ']' */ + next(ls); /* skip the '[' */ + expr(ls, v); + luaK_exp2val(ls->fs, v); + check(ls, ']'); +} + + +/* +** {====================================================================== +** Rules for Constructors +** ======================================================================= +*/ + + +struct ConsControl { + expdesc v; /* last list item read */ + expdesc *t; /* table descriptor */ + int nh; /* total number of `record' elements */ + int na; /* total number of array elements */ + int tostore; /* number of array elements pending to be stored */ +}; + + +static void recfield (LexState *ls, struct ConsControl *cc) { + /* recfield -> (NAME | `['exp1`]') = exp1 */ + FuncState *fs = ls->fs; + int reg = ls->fs->freereg; + expdesc key, val; + if (ls->t.token == TK_NAME) { + luaX_checklimit(ls, cc->nh, MAX_INT, "items in a constructor"); + cc->nh++; + checkname(ls, &key); + } + else /* ls->t.token == '[' */ + luaY_index(ls, &key); + check(ls, '='); + luaK_exp2RK(fs, &key); + expr(ls, &val); + luaK_codeABC(fs, OP_SETTABLE, cc->t->info, luaK_exp2RK(fs, &key), + luaK_exp2RK(fs, &val)); + fs->freereg = reg; /* free registers */ +} + + +static void closelistfield (FuncState *fs, struct ConsControl *cc) { + if (cc->v.k == VVOID) return; /* there is no list item */ + luaK_exp2nextreg(fs, &cc->v); + cc->v.k = VVOID; + if (cc->tostore == LFIELDS_PER_FLUSH) { + luaK_codeABx(fs, OP_SETLIST, cc->t->info, cc->na-1); /* flush */ + cc->tostore = 0; /* no more items pending */ + fs->freereg = cc->t->info + 1; /* free registers */ + } +} + + +static void lastlistfield (FuncState *fs, struct ConsControl *cc) { + if (cc->tostore == 0) return; + if (cc->v.k == VCALL) { + luaK_setcallreturns(fs, &cc->v, LUA_MULTRET); + luaK_codeABx(fs, OP_SETLISTO, cc->t->info, cc->na-1); + } + else { + if (cc->v.k != VVOID) + luaK_exp2nextreg(fs, &cc->v); + luaK_codeABx(fs, OP_SETLIST, cc->t->info, cc->na-1); + } + fs->freereg = cc->t->info + 1; /* free registers */ +} + + +static void listfield (LexState *ls, struct ConsControl *cc) { + expr(ls, &cc->v); + luaX_checklimit(ls, cc->na, MAXARG_Bx, "items in a constructor"); + cc->na++; + cc->tostore++; +} + + +static void constructor (LexState *ls, expdesc *t) { + /* constructor -> ?? */ + FuncState *fs = ls->fs; + int line = ls->linenumber; + int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); + struct ConsControl cc; + cc.na = cc.nh = cc.tostore = 0; + cc.t = t; + init_exp(t, VRELOCABLE, pc); + init_exp(&cc.v, VVOID, 0); /* no value (yet) */ + luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ + check(ls, '{'); + do { + lua_assert(cc.v.k == VVOID || cc.tostore > 0); + testnext(ls, ';'); /* compatibility only */ + if (ls->t.token == '}') break; + closelistfield(fs, &cc); + switch(ls->t.token) { + case TK_NAME: { /* may be listfields or recfields */ + lookahead(ls); + if (ls->lookahead.token != '=') /* expression? */ + listfield(ls, &cc); + else + recfield(ls, &cc); + break; + } + case '[': { /* constructor_item -> recfield */ + recfield(ls, &cc); + break; + } + default: { /* constructor_part -> listfield */ + listfield(ls, &cc); + break; + } + } + } while (testnext(ls, ',') || testnext(ls, ';')); + check_match(ls, '}', '{', line); + lastlistfield(fs, &cc); + SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ + SETARG_C(fs->f->code[pc], luaO_log2(cc.nh)+1); /* set initial table size */ +} + +/* }====================================================================== */ + + + +static void parlist (LexState *ls) { + /* parlist -> [ param { `,' param } ] */ + int nparams = 0; + int dots = 0; + if (ls->t.token != ')') { /* is `parlist' not empty? */ + do { + switch (ls->t.token) { + case TK_DOTS: dots = 1; next(ls); break; + case TK_NAME: new_localvar(ls, str_checkname(ls), nparams++); break; + default: luaX_syntaxerror(ls, " or `...' expected"); + } + } while (!dots && testnext(ls, ',')); + } + code_params(ls, nparams, dots); +} + + +static void body (LexState *ls, expdesc *e, int needself, int line) { + /* body -> `(' parlist `)' chunk END */ + FuncState new_fs; + open_func(ls, &new_fs); + new_fs.f->lineDefined = line; + check(ls, '('); + if (needself) + create_local(ls, "self"); + parlist(ls); + check(ls, ')'); + chunk(ls); + check_match(ls, TK_END, TK_FUNCTION, line); + close_func(ls); + pushclosure(ls, &new_fs, e); +} + + +static int explist1 (LexState *ls, expdesc *v) { + /* explist1 -> expr { `,' expr } */ + int n = 1; /* at least one expression */ + expr(ls, v); + while (testnext(ls, ',')) { + luaK_exp2nextreg(ls->fs, v); + expr(ls, v); + n++; + } + return n; +} + + +static void funcargs (LexState *ls, expdesc *f) { + FuncState *fs = ls->fs; + expdesc args; + int base, nparams; + int line = ls->linenumber; + switch (ls->t.token) { + case '(': { /* funcargs -> `(' [ explist1 ] `)' */ + if (line != ls->lastline) + luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)"); + next(ls); + if (ls->t.token == ')') /* arg list is empty? */ + args.k = VVOID; + else { + explist1(ls, &args); + luaK_setcallreturns(fs, &args, LUA_MULTRET); + } + check_match(ls, ')', '(', line); + break; + } + case '{': { /* funcargs -> constructor */ + constructor(ls, &args); + break; + } + case TK_STRING: { /* funcargs -> STRING */ + codestring(ls, &args, ls->t.seminfo.ts); + next(ls); /* must use `seminfo' before `next' */ + break; + } + default: { + luaX_syntaxerror(ls, "function arguments expected"); + return; + } + } + lua_assert(f->k == VNONRELOC); + base = f->info; /* base register for call */ + if (args.k == VCALL) + nparams = LUA_MULTRET; /* open call */ + else { + if (args.k != VVOID) + luaK_exp2nextreg(fs, &args); /* close last argument */ + nparams = fs->freereg - (base+1); + } + init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); + luaK_fixline(fs, line); + fs->freereg = base+1; /* call remove function and arguments and leaves + (unless changed) one result */ +} + + + + +/* +** {====================================================================== +** Expression parsing +** ======================================================================= +*/ + + +static void prefixexp (LexState *ls, expdesc *v) { + /* prefixexp -> NAME | '(' expr ')' */ + switch (ls->t.token) { + case '(': { + int line = ls->linenumber; + next(ls); + expr(ls, v); + check_match(ls, ')', '(', line); + luaK_dischargevars(ls->fs, v); + return; + } + case TK_NAME: { + singlevar(ls, v, 1); + return; + } +#ifdef LUA_COMPATUPSYNTAX + case '%': { /* for compatibility only */ + TString *varname; + int line = ls->linenumber; + next(ls); /* skip `%' */ + varname = singlevar(ls, v, 1); + if (v->k != VUPVAL) + luaX_errorline(ls, "global upvalues are obsolete", + getstr(varname), line); + return; + } +#endif + default: { + luaX_syntaxerror(ls, "unexpected symbol"); + return; + } + } +} + + +static void primaryexp (LexState *ls, expdesc *v) { + /* primaryexp -> + prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ + FuncState *fs = ls->fs; + prefixexp(ls, v); + for (;;) { + switch (ls->t.token) { + case '.': { /* field */ + luaY_field(ls, v); + break; + } + case '[': { /* `[' exp1 `]' */ + expdesc key; + luaK_exp2anyreg(fs, v); + luaY_index(ls, &key); + luaK_indexed(fs, v, &key); + break; + } + case ':': { /* `:' NAME funcargs */ + expdesc key; + next(ls); + checkname(ls, &key); + luaK_self(fs, v, &key); + funcargs(ls, v); + break; + } + case '(': case TK_STRING: case '{': { /* funcargs */ + luaK_exp2nextreg(fs, v); + funcargs(ls, v); + break; + } + default: return; + } + } +} + + +static void simpleexp (LexState *ls, expdesc *v) { + /* simpleexp -> NUMBER | STRING | NIL | constructor | FUNCTION body + | primaryexp */ + switch (ls->t.token) { + case TK_NUMBER: { + init_exp(v, VK, luaK_numberK(ls->fs, ls->t.seminfo.r)); + next(ls); /* must use `seminfo' before `next' */ + break; + } + case TK_STRING: { + codestring(ls, v, ls->t.seminfo.ts); + next(ls); /* must use `seminfo' before `next' */ + break; + } + case TK_NIL: { + init_exp(v, VNIL, 0); + next(ls); + break; + } + case TK_TRUE: { + init_exp(v, VTRUE, 0); + next(ls); + break; + } + case TK_FALSE: { + init_exp(v, VFALSE, 0); + next(ls); + break; + } + case '{': { /* constructor */ + constructor(ls, v); + break; + } + case TK_FUNCTION: { + next(ls); + body(ls, v, 0, ls->linenumber); + break; + } + default: { + primaryexp(ls, v); + break; + } + } +} + + +static UnOpr getunopr (int op) { + switch (op) { + case TK_NOT: return OPR_NOT; + case '-': return OPR_MINUS; + default: return OPR_NOUNOPR; + } +} + + +static BinOpr getbinopr (int op) { + switch (op) { + case '+': return OPR_ADD; + case '-': return OPR_SUB; + case '*': return OPR_MULT; + case '/': return OPR_DIV; + case '^': return OPR_POW; + case TK_CONCAT: return OPR_CONCAT; + case TK_NE: return OPR_NE; + case TK_EQ: return OPR_EQ; + case '<': return OPR_LT; + case TK_LE: return OPR_LE; + case '>': return OPR_GT; + case TK_GE: return OPR_GE; + case TK_AND: return OPR_AND; + case TK_OR: return OPR_OR; + default: return OPR_NOBINOPR; + } +} + + +static const struct { + lu_byte left; /* left priority for each binary operator */ + lu_byte right; /* right priority */ +} priority[] = { /* ORDER OPR */ + {6, 6}, {6, 6}, {7, 7}, {7, 7}, /* arithmetic */ + {10, 9}, {5, 4}, /* power and concat (right associative) */ + {3, 3}, {3, 3}, /* equality */ + {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */ + {2, 2}, {1, 1} /* logical (and/or) */ +}; + +#define UNARY_PRIORITY 8 /* priority for unary operators */ + + +/* +** subexpr -> (simplexep | unop subexpr) { binop subexpr } +** where `binop' is any binary operator with a priority higher than `limit' +*/ +static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { + BinOpr op; + UnOpr uop; + enterlevel(ls); + uop = getunopr(ls->t.token); + if (uop != OPR_NOUNOPR) { + next(ls); + subexpr(ls, v, UNARY_PRIORITY); + luaK_prefix(ls->fs, uop, v); + } + else simpleexp(ls, v); + /* expand while operators have priorities higher than `limit' */ + op = getbinopr(ls->t.token); + while (op != OPR_NOBINOPR && cast(int, priority[op].left) > limit) { + expdesc v2; + BinOpr nextop; + next(ls); + luaK_infix(ls->fs, op, v); + /* read sub-expression with higher priority */ + nextop = subexpr(ls, &v2, cast(int, priority[op].right)); + luaK_posfix(ls->fs, op, v, &v2); + op = nextop; + } + leavelevel(ls); + return op; /* return first untreated operator */ +} + + +static void expr (LexState *ls, expdesc *v) { + subexpr(ls, v, -1); +} + +/* }==================================================================== */ + + + +/* +** {====================================================================== +** Rules for Statements +** ======================================================================= +*/ + + +static int block_follow (int token) { + switch (token) { + case TK_ELSE: case TK_ELSEIF: case TK_END: + case TK_UNTIL: case TK_EOS: + return 1; + default: return 0; + } +} + + +static void block (LexState *ls) { + /* block -> chunk */ + FuncState *fs = ls->fs; + BlockCnt bl; + enterblock(fs, &bl, 0); + chunk(ls); + lua_assert(bl.breaklist == NO_JUMP); + leaveblock(fs); +} + + +/* +** structure to chain all variables in the left-hand side of an +** assignment +*/ +struct LHS_assign { + struct LHS_assign *prev; + expdesc v; /* variable (global, local, upvalue, or indexed) */ +}; + + +/* +** check whether, in an assignment to a local variable, the local variable +** is needed in a previous assignment (to a table). If so, save original +** local value in a safe place and use this safe copy in the previous +** assignment. +*/ +static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { + FuncState *fs = ls->fs; + int extra = fs->freereg; /* eventual position to save local variable */ + int conflict = 0; + for (; lh; lh = lh->prev) { + if (lh->v.k == VINDEXED) { + if (lh->v.info == v->info) { /* conflict? */ + conflict = 1; + lh->v.info = extra; /* previous assignment will use safe copy */ + } + if (lh->v.aux == v->info) { /* conflict? */ + conflict = 1; + lh->v.aux = extra; /* previous assignment will use safe copy */ + } + } + } + if (conflict) { + luaK_codeABC(fs, OP_MOVE, fs->freereg, v->info, 0); /* make copy */ + luaK_reserveregs(fs, 1); + } +} + + +static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { + expdesc e; + check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, + "syntax error"); + if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ + struct LHS_assign nv; + nv.prev = lh; + primaryexp(ls, &nv.v); + if (nv.v.k == VLOCAL) + check_conflict(ls, lh, &nv.v); + assignment(ls, &nv, nvars+1); + } + else { /* assignment -> `=' explist1 */ + int nexps; + check(ls, '='); + nexps = explist1(ls, &e); + if (nexps != nvars) { + adjust_assign(ls, nvars, nexps, &e); + if (nexps > nvars) + ls->fs->freereg -= nexps - nvars; /* remove extra values */ + } + else { + luaK_setcallreturns(ls->fs, &e, 1); /* close last expression */ + luaK_storevar(ls->fs, &lh->v, &e); + return; /* avoid default */ + } + } + init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ + luaK_storevar(ls->fs, &lh->v, &e); +} + + +static void cond (LexState *ls, expdesc *v) { + /* cond -> exp */ + expr(ls, v); /* read condition */ + if (v->k == VNIL) v->k = VFALSE; /* `falses' are all equal here */ + luaK_goiftrue(ls->fs, v); + luaK_patchtohere(ls->fs, v->t); +} + + +/* +** The while statement optimizes its code by coding the condition +** after its body (and thus avoiding one jump in the loop). +*/ + +/* +** maximum size of expressions for optimizing `while' code +*/ +#ifndef MAXEXPWHILE +#define MAXEXPWHILE 100 +#endif + +/* +** the call `luaK_goiffalse' may grow the size of an expression by +** at most this: +*/ +#define EXTRAEXP 5 + +static void whilestat (LexState *ls, int line) { + /* whilestat -> WHILE cond DO block END */ + Instruction codeexp[MAXEXPWHILE + EXTRAEXP]; + int lineexp; + int i; + int sizeexp; + FuncState *fs = ls->fs; + int whileinit, blockinit, expinit; + expdesc v; + BlockCnt bl; + next(ls); /* skip WHILE */ + whileinit = luaK_jump(fs); /* jump to condition (which will be moved) */ + expinit = luaK_getlabel(fs); + expr(ls, &v); /* parse condition */ + if (v.k == VK) v.k = VTRUE; /* `trues' are all equal here */ + lineexp = ls->linenumber; + luaK_goiffalse(fs, &v); + luaK_concat(fs, &v.f, fs->jpc); + fs->jpc = NO_JUMP; + sizeexp = fs->pc - expinit; /* size of expression code */ + if (sizeexp > MAXEXPWHILE) + luaX_syntaxerror(ls, "`while' condition too complex"); + for (i = 0; i < sizeexp; i++) /* save `exp' code */ + codeexp[i] = fs->f->code[expinit + i]; + fs->pc = expinit; /* remove `exp' code */ + enterblock(fs, &bl, 1); + check(ls, TK_DO); + blockinit = luaK_getlabel(fs); + block(ls); + luaK_patchtohere(fs, whileinit); /* initial jump jumps to here */ + /* move `exp' back to code */ + if (v.t != NO_JUMP) v.t += fs->pc - expinit; + if (v.f != NO_JUMP) v.f += fs->pc - expinit; + for (i=0; i REPEAT block UNTIL cond */ + FuncState *fs = ls->fs; + int repeat_init = luaK_getlabel(fs); + expdesc v; + BlockCnt bl; + enterblock(fs, &bl, 1); + next(ls); + block(ls); + check_match(ls, TK_UNTIL, TK_REPEAT, line); + cond(ls, &v); + luaK_patchlist(fs, v.f, repeat_init); + leaveblock(fs); +} + + +static int exp1 (LexState *ls) { + expdesc e; + int k; + expr(ls, &e); + k = e.k; + luaK_exp2nextreg(ls->fs, &e); + return k; +} + + +static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { + BlockCnt bl; + FuncState *fs = ls->fs; + int prep, endfor; + adjustlocalvars(ls, nvars); /* scope for all variables */ + check(ls, TK_DO); + enterblock(fs, &bl, 1); /* loop block */ + prep = luaK_getlabel(fs); + block(ls); + luaK_patchtohere(fs, prep-1); + endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : + luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars - 3); + luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ + luaK_patchlist(fs, (isnum) ? endfor : luaK_jump(fs), prep); + leaveblock(fs); +} + + +static void fornum (LexState *ls, TString *varname, int line) { + /* fornum -> NAME = exp1,exp1[,exp1] DO body */ + FuncState *fs = ls->fs; + int base = fs->freereg; + new_localvar(ls, varname, 0); + new_localvarstr(ls, "(for limit)", 1); + new_localvarstr(ls, "(for step)", 2); + check(ls, '='); + exp1(ls); /* initial value */ + check(ls, ','); + exp1(ls); /* limit */ + if (testnext(ls, ',')) + exp1(ls); /* optional step */ + else { /* default step = 1 */ + luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); + luaK_reserveregs(fs, 1); + } + luaK_codeABC(fs, OP_SUB, fs->freereg - 3, fs->freereg - 3, fs->freereg - 1); + luaK_jump(fs); + forbody(ls, base, line, 3, 1); +} + + +static void forlist (LexState *ls, TString *indexname) { + /* forlist -> NAME {,NAME} IN explist1 DO body */ + FuncState *fs = ls->fs; + expdesc e; + int nvars = 0; + int line; + int base = fs->freereg; + new_localvarstr(ls, "(for generator)", nvars++); + new_localvarstr(ls, "(for state)", nvars++); + new_localvar(ls, indexname, nvars++); + while (testnext(ls, ',')) + new_localvar(ls, str_checkname(ls), nvars++); + check(ls, TK_IN); + line = ls->linenumber; + adjust_assign(ls, nvars, explist1(ls, &e), &e); + luaK_checkstack(fs, 3); /* extra space to call generator */ + luaK_codeAsBx(fs, OP_TFORPREP, base, NO_JUMP); + forbody(ls, base, line, nvars, 0); +} + + +static void forstat (LexState *ls, int line) { + /* forstat -> fornum | forlist */ + FuncState *fs = ls->fs; + TString *varname; + BlockCnt bl; + enterblock(fs, &bl, 0); /* block to control variable scope */ + next(ls); /* skip `for' */ + varname = str_checkname(ls); /* first variable name */ + switch (ls->t.token) { + case '=': fornum(ls, varname, line); break; + case ',': case TK_IN: forlist(ls, varname); break; + default: luaX_syntaxerror(ls, "`=' or `in' expected"); + } + check_match(ls, TK_END, TK_FOR, line); + leaveblock(fs); +} + + +static void test_then_block (LexState *ls, expdesc *v) { + /* test_then_block -> [IF | ELSEIF] cond THEN block */ + next(ls); /* skip IF or ELSEIF */ + cond(ls, v); + check(ls, TK_THEN); + block(ls); /* `then' part */ +} + + +static void ifstat (LexState *ls, int line) { + /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ + FuncState *fs = ls->fs; + expdesc v; + int escapelist = NO_JUMP; + test_then_block(ls, &v); /* IF cond THEN block */ + while (ls->t.token == TK_ELSEIF) { + luaK_concat(fs, &escapelist, luaK_jump(fs)); + luaK_patchtohere(fs, v.f); + test_then_block(ls, &v); /* ELSEIF cond THEN block */ + } + if (ls->t.token == TK_ELSE) { + luaK_concat(fs, &escapelist, luaK_jump(fs)); + luaK_patchtohere(fs, v.f); + next(ls); /* skip ELSE (after patch, for correct line info) */ + block(ls); /* `else' part */ + } + else + luaK_concat(fs, &escapelist, v.f); + luaK_patchtohere(fs, escapelist); + check_match(ls, TK_END, TK_IF, line); +} + + +static void localfunc (LexState *ls) { + expdesc v, b; + FuncState *fs = ls->fs; + new_localvar(ls, str_checkname(ls), 0); + init_exp(&v, VLOCAL, fs->freereg); + luaK_reserveregs(fs, 1); + adjustlocalvars(ls, 1); + body(ls, &b, 0, ls->linenumber); + luaK_storevar(fs, &v, &b); + /* debug information will only see the variable after this point! */ + getlocvar(fs, fs->nactvar - 1).startpc = fs->pc; +} + + +static void localstat (LexState *ls) { + /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ + int nvars = 0; + int nexps; + expdesc e; + do { + new_localvar(ls, str_checkname(ls), nvars++); + } while (testnext(ls, ',')); + if (testnext(ls, '=')) + nexps = explist1(ls, &e); + else { + e.k = VVOID; + nexps = 0; + } + adjust_assign(ls, nvars, nexps, &e); + adjustlocalvars(ls, nvars); +} + + +static int funcname (LexState *ls, expdesc *v) { + /* funcname -> NAME {field} [`:' NAME] */ + int needself = 0; + singlevar(ls, v, 1); + while (ls->t.token == '.') + luaY_field(ls, v); + if (ls->t.token == ':') { + needself = 1; + luaY_field(ls, v); + } + return needself; +} + + +static void funcstat (LexState *ls, int line) { + /* funcstat -> FUNCTION funcname body */ + int needself; + expdesc v, b; + next(ls); /* skip FUNCTION */ + needself = funcname(ls, &v); + body(ls, &b, needself, line); + luaK_storevar(ls->fs, &v, &b); + luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ +} + + +static void exprstat (LexState *ls) { + /* stat -> func | assignment */ + FuncState *fs = ls->fs; + struct LHS_assign v; + primaryexp(ls, &v.v); + if (v.v.k == VCALL) { /* stat -> func */ + luaK_setcallreturns(fs, &v.v, 0); /* call statement uses no results */ + } + else { /* stat -> assignment */ + v.prev = NULL; + assignment(ls, &v, 1); + } +} + + +static void retstat (LexState *ls) { + /* stat -> RETURN explist */ + FuncState *fs = ls->fs; + expdesc e; + int first, nret; /* registers with returned values */ + next(ls); /* skip RETURN */ + if (block_follow(ls->t.token) || ls->t.token == ';') + first = nret = 0; /* return no values */ + else { + nret = explist1(ls, &e); /* optional return values */ + if (e.k == VCALL) { + luaK_setcallreturns(fs, &e, LUA_MULTRET); + if (nret == 1) { /* tail call? */ + SET_OPCODE(getcode(fs,&e), OP_TAILCALL); + lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); + } + first = fs->nactvar; + nret = LUA_MULTRET; /* return all values */ + } + else { + if (nret == 1) /* only one single value? */ + first = luaK_exp2anyreg(fs, &e); + else { + luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ + first = fs->nactvar; /* return all `active' values */ + lua_assert(nret == fs->freereg - first); + } + } + } + luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); +} + + +static void breakstat (LexState *ls) { + /* stat -> BREAK [NAME] */ + FuncState *fs = ls->fs; + BlockCnt *bl = fs->bl; + int upval = 0; + next(ls); /* skip BREAK */ + while (bl && !bl->isbreakable) { + upval |= bl->upval; + bl = bl->previous; + } + if (!bl) + luaX_syntaxerror(ls, "no loop to break"); + if (upval) + luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); + luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); +} + + +static int statement (LexState *ls) { + int line = ls->linenumber; /* may be needed for error messages */ + switch (ls->t.token) { + case TK_IF: { /* stat -> ifstat */ + ifstat(ls, line); + return 0; + } + case TK_WHILE: { /* stat -> whilestat */ + whilestat(ls, line); + return 0; + } + case TK_DO: { /* stat -> DO block END */ + next(ls); /* skip DO */ + block(ls); + check_match(ls, TK_END, TK_DO, line); + return 0; + } + case TK_FOR: { /* stat -> forstat */ + forstat(ls, line); + return 0; + } + case TK_REPEAT: { /* stat -> repeatstat */ + repeatstat(ls, line); + return 0; + } + case TK_FUNCTION: { + funcstat(ls, line); /* stat -> funcstat */ + return 0; + } + case TK_LOCAL: { /* stat -> localstat */ + next(ls); /* skip LOCAL */ + if (testnext(ls, TK_FUNCTION)) /* local function? */ + localfunc(ls); + else + localstat(ls); + return 0; + } + case TK_RETURN: { /* stat -> retstat */ + retstat(ls); + return 1; /* must be last statement */ + } + case TK_BREAK: { /* stat -> breakstat */ + breakstat(ls); + return 1; /* must be last statement */ + } + default: { + exprstat(ls); + return 0; /* to avoid warnings */ + } + } +} + + +static void chunk (LexState *ls) { + /* chunk -> { stat [`;'] } */ + int islast = 0; + enterlevel(ls); + while (!islast && !block_follow(ls->t.token)) { + islast = statement(ls); + testnext(ls, ';'); + lua_assert(ls->fs->freereg >= ls->fs->nactvar); + ls->fs->freereg = ls->fs->nactvar; /* free registers */ + } + leavelevel(ls); +} + +/* }====================================================================== */ diff --git a/src/lparser.h b/src/lparser.h new file mode 100644 index 0000000..d6aaaf0 --- /dev/null +++ b/src/lparser.h @@ -0,0 +1,71 @@ +/* +** $Id: lparser.h,v 1.47 2003/02/11 10:46:24 roberto Exp $ +** Lua Parser +** See Copyright Notice in lua.h +*/ + +#ifndef lparser_h +#define lparser_h + +#include "llimits.h" +#include "lobject.h" +#include "ltable.h" +#include "lzio.h" + + +/* +** Expression descriptor +*/ + +typedef enum { + VVOID, /* no value */ + VNIL, + VTRUE, + VFALSE, + VK, /* info = index of constant in `k' */ + VLOCAL, /* info = local register */ + VUPVAL, /* info = index of upvalue in `upvalues' */ + VGLOBAL, /* info = index of table; aux = index of global name in `k' */ + VINDEXED, /* info = table register; aux = index register (or `k') */ + VJMP, /* info = instruction pc */ + VRELOCABLE, /* info = instruction pc */ + VNONRELOC, /* info = result register */ + VCALL /* info = result register */ +} expkind; + +typedef struct expdesc { + expkind k; + int info, aux; + int t; /* patch list of `exit when true' */ + int f; /* patch list of `exit when false' */ +} expdesc; + + +struct BlockCnt; /* defined in lparser.c */ + + +/* state needed to generate code for a given function */ +typedef struct FuncState { + Proto *f; /* current function header */ + Table *h; /* table to find (and reuse) elements in `k' */ + struct FuncState *prev; /* enclosing function */ + struct LexState *ls; /* lexical state */ + struct lua_State *L; /* copy of the Lua state */ + struct BlockCnt *bl; /* chain of current blocks */ + int pc; /* next position to code (equivalent to `ncode') */ + int lasttarget; /* `pc' of last `jump target' */ + int jpc; /* list of pending jumps to `pc' */ + int freereg; /* first free register */ + int nk; /* number of elements in `k' */ + int np; /* number of elements in `p' */ + int nlocvars; /* number of elements in `locvars' */ + int nactvar; /* number of active local variables */ + expdesc upvalues[MAXUPVALUES]; /* upvalues */ + int actvar[MAXVARS]; /* declared-variable stack */ +} FuncState; + + +Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff); + + +#endif diff --git a/src/lstate.cpp b/src/lstate.cpp new file mode 100644 index 0000000..b593658 --- /dev/null +++ b/src/lstate.cpp @@ -0,0 +1,220 @@ +/* +** $Id: lstate.c,v 1.123 2003/04/03 13:35:34 roberto Exp $ +** Global State +** See Copyright Notice in lua.h +*/ + + +#include + +#define lstate_c + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "llex.h" +#include "lmem.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + +/* +** macro to allow the inclusion of user information in Lua state +*/ +#ifndef LUA_USERSTATE +#define EXTRASPACE 0 +#else +union UEXTRASPACE {L_Umaxalign a; LUA_USERSTATE b;}; +#define EXTRASPACE (sizeof(union UEXTRASPACE)) +#endif + + + +/* +** you can change this function through the official API: +** call `lua_setpanicf' +*/ +static int default_panic (lua_State *L) { + UNUSED(L); + return 0; +} + + +static lua_State *mallocstate (lua_State *L) { + lu_byte *block = (lu_byte *)luaM_malloc(L, sizeof(lua_State) + EXTRASPACE); + if (block == NULL) return NULL; + else { + block += EXTRASPACE; + return cast(lua_State *, block); + } +} + + +static void freestate (lua_State *L, lua_State *L1) { + luaM_free(L, cast(lu_byte *, L1) - EXTRASPACE, + sizeof(lua_State) + EXTRASPACE); +} + + +static void stack_init (lua_State *L1, lua_State *L) { + L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TObject); + L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; + L1->top = L1->stack; + L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; + L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); + L1->ci = L1->base_ci; + L1->ci->state = CI_C; /* not a Lua function */ + setnilvalue(L1->top++); /* `function' entry for this `ci' */ + L1->base = L1->ci->base = L1->top; + L1->ci->top = L1->top + LUA_MINSTACK; + L1->size_ci = BASIC_CI_SIZE; + L1->end_ci = L1->base_ci + L1->size_ci; +} + + +static void freestack (lua_State *L, lua_State *L1) { + luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo); + luaM_freearray(L, L1->stack, L1->stacksize, TObject); +} + + +/* +** open parts that may cause memory-allocation errors +*/ +static void f_luaopen (lua_State *L, void *ud) { + /* create a new global state */ + global_State *g = luaM_new(NULL, global_State); + UNUSED(ud); + if (g == NULL) luaD_throw(L, LUA_ERRMEM); + L->l_G = g; + g->mainthread = L; + g->GCthreshold = 0; /* mark it as unfinished state */ + g->strt.size = 0; + g->strt.nuse = 0; + g->strt.hash = NULL; + setnilvalue(defaultmeta(L)); + setnilvalue(registry(L)); + luaZ_initbuffer(L, &g->buff); + g->panic = default_panic; + g->rootgc = NULL; + g->rootudata = NULL; + g->tmudata = NULL; + setnilvalue(gkey(g->dummynode)); + setnilvalue(gval(g->dummynode)); + g->dummynode->next = NULL; + g->nblocks = sizeof(lua_State) + sizeof(global_State); + stack_init(L, L); /* init stack */ + /* create default meta table with a dummy table, and then close the loop */ + defaultmeta(L)->tt = LUA_TTABLE; + sethvalue(defaultmeta(L), luaH_new(L, 0, 0)); + hvalue(defaultmeta(L))->metatable = hvalue(defaultmeta(L)); + sethvalue(gt(L), luaH_new(L, 0, 4)); /* table of globals */ + sethvalue(registry(L), luaH_new(L, 4, 4)); /* registry */ + luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ + luaT_init(L); + luaX_init(L); + luaS_fix(luaS_newliteral(L, MEMERRMSG)); + g->GCthreshold = 4*G(L)->nblocks; +} + + +static void preinit_state (lua_State *L) { + L->stack = NULL; + L->stacksize = 0; + L->errorJmp = NULL; + L->hook = NULL; + L->hookmask = L->hookinit = 0; + L->basehookcount = 0; + L->allowhook = 1; + resethookcount(L); + L->openupval = NULL; + L->size_ci = 0; + L->nCcalls = 0; + L->base_ci = L->ci = NULL; + L->errfunc = 0; + setnilvalue(gt(L)); +} + + +static void close_state (lua_State *L) { + luaF_close(L, L->stack); /* close all upvalues for this thread */ + if (G(L)) { /* close global state */ + luaC_sweep(L, 1); /* collect all elements */ + lua_assert(G(L)->rootgc == NULL); + lua_assert(G(L)->rootudata == NULL); + luaS_freeall(L); + luaZ_freebuffer(L, &G(L)->buff); + } + freestack(L, L); + if (G(L)) { + lua_assert(G(L)->nblocks == sizeof(lua_State) + sizeof(global_State)); + luaM_freelem(NULL, G(L)); + } + freestate(NULL, L); +} + + +lua_State *luaE_newthread (lua_State *L) { + lua_State *L1 = mallocstate(L); + luaC_link(L, valtogco(L1), LUA_TTHREAD); + preinit_state(L1); + L1->l_G = L->l_G; + stack_init(L1, L); /* init stack */ + setobj2n(gt(L1), gt(L)); /* share table of globals */ + return L1; +} + + +void luaE_freethread (lua_State *L, lua_State *L1) { + luaF_close(L1, L1->stack); /* close all upvalues for this thread */ + lua_assert(L1->openupval == NULL); + freestack(L, L1); + freestate(L, L1); +} + + +LUA_API lua_State *lua_open (void) { + lua_State *L = mallocstate(NULL); + if (L) { /* allocation OK? */ + L->tt = LUA_TTHREAD; + L->marked = 0; + L->next = L->gclist = NULL; + preinit_state(L); + L->l_G = NULL; + if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { + /* memory allocation error: free partial state */ + close_state(L); + L = NULL; + } + } + lua_userstateopen(L); + return L; +} + + +static void callallgcTM (lua_State *L, void *ud) { + UNUSED(ud); + luaC_callGCTM(L); /* call GC metamethods for all udata */ +} + + +LUA_API void lua_close (lua_State *L) { + lua_lock(L); + L = G(L)->mainthread; /* only the main thread can be closed */ + luaF_close(L, L->stack); /* close all upvalues for this thread */ + luaC_separateudata(L); /* separate udata that have GC metamethods */ + L->errfunc = 0; /* no error function during GC metamethods */ + do { /* repeat until no more errors */ + L->ci = L->base_ci; + L->base = L->top = L->ci->base; + L->nCcalls = 0; + } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0); + lua_assert(G(L)->tmudata == NULL); + close_state(L); +} + diff --git a/src/lstate.h b/src/lstate.h new file mode 100644 index 0000000..5422f1b --- /dev/null +++ b/src/lstate.h @@ -0,0 +1,195 @@ +/* +** $Id: lstate.h,v 1.109 2003/02/27 11:52:30 roberto Exp $ +** Global State +** See Copyright Notice in lua.h +*/ + +#ifndef lstate_h +#define lstate_h + +#include "lua.h" + +#include "lobject.h" +#include "ltm.h" +#include "lzio.h" + + +/* +** macros for thread synchronization inside Lua core machine: +** all accesses to the global state and to global objects are synchronized. +** Because threads can read the stack of other threads +** (when running garbage collection), +** a thread must also synchronize any write-access to its own stack. +** Unsynchronized accesses are allowed only when reading its own stack, +** or when reading immutable fields from global objects +** (such as string values and udata values). +*/ +#ifndef lua_lock +#define lua_lock(L) ((void) 0) +#endif + +#ifndef lua_unlock +#define lua_unlock(L) ((void) 0) +#endif + + +#ifndef lua_userstateopen +#define lua_userstateopen(l) +#endif + + + +struct lua_longjmp; /* defined in ldo.c */ + + +/* default meta table (both for tables and udata) */ +#define defaultmeta(L) (&G(L)->_defaultmeta) + +/* table of globals */ +#define gt(L) (&L->_gt) + +/* registry */ +#define registry(L) (&G(L)->_registry) + + +/* extra stack space to handle TM calls and some other extras */ +#define EXTRA_STACK 5 + + +#define BASIC_CI_SIZE 8 + +#define BASIC_STACK_SIZE (2*LUA_MINSTACK) + + + +typedef struct stringtable { + GCObject **hash; + ls_nstr nuse; /* number of elements */ + int size; +} stringtable; + + +/* +** informations about a call +*/ +typedef struct CallInfo { + StkId base; /* base for called function */ + StkId top; /* top for this function */ + int state; /* bit fields; see below */ + union { + struct { /* for Lua functions */ + const Instruction *savedpc; + const Instruction **pc; /* points to `pc' variable in `luaV_execute' */ + int tailcalls; /* number of tail calls lost under this entry */ + } l; + struct { /* for C functions */ + int dummy; /* just to avoid an empty struct */ + } c; + } u; +} CallInfo; + + +/* +** bit fields for `CallInfo.state' +*/ +#define CI_C (1<<0) /* 1 if function is a C function */ +/* 1 if (Lua) function has an active `luaV_execute' running it */ +#define CI_HASFRAME (1<<1) +/* 1 if Lua function is calling another Lua function (and therefore its + `pc' is being used by the other, and therefore CI_SAVEDPC is 1 too) */ +#define CI_CALLING (1<<2) +#define CI_SAVEDPC (1<<3) /* 1 if `savedpc' is updated */ +#define CI_YIELD (1<<4) /* 1 if thread is suspended */ + + +#define ci_func(ci) (clvalue((ci)->base - 1)) + + +/* +** `global state', shared by all threads of this state +*/ +typedef struct global_State { + stringtable strt; /* hash table for strings */ + GCObject *rootgc; /* list of (almost) all collectable objects */ + GCObject *rootudata; /* (separated) list of all userdata */ + GCObject *tmudata; /* list of userdata to be GC */ + Mbuffer buff; /* temporary buffer for string concatentation */ + lu_mem GCthreshold; + lu_mem nblocks; /* number of `bytes' currently allocated */ + lua_CFunction panic; /* to be called in unprotected errors */ + TObject _registry; + TObject _defaultmeta; + struct lua_State *mainthread; + Node dummynode[1]; /* common node array for all empty tables */ + TString *tmname[TM_N]; /* array with tag-method names */ +} global_State; + + +/* +** `per thread' state +*/ +struct lua_State { + CommonHeader; + StkId top; /* first free slot in the stack */ + StkId base; /* base of current function */ + global_State *l_G; + CallInfo *ci; /* call info for current function */ + StkId stack_last; /* last free slot in the stack */ + StkId stack; /* stack base */ + int stacksize; + CallInfo *end_ci; /* points after end of ci array*/ + CallInfo *base_ci; /* array of CallInfo's */ + unsigned short size_ci; /* size of array `base_ci' */ + unsigned short nCcalls; /* number of nested C calls */ + lu_byte hookmask; + lu_byte allowhook; + lu_byte hookinit; + int basehookcount; + int hookcount; + lua_Hook hook; + TObject _gt; /* table of globals */ + GCObject *openupval; /* list of open upvalues in this stack */ + GCObject *gclist; + struct lua_longjmp *errorJmp; /* current error recover point */ + ptrdiff_t errfunc; /* current error handling function (stack index) */ +}; + + +#define G(L) (L->l_G) + + +/* +** Union of all collectable objects +*/ +union GCObject { + GCheader gch; + union TString ts; + union Udata u; + union Closure cl; + struct Table h; + struct Proto p; + struct UpVal uv; + struct lua_State th; /* thread */ +}; + + +/* macros to convert a GCObject into a specific value */ +#define gcotots(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) +#define gcotou(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) +#define gcotocl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl)) +#define gcotoh(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) +#define gcotop(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) +#define gcotouv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) +#define ngcotouv(o) \ + check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv)) +#define gcototh(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) + +/* macro to convert any value into a GCObject */ +#define valtogco(v) (cast(GCObject *, (v))) + + +lua_State *luaE_newthread (lua_State *L); +void luaE_freethread (lua_State *L, lua_State *L1); + +#endif + diff --git a/src/lstring.cpp b/src/lstring.cpp new file mode 100644 index 0000000..8cbddbd --- /dev/null +++ b/src/lstring.cpp @@ -0,0 +1,102 @@ +/* +** $Id: lstring.c,v 1.78 2002/12/04 17:38:31 roberto Exp $ +** String table (keeps all strings handled by Lua) +** See Copyright Notice in lua.h +*/ + + +#include + +#define lstring_c + +#include "lua.h" + +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" + + + +void luaS_freeall (lua_State *L) { + lua_assert(G(L)->strt.nuse==0); + luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); +} + + +void luaS_resize (lua_State *L, int newsize) { + GCObject **newhash = luaM_newvector(L, newsize, GCObject *); + stringtable *tb = &G(L)->strt; + int i; + for (i=0; isize; i++) { + GCObject *p = tb->hash[i]; + while (p) { /* for each node in the list */ + GCObject *next = p->gch.next; /* save next */ + lu_hash h = gcotots(p)->tsv.hash; + int h1 = lmod(h, newsize); /* new position */ + lua_assert(cast(int, h%newsize) == lmod(h, newsize)); + p->gch.next = newhash[h1]; /* chain it */ + newhash[h1] = p; + p = next; + } + } + luaM_freearray(L, tb->hash, tb->size, TString *); + tb->size = newsize; + tb->hash = newhash; +} + + +static TString *newlstr (lua_State *L, const char *str, size_t l, lu_hash h) { + TString *ts = cast(TString *, luaM_malloc(L, sizestring(l))); + stringtable *tb; + ts->tsv.len = l; + ts->tsv.hash = h; + ts->tsv.marked = 0; + ts->tsv.tt = LUA_TSTRING; + ts->tsv.reserved = 0; + memcpy(ts+1, str, l*sizeof(char)); + ((char *)(ts+1))[l] = '\0'; /* ending 0 */ + tb = &G(L)->strt; + h = lmod(h, tb->size); + ts->tsv.next = tb->hash[h]; /* chain new entry */ + tb->hash[h] = valtogco(ts); + tb->nuse++; + if (tb->nuse > cast(ls_nstr, tb->size) && tb->size <= MAX_INT/2) + luaS_resize(L, tb->size*2); /* too crowded */ + return ts; +} + + +TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { + GCObject *o; + lu_hash h = (lu_hash)l; /* seed */ + size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ + size_t l1; + for (l1=l; l1>=step; l1-=step) /* compute hash */ + h = h ^ ((h<<5)+(h>>2)+(unsigned char)(str[l1-1])); + for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; + o != NULL; + o = o->gch.next) { + TString *ts = gcotots(o); + if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) + return ts; + } + return newlstr(L, str, l, h); /* not found */ +} + + +Udata *luaS_newudata (lua_State *L, size_t s) { + Udata *u; + u = cast(Udata *, luaM_malloc(L, sizeudata(s))); + u->uv.marked = (1<<1); /* is not finalized */ + u->uv.tt = LUA_TUSERDATA; + u->uv.len = s; + u->uv.metatable = hvalue(defaultmeta(L)); + /* chain it on udata list */ + u->uv.next = G(L)->rootudata; + G(L)->rootudata = valtogco(u); + return u; +} + diff --git a/src/lstring.h b/src/lstring.h new file mode 100644 index 0000000..be5a1e3 --- /dev/null +++ b/src/lstring.h @@ -0,0 +1,33 @@ +/* +** $Id: lstring.h,v 1.37 2002/08/16 14:45:55 roberto Exp $ +** String table (keep all strings handled by Lua) +** See Copyright Notice in lua.h +*/ + +#ifndef lstring_h +#define lstring_h + + +#include "lobject.h" +#include "lstate.h" + + + +#define sizestring(l) (cast(lu_mem, sizeof(union TString))+ \ + (cast(lu_mem, l)+1)*sizeof(char)) + +#define sizeudata(l) (cast(lu_mem, sizeof(union Udata))+(l)) + +#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) +#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ + (sizeof(s)/sizeof(char))-1)) + +#define luaS_fix(s) ((s)->tsv.marked |= (1<<4)) + +void luaS_resize (lua_State *L, int newsize); +Udata *luaS_newudata (lua_State *L, size_t s); +void luaS_freeall (lua_State *L); +TString *luaS_newlstr (lua_State *L, const char *str, size_t l); + + +#endif diff --git a/src/ltable.cpp b/src/ltable.cpp new file mode 100644 index 0000000..0c64adb --- /dev/null +++ b/src/ltable.cpp @@ -0,0 +1,509 @@ +/* +** $Id: ltable.c,v 1.132 2003/04/03 13:35:34 roberto Exp $ +** Lua tables (hash) +** See Copyright Notice in lua.h +*/ + + +/* +** Implementation of tables (aka arrays, objects, or hash tables). +** Tables keep its elements in two parts: an array part and a hash part. +** Non-negative integer keys are all candidates to be kept in the array +** part. The actual size of the array is the largest `n' such that at +** least half the slots between 0 and n are in use. +** Hash uses a mix of chained scatter table with Brent's variation. +** A main invariant of these tables is that, if an element is not +** in its main position (i.e. the `original' position that its hash gives +** to it), then the colliding element is in its own main position. +** In other words, there are collisions only when two elements have the +** same main position (i.e. the same hash values for that table size). +** Because of that, the load factor of these tables can be 100% without +** performance penalties. +*/ + +#include + +#define ltable_c + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "ltable.h" + + +/* +** max size of array part is 2^MAXBITS +*/ +#if BITS_INT > 26 +#define MAXBITS 24 +#else +#define MAXBITS (BITS_INT-2) +#endif + +/* check whether `x' < 2^MAXBITS */ +#define toobig(x) ((((x)-1) >> MAXBITS) != 0) + + +/* function to convert a lua_Number to int (with any rounding method) */ +#ifndef lua_number2int +#define lua_number2int(i,n) ((i)=(int)(n)) +#endif + + +#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) + +#define hashstr(t,str) hashpow2(t, (str)->tsv.hash) +#define hashboolean(t,p) hashpow2(t, p) + + +/* +** for some types, it is better to avoid modulus by power of 2, as +** they tend to have many 2 factors. +*/ +#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) + + +#define hashpointer(t,p) hashmod(t, IntPoint(p)) + + +/* +** number of ints inside a lua_Number +*/ +#define numints cast(int, sizeof(lua_Number)/sizeof(int)) + + +/* +** hash for lua_Numbers +*/ +static Node *hashnum (const Table *t, lua_Number n) { + unsigned int a[numints]; + int i; + n += 1; /* normalize number (avoid -0) */ + lua_assert(sizeof(a) <= sizeof(n)); + memcpy(a, &n, sizeof(a)); + for (i = 1; i < numints; i++) a[0] += a[i]; + return hashmod(t, cast(lu_hash, a[0])); +} + + + +/* +** returns the `main' position of an element in a table (that is, the index +** of its hash value) +*/ +Node *luaH_mainposition (const Table *t, const TObject *key) { + switch (ttype(key)) { + case LUA_TNUMBER: + return hashnum(t, nvalue(key)); + case LUA_TSTRING: + return hashstr(t, tsvalue(key)); + case LUA_TBOOLEAN: + return hashboolean(t, bvalue(key)); + case LUA_TLIGHTUSERDATA: + return hashpointer(t, pvalue(key)); + default: + return hashpointer(t, gcvalue(key)); + } +} + + +/* +** returns the index for `key' if `key' is an appropriate key to live in +** the array part of the table, -1 otherwise. +*/ +static int arrayindex (const TObject *key) { + if (ttisnumber(key)) { + int k; + lua_number2int(k, (nvalue(key))); + if (cast(lua_Number, k) == nvalue(key) && k >= 1 && !toobig(k)) + return k; + } + return -1; /* `key' did not match some condition */ +} + + +/* +** returns the index of a `key' for table traversals. First goes all +** elements in the array part, then elements in the hash part. The +** beginning and end of a traversal are signalled by -1. +*/ +static int luaH_index (lua_State *L, Table *t, StkId key) { + int i; + if (ttisnil(key)) return -1; /* first iteration */ + i = arrayindex(key); + if (0 <= i && i <= t->sizearray) { /* is `key' inside array part? */ + return i-1; /* yes; that's the index (corrected to C) */ + } + else { + const TObject *v = luaH_get(t, key); + if (v == &luaO_nilobject) + luaG_runerror(L, "invalid key for `next'"); + i = cast(int, (cast(const lu_byte *, v) - + cast(const lu_byte *, gval(gnode(t, 0)))) / sizeof(Node)); + return i + t->sizearray; /* hash elements are numbered after array ones */ + } +} + + +int luaH_next (lua_State *L, Table *t, StkId key) { + int i = luaH_index(L, t, key); /* find original element */ + for (i++; i < t->sizearray; i++) { /* try first array part */ + if (!ttisnil(&t->array[i])) { /* a non-nil value? */ + setnvalue(key, cast(lua_Number, i+1)); + setobj2s(key+1, &t->array[i]); + return 1; + } + } + for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ + if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ + setobj2s(key, gkey(gnode(t, i))); + setobj2s(key+1, gval(gnode(t, i))); + return 1; + } + } + return 0; /* no more elements */ +} + + +/* +** {============================================================= +** Rehash +** ============================================================== +*/ + + +static void computesizes (int nums[], int ntotal, int *narray, int *nhash) { + int i; + int a = nums[0]; /* number of elements smaller than 2^i */ + int na = a; /* number of elements to go to array part */ + int n = (na == 0) ? -1 : 0; /* (log of) optimal size for array part */ + for (i = 1; a < *narray && *narray >= twoto(i-1); i++) { + if (nums[i] > 0) { + a += nums[i]; + if (a >= twoto(i-1)) { /* more than half elements in use? */ + n = i; + na = a; + } + } + } + lua_assert(na <= *narray && *narray <= ntotal); + *nhash = ntotal - na; + *narray = (n == -1) ? 0 : twoto(n); + lua_assert(na <= *narray && na >= *narray/2); +} + + +static void numuse (const Table *t, int *narray, int *nhash) { + int nums[MAXBITS+1]; + int i, lg; + int totaluse = 0; + /* count elements in array part */ + for (i=0, lg=0; lg<=MAXBITS; lg++) { /* for each slice [2^(lg-1) to 2^lg) */ + int ttlg = twoto(lg); /* 2^lg */ + if (ttlg > t->sizearray) { + ttlg = t->sizearray; + if (i >= ttlg) break; + } + nums[lg] = 0; + for (; iarray[i])) { + nums[lg]++; + totaluse++; + } + } + } + for (; lg<=MAXBITS; lg++) nums[lg] = 0; /* reset other counts */ + *narray = totaluse; /* all previous uses were in array part */ + /* count elements in hash part */ + i = sizenode(t); + while (i--) { + Node *n = &t->node[i]; + if (!ttisnil(gval(n))) { + int k = arrayindex(gkey(n)); + if (k >= 0) { /* is `key' an appropriate array index? */ + nums[luaO_log2(k-1)+1]++; /* count as such */ + (*narray)++; + } + totaluse++; + } + } + computesizes(nums, totaluse, narray, nhash); +} + + +static void setarrayvector (lua_State *L, Table *t, int size) { + int i; + luaM_reallocvector(L, t->array, t->sizearray, size, TObject); + for (i=t->sizearray; iarray[i]); + t->sizearray = size; +} + + +static void setnodevector (lua_State *L, Table *t, int lsize) { + int i; + int size = twoto(lsize); + if (lsize > MAXBITS) + luaG_runerror(L, "table overflow"); + if (lsize == 0) { /* no elements to hash part? */ + t->node = G(L)->dummynode; /* use common `dummynode' */ + lua_assert(ttisnil(gkey(t->node))); /* assert invariants: */ + lua_assert(ttisnil(gval(t->node))); + lua_assert(t->node->next == NULL); /* (`dummynode' must be empty) */ + } + else { + t->node = luaM_newvector(L, size, Node); + for (i=0; inode[i].next = NULL; + setnilvalue(gkey(gnode(t, i))); + setnilvalue(gval(gnode(t, i))); + } + } + t->lsizenode = cast(lu_byte, lsize); + t->firstfree = gnode(t, size-1); /* first free position to be used */ +} + + +static void resize (lua_State *L, Table *t, int nasize, int nhsize) { + int i; + int oldasize = t->sizearray; + int oldhsize = t->lsizenode; + Node *nold; + Node temp[1]; + if (oldhsize) + nold = t->node; /* save old hash ... */ + else { /* old hash is `dummynode' */ + lua_assert(t->node == G(L)->dummynode); + temp[0] = t->node[0]; /* copy it to `temp' */ + nold = temp; + setnilvalue(gkey(G(L)->dummynode)); /* restate invariant */ + setnilvalue(gval(G(L)->dummynode)); + lua_assert(G(L)->dummynode->next == NULL); + } + if (nasize > oldasize) /* array part must grow? */ + setarrayvector(L, t, nasize); + /* create new hash part with appropriate size */ + setnodevector(L, t, nhsize); + /* re-insert elements */ + if (nasize < oldasize) { /* array part must shrink? */ + t->sizearray = nasize; + /* re-insert elements from vanishing slice */ + for (i=nasize; iarray[i])) + setobjt2t(luaH_setnum(L, t, i+1), &t->array[i]); + } + /* shrink array */ + luaM_reallocvector(L, t->array, oldasize, nasize, TObject); + } + /* re-insert elements in hash part */ + for (i = twoto(oldhsize) - 1; i >= 0; i--) { + Node *old = nold+i; + if (!ttisnil(gval(old))) + setobjt2t(luaH_set(L, t, gkey(old)), gval(old)); + } + if (oldhsize) + luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ +} + + +static void rehash (lua_State *L, Table *t) { + int nasize, nhsize; + numuse(t, &nasize, &nhsize); /* compute new sizes for array and hash parts */ + resize(L, t, nasize, luaO_log2(nhsize)+1); +} + + + +/* +** }============================================================= +*/ + + +Table *luaH_new (lua_State *L, int narray, int lnhash) { + Table *t = luaM_new(L, Table); + luaC_link(L, valtogco(t), LUA_TTABLE); + t->metatable = hvalue(defaultmeta(L)); + t->flags = cast(lu_byte, ~0); + /* temporary values (kept only if some malloc fails) */ + t->array = NULL; + t->sizearray = 0; + t->lsizenode = 0; + t->node = NULL; + setarrayvector(L, t, narray); + setnodevector(L, t, lnhash); + return t; +} + + +void luaH_free (lua_State *L, Table *t) { + if (t->lsizenode) + luaM_freearray(L, t->node, sizenode(t), Node); + luaM_freearray(L, t->array, t->sizearray, TObject); + luaM_freelem(L, t); +} + + +#if 0 +/* +** try to remove an element from a hash table; cannot move any element +** (because gc can call `remove' during a table traversal) +*/ +void luaH_remove (Table *t, Node *e) { + Node *mp = luaH_mainposition(t, gkey(e)); + if (e != mp) { /* element not in its main position? */ + while (mp->next != e) mp = mp->next; /* find previous */ + mp->next = e->next; /* remove `e' from its list */ + } + else { + if (e->next != NULL) ?? + } + lua_assert(ttisnil(gval(node))); + setnilvalue(gkey(e)); /* clear node `e' */ + e->next = NULL; +} +#endif + + +/* +** inserts a new key into a hash table; first, check whether key's main +** position is free. If not, check whether colliding node is in its main +** position or not: if it is not, move colliding node to an empty place and +** put new key in its main position; otherwise (colliding node is in its main +** position), new key goes to an empty position. +*/ +static TObject *newkey (lua_State *L, Table *t, const TObject *key) { + TObject *val; + Node *mp = luaH_mainposition(t, key); + if (!ttisnil(gval(mp))) { /* main position is not free? */ + Node *othern = luaH_mainposition(t, gkey(mp)); /* `mp' of colliding node */ + Node *n = t->firstfree; /* get a free place */ + if (othern != mp) { /* is colliding node out of its main position? */ + /* yes; move colliding node into free position */ + while (othern->next != mp) othern = othern->next; /* find previous */ + othern->next = n; /* redo the chain with `n' in place of `mp' */ + *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ + mp->next = NULL; /* now `mp' is free */ + setnilvalue(gval(mp)); + } + else { /* colliding node is in its own main position */ + /* new node will go into free position */ + n->next = mp->next; /* chain new position */ + mp->next = n; + mp = n; + } + } + setobj2t(gkey(mp), key); /* write barrier */ + lua_assert(ttisnil(gval(mp))); + for (;;) { /* correct `firstfree' */ + if (ttisnil(gkey(t->firstfree))) + return gval(mp); /* OK; table still has a free place */ + else if (t->firstfree == t->node) break; /* cannot decrement from here */ + else (t->firstfree)--; + } + /* no more free places; must create one */ + setbvalue(gval(mp), 0); /* avoid new key being removed */ + rehash(L, t); /* grow table */ + val = cast(TObject *, luaH_get(t, key)); /* get new position */ + lua_assert(ttisboolean(val)); + setnilvalue(val); + return val; +} + + +/* +** generic search function +*/ +static const TObject *luaH_getany (Table *t, const TObject *key) { + if (ttisnil(key)) return &luaO_nilobject; + else { + Node *n = luaH_mainposition(t, key); + do { /* check whether `key' is somewhere in the chain */ + if (luaO_rawequalObj(gkey(n), key)) return gval(n); /* that's it */ + else n = n->next; + } while (n); + return &luaO_nilobject; + } +} + + +/* +** search function for integers +*/ +const TObject *luaH_getnum (Table *t, int key) { + if (1 <= key && key <= t->sizearray) + return &t->array[key-1]; + else { + lua_Number nk = cast(lua_Number, key); + Node *n = hashnum(t, nk); + do { /* check whether `key' is somewhere in the chain */ + if (ttisnumber(gkey(n)) && nvalue(gkey(n)) == nk) + return gval(n); /* that's it */ + else n = n->next; + } while (n); + return &luaO_nilobject; + } +} + + +/* +** search function for strings +*/ +const TObject *luaH_getstr (Table *t, TString *key) { + Node *n = hashstr(t, key); + do { /* check whether `key' is somewhere in the chain */ + if (ttisstring(gkey(n)) && tsvalue(gkey(n)) == key) + return gval(n); /* that's it */ + else n = n->next; + } while (n); + return &luaO_nilobject; +} + + +/* +** main search function +*/ +const TObject *luaH_get (Table *t, const TObject *key) { + switch (ttype(key)) { + case LUA_TSTRING: return luaH_getstr(t, tsvalue(key)); + case LUA_TNUMBER: { + int k; + lua_number2int(k, (nvalue(key))); + if (cast(lua_Number, k) == nvalue(key)) /* is an integer index? */ + return luaH_getnum(t, k); /* use specialized version */ + /* else go through */ + } + default: return luaH_getany(t, key); + } +} + + +TObject *luaH_set (lua_State *L, Table *t, const TObject *key) { + const TObject *p = luaH_get(t, key); + t->flags = 0; + if (p != &luaO_nilobject) + return cast(TObject *, p); + else { + if (ttisnil(key)) luaG_runerror(L, "table index is nil"); + else if (ttisnumber(key) && nvalue(key) != nvalue(key)) + luaG_runerror(L, "table index is NaN"); + return newkey(L, t, key); + } +} + + +TObject *luaH_setnum (lua_State *L, Table *t, int key) { + const TObject *p = luaH_getnum(t, key); + if (p != &luaO_nilobject) + return cast(TObject *, p); + else { + TObject k; + setnvalue(&k, cast(lua_Number, key)); + return newkey(L, t, &k); + } +} + diff --git a/src/ltable.h b/src/ltable.h new file mode 100644 index 0000000..3d4d753 --- /dev/null +++ b/src/ltable.h @@ -0,0 +1,31 @@ +/* +** $Id: ltable.h,v 1.44 2003/03/18 12:50:04 roberto Exp $ +** Lua tables (hash) +** See Copyright Notice in lua.h +*/ + +#ifndef ltable_h +#define ltable_h + +#include "lobject.h" + + +#define gnode(t,i) (&(t)->node[i]) +#define gkey(n) (&(n)->i_key) +#define gval(n) (&(n)->i_val) + + +const TObject *luaH_getnum (Table *t, int key); +TObject *luaH_setnum (lua_State *L, Table *t, int key); +const TObject *luaH_getstr (Table *t, TString *key); +const TObject *luaH_get (Table *t, const TObject *key); +TObject *luaH_set (lua_State *L, Table *t, const TObject *key); +Table *luaH_new (lua_State *L, int narray, int lnhash); +void luaH_free (lua_State *L, Table *t); +int luaH_next (lua_State *L, Table *t, StkId key); + +/* exported only for debugging */ +Node *luaH_mainposition (const Table *t, const TObject *key); + + +#endif diff --git a/src/ltests.cpp b/src/ltests.cpp new file mode 100644 index 0000000..649b14e --- /dev/null +++ b/src/ltests.cpp @@ -0,0 +1,852 @@ +/* +** $Id: ltests.c,v 1.158 2003/04/07 14:35:00 roberto Exp $ +** Internal Module for Debugging of the Lua Implementation +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include + +#define ltests_c + +#include "lua.h" + +#include "lapi.h" +#include "lauxlib.h" +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lmem.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "lualib.h" + + + +/* +** The whole module only makes sense with LUA_DEBUG on +*/ +#ifdef LUA_DEBUG + + +#define lua_pushintegral(L,i) lua_pushnumber(L, cast(lua_Number, (i))) + + +static lua_State *lua_state = NULL; + +int islocked = 0; + + +#define func_at(L,k) (L->ci->base+(k) - 1) + + +static void setnameval (lua_State *L, const char *name, int val) { + lua_pushstring(L, name); + lua_pushintegral(L, val); + lua_settable(L, -3); +} + + +/* +** {====================================================================== +** Controlled version for realloc. +** ======================================================================= +*/ + +#define MARK 0x55 /* 01010101 (a nice pattern) */ + +#ifndef EXTERNMEMCHECK +/* full memory check */ +#define HEADER (sizeof(L_Umaxalign)) /* ensures maximum alignment for HEADER */ +#define MARKSIZE 16 /* size of marks after each block */ +#define blockhead(b) (cast(char *, b) - HEADER) +#define setsize(newblock, size) (*cast(size_t *, newblock) = size) +#define checkblocksize(b, size) (size == (*cast(size_t *, blockhead(b)))) +#define fillmem(mem,size) memset(mem, -MARK, size) +#else +/* external memory check: don't do it twice */ +#define HEADER 0 +#define MARKSIZE 0 +#define blockhead(b) (b) +#define setsize(newblock, size) /* empty */ +#define checkblocksize(b,size) (1) +#define fillmem(mem,size) /* empty */ +#endif + +unsigned long memdebug_numblocks = 0; +unsigned long memdebug_total = 0; +unsigned long memdebug_maxmem = 0; +unsigned long memdebug_memlimit = ULONG_MAX; + + +static void *checkblock (void *block, size_t size) { + void *b = blockhead(block); + int i; + for (i=0;i 0); + if (size == 0) { + freeblock(block, oldsize); + return NULL; + } + else if (size > oldsize && memdebug_total+size-oldsize > memdebug_memlimit) + return NULL; /* to test memory allocation errors */ + else { + void *newblock; + int i; + size_t realsize = HEADER+size+MARKSIZE; + size_t commonsize = (oldsize < size) ? oldsize : size; + if (realsize < size) return NULL; /* overflow! */ + newblock = malloc(realsize); /* alloc a new block */ + if (newblock == NULL) return NULL; + if (block) { + memcpy(cast(char *, newblock)+HEADER, block, commonsize); + freeblock(block, oldsize); /* erase (and check) old copy */ + } + /* initialize new part of the block with something `weird' */ + fillmem(cast(char *, newblock)+HEADER+commonsize, size-commonsize); + memdebug_total += size; + if (memdebug_total > memdebug_maxmem) + memdebug_maxmem = memdebug_total; + memdebug_numblocks++; + setsize(newblock, size); + for (i=0;icode[pc]; + OpCode o = GET_OPCODE(i); + const char *name = luaP_opnames[o]; + int line = getline(p, pc); + sprintf(buff, "(%4d) %4d - ", line, pc); + switch (getOpMode(o)) { + case iABC: + sprintf(buff+strlen(buff), "%-12s%4d %4d %4d", name, + GETARG_A(i), GETARG_B(i), GETARG_C(i)); + break; + case iABx: + sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), GETARG_Bx(i)); + break; + case iAsBx: + sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), GETARG_sBx(i)); + break; + } + return buff; +} + + +#if 0 +void luaI_printcode (Proto *pt, int size) { + int pc; + for (pc=0; pcl.p; + lua_newtable(L); + setnameval(L, "maxstack", p->maxstacksize); + setnameval(L, "numparams", p->numparams); + for (pc=0; pcsizecode; pc++) { + char buff[100]; + lua_pushintegral(L, pc+1); + lua_pushstring(L, buildop(p, pc, buff)); + lua_settable(L, -3); + } + return 1; +} + + +static int listk (lua_State *L) { + Proto *p; + int i; + luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), + 1, "Lua function expected"); + p = clvalue(func_at(L, 1))->l.p; + lua_newtable(L); + for (i=0; isizek; i++) { + lua_pushintegral(L, i+1); + luaA_pushobject(L, p->k+i); + lua_settable(L, -3); + } + return 1; +} + + +static int listlocals (lua_State *L) { + Proto *p; + int pc = luaL_checkint(L, 2) - 1; + int i = 0; + const char *name; + luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), + 1, "Lua function expected"); + p = clvalue(func_at(L, 1))->l.p; + while ((name = luaF_getlocalname(p, ++i, pc)) != NULL) + lua_pushstring(L, name); + return i-1; +} + +/* }====================================================== */ + + + + +static int get_limits (lua_State *L) { + lua_newtable(L); + setnameval(L, "BITS_INT", BITS_INT); + setnameval(L, "LFPF", LFIELDS_PER_FLUSH); + setnameval(L, "MAXVARS", MAXVARS); + setnameval(L, "MAXPARAMS", MAXPARAMS); + setnameval(L, "MAXSTACK", MAXSTACK); + setnameval(L, "MAXUPVALUES", MAXUPVALUES); + return 1; +} + + +static int mem_query (lua_State *L) { + if (lua_isnone(L, 1)) { + lua_pushintegral(L, memdebug_total); + lua_pushintegral(L, memdebug_numblocks); + lua_pushintegral(L, memdebug_maxmem); + return 3; + } + else { + memdebug_memlimit = luaL_checkint(L, 1); + return 0; + } +} + + +static int hash_query (lua_State *L) { + if (lua_isnone(L, 2)) { + luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "string expected"); + lua_pushintegral(L, tsvalue(func_at(L, 1))->tsv.hash); + } + else { + TObject *o = func_at(L, 1); + Table *t; + luaL_checktype(L, 2, LUA_TTABLE); + t = hvalue(func_at(L, 2)); + lua_pushintegral(L, luaH_mainposition(t, o) - t->node); + } + return 1; +} + + +static int stacklevel (lua_State *L) { + unsigned long a = 0; + lua_pushintegral(L, (int)(L->top - L->stack)); + lua_pushintegral(L, (int)(L->stack_last - L->stack)); + lua_pushintegral(L, (int)(L->ci - L->base_ci)); + lua_pushintegral(L, (int)(L->end_ci - L->base_ci)); + lua_pushintegral(L, (unsigned long)&a); + return 5; +} + + +static int table_query (lua_State *L) { + const Table *t; + int i = luaL_optint(L, 2, -1); + luaL_checktype(L, 1, LUA_TTABLE); + t = hvalue(func_at(L, 1)); + if (i == -1) { + lua_pushintegral(L, t->sizearray); + lua_pushintegral(L, sizenode(t)); + lua_pushintegral(L, t->firstfree - t->node); + } + else if (i < t->sizearray) { + lua_pushintegral(L, i); + luaA_pushobject(L, &t->array[i]); + lua_pushnil(L); + } + else if ((i -= t->sizearray) < sizenode(t)) { + if (!ttisnil(gval(gnode(t, i))) || + ttisnil(gkey(gnode(t, i))) || + ttisnumber(gkey(gnode(t, i)))) { + luaA_pushobject(L, gkey(gnode(t, i))); + } + else + lua_pushstring(L, ""); + luaA_pushobject(L, gval(gnode(t, i))); + if (t->node[i].next) + lua_pushintegral(L, t->node[i].next - t->node); + else + lua_pushnil(L); + } + return 3; +} + + +static int string_query (lua_State *L) { + stringtable *tb = &G(L)->strt; + int s = luaL_optint(L, 2, 0) - 1; + if (s==-1) { + lua_pushintegral(L ,tb->nuse); + lua_pushintegral(L ,tb->size); + return 2; + } + else if (s < tb->size) { + GCObject *ts; + int n = 0; + for (ts = tb->hash[s]; ts; ts = ts->gch.next) { + setsvalue2s(L->top, gcotots(ts)); + incr_top(L); + n++; + } + return n; + } + return 0; +} + + +static int tref (lua_State *L) { + int level = lua_gettop(L); + int lock = luaL_optint(L, 2, 1); + luaL_checkany(L, 1); + lua_pushvalue(L, 1); + lua_pushintegral(L, lua_ref(L, lock)); + assert(lua_gettop(L) == level+1); /* +1 for result */ + return 1; +} + +static int getref (lua_State *L) { + int level = lua_gettop(L); + lua_getref(L, luaL_checkint(L, 1)); + assert(lua_gettop(L) == level+1); + return 1; +} + +static int unref (lua_State *L) { + int level = lua_gettop(L); + lua_unref(L, luaL_checkint(L, 1)); + assert(lua_gettop(L) == level); + return 0; +} + +static int metatable (lua_State *L) { + luaL_checkany(L, 1); + if (lua_isnone(L, 2)) { + if (lua_getmetatable(L, 1) == 0) + lua_pushnil(L); + } + else { + lua_settop(L, 2); + luaL_checktype(L, 2, LUA_TTABLE); + lua_setmetatable(L, 1); + } + return 1; +} + + +static int upvalue (lua_State *L) { + int n = luaL_checkint(L, 2); + luaL_checktype(L, 1, LUA_TFUNCTION); + if (lua_isnone(L, 3)) { + const char *name = lua_getupvalue(L, 1, n); + if (name == NULL) return 0; + lua_pushstring(L, name); + return 2; + } + else { + const char *name = lua_setupvalue(L, 1, n); + lua_pushstring(L, name); + return 1; + } +} + + +static int newuserdata (lua_State *L) { + size_t size = luaL_checkint(L, 1); + char *p = cast(char *, lua_newuserdata(L, size)); + while (size--) *p++ = '\0'; + return 1; +} + + +static int pushuserdata (lua_State *L) { + lua_pushlightuserdata(L, cast(void *, luaL_checkint(L, 1))); + return 1; +} + + +static int udataval (lua_State *L) { + lua_pushintegral(L, cast(int, lua_touserdata(L, 1))); + return 1; +} + + +static int doonnewstack (lua_State *L) { + lua_State *L1 = lua_newthread(L); + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + int status = luaL_loadbuffer(L1, s, l, s); + if (status == 0) + status = lua_pcall(L1, 0, 0, 0); + lua_pushintegral(L, status); + return 1; +} + + +static int s2d (lua_State *L) { + lua_pushnumber(L, *cast(const double *, luaL_checkstring(L, 1))); + return 1; +} + +static int d2s (lua_State *L) { + double d = luaL_checknumber(L, 1); + lua_pushlstring(L, cast(char *, &d), sizeof(d)); + return 1; +} + + +static int newstate (lua_State *L) { + lua_State *L1 = lua_open(); + if (L1) { + lua_userstateopen(L1); /* init lock */ + lua_pushintegral(L, (unsigned long)L1); + } + else + lua_pushnil(L); + return 1; +} + + +static int loadlib (lua_State *L) { + static const luaL_reg libs[] = { + {"mathlibopen", luaopen_math}, + {"strlibopen", luaopen_string}, + {"iolibopen", luaopen_io}, + {"tablibopen", luaopen_table}, + {"dblibopen", luaopen_debug}, + {"baselibopen", luaopen_base}, + {NULL, NULL} + }; + lua_State *L1 = cast(lua_State *, + cast(unsigned long, luaL_checknumber(L, 1))); + lua_pushvalue(L1, LUA_GLOBALSINDEX); + luaL_openlib(L1, NULL, libs, 0); + return 0; +} + +static int closestate (lua_State *L) { + lua_State *L1 = cast(lua_State *, cast(unsigned long, luaL_checknumber(L, 1))); + lua_close(L1); + lua_unlock(L); /* close cannot unlock that */ + return 0; +} + +static int doremote (lua_State *L) { + lua_State *L1 = cast(lua_State *,cast(unsigned long,luaL_checknumber(L, 1))); + size_t lcode; + const char *code = luaL_checklstring(L, 2, &lcode); + int status; + lua_settop(L1, 0); + status = luaL_loadbuffer(L1, code, lcode, code); + if (status == 0) + status = lua_pcall(L1, 0, LUA_MULTRET, 0); + if (status != 0) { + lua_pushnil(L); + lua_pushintegral(L, status); + lua_pushstring(L, lua_tostring(L1, -1)); + return 3; + } + else { + int i = 0; + while (!lua_isnone(L1, ++i)) + lua_pushstring(L, lua_tostring(L1, i)); + lua_pop(L1, i-1); + return i-1; + } +} + + +static int log2_aux (lua_State *L) { + lua_pushintegral(L, luaO_log2(luaL_checkint(L, 1))); + return 1; +} + +static int int2fb_aux (lua_State *L) { + int b = luaO_int2fb(luaL_checkint(L, 1)); + lua_pushintegral(L, b); + lua_pushintegral(L, fb2int(b)); + return 2; +} + + +static int test_do (lua_State *L) { + const char *p = luaL_checkstring(L, 1); + if (*p == '@') + lua_dofile(L, p+1); + else + lua_dostring(L, p); + return lua_gettop(L); +} + + + +/* +** {====================================================== +** function to test the API with C. It interprets a kind of assembler +** language with calls to the API, so the test can be driven by Lua code +** ======================================================= +*/ + +static const char *const delimits = " \t\n,;"; + +static void skip (const char **pc) { + while (**pc != '\0' && strchr(delimits, **pc)) (*pc)++; +} + +static int getnum_aux (lua_State *L, const char **pc) { + int res = 0; + int sig = 1; + skip(pc); + if (**pc == '.') { + res = cast(int, lua_tonumber(L, -1)); + lua_pop(L, 1); + (*pc)++; + return res; + } + else if (**pc == '-') { + sig = -1; + (*pc)++; + } + while (isdigit(cast(int, **pc))) res = res*10 + (*(*pc)++) - '0'; + return sig*res; +} + +static const char *getname_aux (char *buff, const char **pc) { + int i = 0; + skip(pc); + while (**pc != '\0' && !strchr(delimits, **pc)) + buff[i++] = *(*pc)++; + buff[i] = '\0'; + return buff; +} + + +#define EQ(s1) (strcmp(s1, inst) == 0) + +#define getnum (getnum_aux(L, &pc)) +#define getname (getname_aux(buff, &pc)) + + +static int testC (lua_State *L) { + char buff[30]; + const char *pc = luaL_checkstring(L, 1); + for (;;) { + const char *inst = getname; + if EQ("") return 0; + else if EQ("isnumber") { + lua_pushintegral(L, lua_isnumber(L, getnum)); + } + else if EQ("isstring") { + lua_pushintegral(L, lua_isstring(L, getnum)); + } + else if EQ("istable") { + lua_pushintegral(L, lua_istable(L, getnum)); + } + else if EQ("iscfunction") { + lua_pushintegral(L, lua_iscfunction(L, getnum)); + } + else if EQ("isfunction") { + lua_pushintegral(L, lua_isfunction(L, getnum)); + } + else if EQ("isuserdata") { + lua_pushintegral(L, lua_isuserdata(L, getnum)); + } + else if EQ("isudataval") { + lua_pushintegral(L, lua_islightuserdata(L, getnum)); + } + else if EQ("isnil") { + lua_pushintegral(L, lua_isnil(L, getnum)); + } + else if EQ("isnull") { + lua_pushintegral(L, lua_isnone(L, getnum)); + } + else if EQ("tonumber") { + lua_pushnumber(L, lua_tonumber(L, getnum)); + } + else if EQ("tostring") { + const char *s = lua_tostring(L, getnum); + lua_pushstring(L, s); + } + else if EQ("strlen") { + lua_pushintegral(L, lua_strlen(L, getnum)); + } + else if EQ("tocfunction") { + lua_pushcfunction(L, lua_tocfunction(L, getnum)); + } + else if EQ("return") { + return getnum; + } + else if EQ("gettop") { + lua_pushintegral(L, lua_gettop(L)); + } + else if EQ("settop") { + lua_settop(L, getnum); + } + else if EQ("pop") { + lua_pop(L, getnum); + } + else if EQ("pushnum") { + lua_pushintegral(L, getnum); + } + else if EQ("pushnil") { + lua_pushnil(L); + } + else if EQ("pushbool") { + lua_pushboolean(L, getnum); + } + else if EQ("tobool") { + lua_pushintegral(L, lua_toboolean(L, getnum)); + } + else if EQ("pushvalue") { + lua_pushvalue(L, getnum); + } + else if EQ("pushcclosure") { + lua_pushcclosure(L, testC, getnum); + } + else if EQ("pushupvalues") { + lua_pushupvalues(L); + } + else if EQ("remove") { + lua_remove(L, getnum); + } + else if EQ("insert") { + lua_insert(L, getnum); + } + else if EQ("replace") { + lua_replace(L, getnum); + } + else if EQ("gettable") { + lua_gettable(L, getnum); + } + else if EQ("settable") { + lua_settable(L, getnum); + } + else if EQ("next") { + lua_next(L, -2); + } + else if EQ("concat") { + lua_concat(L, getnum); + } + else if EQ("lessthan") { + int a = getnum; + lua_pushboolean(L, lua_lessthan(L, a, getnum)); + } + else if EQ("equal") { + int a = getnum; + lua_pushboolean(L, lua_equal(L, a, getnum)); + } + else if EQ("rawcall") { + int narg = getnum; + int nres = getnum; + lua_call(L, narg, nres); + } + else if EQ("call") { + int narg = getnum; + int nres = getnum; + lua_pcall(L, narg, nres, 0); + } + else if EQ("loadstring") { + size_t sl; + const char *s = luaL_checklstring(L, getnum, &sl); + luaL_loadbuffer(L, s, sl, s); + } + else if EQ("loadfile") { + luaL_loadfile(L, luaL_checkstring(L, getnum)); + } + else if EQ("setmetatable") { + lua_setmetatable(L, getnum); + } + else if EQ("getmetatable") { + if (lua_getmetatable(L, getnum) == 0) + lua_pushnil(L); + } + else if EQ("type") { + lua_pushstring(L, lua_typename(L, lua_type(L, getnum))); + } + else if EQ("getn") { + int i = getnum; + lua_pushintegral(L, luaL_getn(L, i)); + } + else if EQ("setn") { + int i = getnum; + int n = cast(int, lua_tonumber(L, -1)); + luaL_setn(L, i, n); + lua_pop(L, 1); + } + else luaL_error(L, "unknown instruction %s", buff); + } + return 0; +} + +/* }====================================================== */ + + +/* +** {====================================================== +** tests for yield inside hooks +** ======================================================= +*/ + +static void yieldf (lua_State *L, lua_Debug *ar) { + lua_yield(L, 0); +} + +static int setyhook (lua_State *L) { + if (lua_isnoneornil(L, 1)) + lua_sethook(L, NULL, 0, 0); /* turn off hooks */ + else { + const char *smask = luaL_checkstring(L, 1); + int count = luaL_optint(L, 2, 0); + int mask = 0; + if (strchr(smask, 'l')) mask |= LUA_MASKLINE; + if (count > 0) mask |= LUA_MASKCOUNT; + lua_sethook(L, yieldf, mask, count); + } + return 0; +} + + +static int coresume (lua_State *L) { + int status; + lua_State *co = lua_tothread(L, 1); + luaL_argcheck(L, co, 1, "coroutine expected"); + status = lua_resume(co, 0); + if (status != 0) { + lua_pushboolean(L, 0); + lua_insert(L, -2); + return 2; /* return false + error message */ + } + else { + lua_pushboolean(L, 1); + return 1; + } +} + +/* }====================================================== */ + + + +static const struct luaL_reg tests_funcs[] = { + {"hash", hash_query}, + {"limits", get_limits}, + {"listcode", listcode}, + {"listk", listk}, + {"listlocals", listlocals}, + {"loadlib", loadlib}, + {"stacklevel", stacklevel}, + {"querystr", string_query}, + {"querytab", table_query}, + {"doit", test_do}, + {"testC", testC}, + {"ref", tref}, + {"getref", getref}, + {"unref", unref}, + {"d2s", d2s}, + {"s2d", s2d}, + {"metatable", metatable}, + {"upvalue", upvalue}, + {"newuserdata", newuserdata}, + {"pushuserdata", pushuserdata}, + {"udataval", udataval}, + {"doonnewstack", doonnewstack}, + {"newstate", newstate}, + {"closestate", closestate}, + {"doremote", doremote}, + {"log2", log2_aux}, + {"int2fb", int2fb_aux}, + {"totalmem", mem_query}, + {"resume", coresume}, + {"setyhook", setyhook}, + {NULL, NULL} +}; + + +static void fim (void) { + if (!islocked) + lua_close(lua_state); + lua_assert(memdebug_numblocks == 0); + lua_assert(memdebug_total == 0); +} + + +static int l_panic (lua_State *L) { + UNUSED(L); + fprintf(stderr, "unable to recover; exiting\n"); + return 0; +} + + +int luaB_opentests (lua_State *L) { + lua_atpanic(L, l_panic); + lua_userstateopen(L); /* init lock */ + lua_state = L; /* keep first state to be opened */ + luaL_openlib(L, "T", tests_funcs, 0); + atexit(fim); + return 0; +} + + +#undef main +int main (int argc, char *argv[]) { + char *limit = getenv("MEMLIMIT"); + if (limit) + memdebug_memlimit = strtoul(limit, NULL, 10); + l_main(argc, argv); + return 0; +} + +#endif diff --git a/src/ltm.cpp b/src/ltm.cpp new file mode 100644 index 0000000..1b3e515 --- /dev/null +++ b/src/ltm.cpp @@ -0,0 +1,70 @@ +/* +** $Id: ltm.c,v 1.106 2003/04/03 13:35:34 roberto Exp $ +** Tag methods +** See Copyright Notice in lua.h +*/ + + +#include + +#define ltm_c + +#include "lua.h" + +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + + +const char *const luaT_typenames[] = { + "nil", "boolean", "userdata", "number", + "string", "table", "function", "userdata", "thread" +}; + + +void luaT_init (lua_State *L) { + static const char *const luaT_eventname[] = { /* ORDER TM */ + "__index", "__newindex", + "__gc", "__mode", "__eq", + "__add", "__sub", "__mul", "__div", + "__pow", "__unm", "__lt", "__le", + "__concat", "__call" + }; + int i; + for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); + luaS_fix(G(L)->tmname[i]); /* never collect these names */ + } +} + + +/* +** function to be used with macro "fasttm": optimized for absence of +** tag methods +*/ +const TObject *luaT_gettm (Table *events, TMS event, TString *ename) { + const TObject *tm = luaH_getstr(events, ename); + lua_assert(event <= TM_EQ); + if (ttisnil(tm)) { /* no tag method? */ + events->flags |= cast(lu_byte, 1u<tmname[event]; + switch (ttype(o)) { + case LUA_TTABLE: + return luaH_getstr(hvalue(o)->metatable, ename); + case LUA_TUSERDATA: + return luaH_getstr(uvalue(o)->uv.metatable, ename); + default: + return &luaO_nilobject; + } +} + diff --git a/src/ltm.h b/src/ltm.h new file mode 100644 index 0000000..8eebfd3 --- /dev/null +++ b/src/ltm.h @@ -0,0 +1,51 @@ +/* +** $Id: ltm.h,v 1.41 2002/11/14 11:51:50 roberto Exp $ +** Tag methods +** See Copyright Notice in lua.h +*/ + +#ifndef ltm_h +#define ltm_h + + +#include "lobject.h" + + +/* +* WARNING: if you change the order of this enumeration, +* grep "ORDER TM" +*/ +typedef enum { + TM_INDEX, + TM_NEWINDEX, + TM_GC, + TM_MODE, + TM_EQ, /* last tag method with `fast' access */ + TM_ADD, + TM_SUB, + TM_MUL, + TM_DIV, + TM_POW, + TM_UNM, + TM_LT, + TM_LE, + TM_CONCAT, + TM_CALL, + TM_N /* number of elements in the enum */ +} TMS; + + + +#define gfasttm(g,et,e) \ + (((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) + +#define fasttm(l,et,e) gfasttm(G(l), et, e) + + +const TObject *luaT_gettm (Table *events, TMS event, TString *ename); +const TObject *luaT_gettmbyobj (lua_State *L, const TObject *o, TMS event); +void luaT_init (lua_State *L); + +extern const char *const luaT_typenames[]; + +#endif diff --git a/src/lua/Makefile b/src/lua/Makefile new file mode 100644 index 0000000..aa52832 --- /dev/null +++ b/src/lua/Makefile @@ -0,0 +1,31 @@ +# makefile for Lua interpreter + +LUA= ../.. + +include $(LUA)/config + +EXTRA_DEFS= $(USERCONF) +OBJS= lua.o +SRCS= lua.c + +T= $(BIN)/lua + +all: $T + +$T: $(OBJS) $(LIB)/liblua.a $(LIB)/liblualib.a + $(CC) -o $@ $(MYLDFLAGS) $(OBJS) -L$(LIB) -llua -llualib $(EXTRA_LIBS) $(DLLIB) + +$(LIB)/liblua.a: + cd ..; $(MAKE) + +$(LIB)/liblualib.a: + cd ../lib; $(MAKE) + +clean: + rm -f $(OBJS) $T + +co: + co -q -f -M $(SRCS) + +klean: clean + rm -f $(SRCS) diff --git a/src/lua/README b/src/lua/README new file mode 100644 index 0000000..febd229 --- /dev/null +++ b/src/lua/README @@ -0,0 +1,32 @@ +This is lua, a sample Lua interpreter. +It can be used as a batch interpreter and also interactively. +There are man pages for it in both nroff and html in ../../doc. + +Usage: ./lua [options] [script [args]]. Available options are: + - execute stdin as a file + -e stat execute string `stat' + -i enter interactive mode after executing `script' + -l name load and run library `name' + -v show version information + -- stop handling options + +This interpreter is suitable for using Lua as a standalone language; it loads +all standard libraries. For a minimal interpreter, see ../../etc/min.c. + +If your application simply exports new functions to Lua (which is common), +then you can use this interpreter (almost) unmodified, as follows: + +* First, define a function + void myinit (lua_State *L) + in your own code. In this function, you should do whatever initializations + are needed by your application, typically exporting your functions to Lua. + (Of course, you can use any name instead of "myinit".) + +* Then, #define lua_userinit(L) to be "openstdlibs(L)+myinit(L)". + Here, openstdlibs is a function in lua.c that opens all standard libraries. + If you don't need them, just don't call openstdlibs and open any standard + libraries that you do need in myinit. + +* Finally, remember to link your C code when building lua. + +For other customizations, see ../../etc/config.c. diff --git a/src/lua/lua.c b/src/lua/lua.c new file mode 100644 index 0000000..28c84cb --- /dev/null +++ b/src/lua/lua.c @@ -0,0 +1,438 @@ +/* +** $Id: lua.c,v 1.122 2003/04/03 13:34:42 roberto Exp $ +** Lua stand-alone interpreter +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include + +#define lua_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* +** generic extra include file +*/ +#ifdef LUA_USERCONFIG +#include LUA_USERCONFIG +#endif + + +/* +** definition of `isatty' +*/ +#ifdef _POSIX_C_SOURCE +#include +#define stdin_is_tty() isatty(0) +#else +#define stdin_is_tty() 1 /* assume stdin is a tty */ +#endif + + + +#ifndef PROMPT +#define PROMPT "> " +#endif + + +#ifndef PROMPT2 +#define PROMPT2 ">> " +#endif + +#ifndef PROGNAME +#define PROGNAME "lua" +#endif + +#ifndef lua_userinit +#define lua_userinit(L) openstdlibs(L) +#endif + + +#ifndef LUA_EXTRALIBS +#define LUA_EXTRALIBS /* empty */ +#endif + + +static lua_State *L = NULL; + +static const char *progname = PROGNAME; + + + +static const luaL_reg lualibs[] = { + {"base", luaopen_base}, + {"table", luaopen_table}, + {"io", luaopen_io}, + {"string", luaopen_string}, + {"math", luaopen_math}, + {"debug", luaopen_debug}, + {"loadlib", luaopen_loadlib}, + /* add your libraries here */ + LUA_EXTRALIBS + {NULL, NULL} +}; + + + +static void lstop (lua_State *l, lua_Debug *ar) { + (void)ar; /* unused arg. */ + lua_sethook(l, NULL, 0, 0); + luaL_error(l, "interrupted!"); +} + + +static void laction (int i) { + signal(i, SIG_DFL); /* if another SIGINT happens before lstop, + terminate process (default action) */ + lua_sethook(L, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); +} + + +static void print_usage (void) { + fprintf(stderr, + "usage: %s [options] [script [args]].\n" + "Available options are:\n" + " - execute stdin as a file\n" + " -e stat execute string `stat'\n" + " -i enter interactive mode after executing `script'\n" + " -l name load and run library `name'\n" + " -v show version information\n" + " -- stop handling options\n" , + progname); +} + + +static void l_message (const char *pname, const char *msg) { + if (pname) fprintf(stderr, "%s: ", pname); + fprintf(stderr, "%s\n", msg); +} + + +static int report (int status) { + const char *msg; + if (status) { + msg = lua_tostring(L, -1); + if (msg == NULL) msg = "(error with no message)"; + l_message(progname, msg); + lua_pop(L, 1); + } + return status; +} + + +static int lcall (int narg, int clear) { + int status; + int base = lua_gettop(L) - narg; /* function index */ + lua_pushliteral(L, "_TRACEBACK"); + lua_rawget(L, LUA_GLOBALSINDEX); /* get traceback function */ + lua_insert(L, base); /* put it under chunk and args */ + signal(SIGINT, laction); + status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base); + signal(SIGINT, SIG_DFL); + lua_remove(L, base); /* remove traceback function */ + return status; +} + + +static void print_version (void) { + l_message(NULL, LUA_VERSION " " LUA_COPYRIGHT); +} + + +static void getargs (char *argv[], int n) { + int i; + lua_newtable(L); + for (i=0; argv[i]; i++) { + lua_pushnumber(L, i - n); + lua_pushstring(L, argv[i]); + lua_rawset(L, -3); + } + /* arg.n = maximum index in table `arg' */ + lua_pushliteral(L, "n"); + lua_pushnumber(L, i-n-1); + lua_rawset(L, -3); +} + + +static int docall (int status) { + if (status == 0) status = lcall(0, 1); + return report(status); +} + + +static int file_input (const char *name) { + return docall(luaL_loadfile(L, name)); +} + + +static int dostring (const char *s, const char *name) { + return docall(luaL_loadbuffer(L, s, strlen(s), name)); +} + + +static int load_file (const char *name) { + lua_pushliteral(L, "require"); + lua_rawget(L, LUA_GLOBALSINDEX); + if (!lua_isfunction(L, -1)) { /* no `require' defined? */ + lua_pop(L, 1); + return file_input(name); + } + else { + lua_pushstring(L, name); + return report(lcall(1, 1)); + } +} + + +/* +** this macro can be used by some `history' system to save lines +** read in manual input +*/ +#ifndef lua_saveline +#define lua_saveline(L,line) /* empty */ +#endif + + +/* +** this macro defines a function to show the prompt and reads the +** next line for manual input +*/ +#ifndef lua_readline +#define lua_readline(L,prompt) readline(L,prompt) + +/* maximum length of an input line */ +#ifndef MAXINPUT +#define MAXINPUT 512 +#endif + + +static int readline (lua_State *l, const char *prompt) { + static char buffer[MAXINPUT]; + if (prompt) { + fputs(prompt, stdout); + fflush(stdout); + } + if (fgets(buffer, sizeof(buffer), stdin) == NULL) + return 0; /* read fails */ + else { + lua_pushstring(l, buffer); + return 1; + } +} + +#endif + + +static const char *get_prompt (int firstline) { + const char *p = NULL; + lua_pushstring(L, firstline ? "_PROMPT" : "_PROMPT2"); + lua_rawget(L, LUA_GLOBALSINDEX); + p = lua_tostring(L, -1); + if (p == NULL) p = (firstline ? PROMPT : PROMPT2); + lua_pop(L, 1); /* remove global */ + return p; +} + + +static int incomplete (int status) { + if (status == LUA_ERRSYNTAX && + strstr(lua_tostring(L, -1), "near `'") != NULL) { + lua_pop(L, 1); + return 1; + } + else + return 0; +} + + +static int load_string (void) { + int status; + lua_settop(L, 0); + if (lua_readline(L, get_prompt(1)) == 0) /* no input? */ + return -1; + if (lua_tostring(L, -1)[0] == '=') { /* line starts with `=' ? */ + lua_pushfstring(L, "return %s", lua_tostring(L, -1)+1);/* `=' -> `return' */ + lua_remove(L, -2); /* remove original line */ + } + for (;;) { /* repeat until gets a complete line */ + status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin"); + if (!incomplete(status)) break; /* cannot try to add lines? */ + if (lua_readline(L, get_prompt(0)) == 0) /* no more input? */ + return -1; + lua_concat(L, lua_gettop(L)); /* join lines */ + } + lua_saveline(L, lua_tostring(L, 1)); + lua_remove(L, 1); /* remove line */ + return status; +} + + +static void manual_input (void) { + int status; + const char *oldprogname = progname; + progname = NULL; + while ((status = load_string()) != -1) { + if (status == 0) status = lcall(0, 0); + report(status); + if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */ + lua_getglobal(L, "print"); + lua_insert(L, 1); + if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0) + l_message(progname, lua_pushfstring(L, "error calling `print' (%s)", + lua_tostring(L, -1))); + } + } + lua_settop(L, 0); /* clear stack */ + fputs("\n", stdout); + progname = oldprogname; +} + + +static int handle_argv (char *argv[], int *interactive) { + if (argv[1] == NULL) { /* no more arguments? */ + if (stdin_is_tty()) { + print_version(); + manual_input(); + } + else + file_input(NULL); /* executes stdin as a file */ + } + else { /* other arguments; loop over them */ + int i; + for (i = 1; argv[i] != NULL; i++) { + if (argv[i][0] != '-') break; /* not an option? */ + switch (argv[i][1]) { /* option */ + case '-': { /* `--' */ + if (argv[i][2] != '\0') { + print_usage(); + return 1; + } + i++; /* skip this argument */ + goto endloop; /* stop handling arguments */ + } + case '\0': { + file_input(NULL); /* executes stdin as a file */ + break; + } + case 'i': { + *interactive = 1; + break; + } + case 'v': { + print_version(); + break; + } + case 'e': { + const char *chunk = argv[i] + 2; + if (*chunk == '\0') chunk = argv[++i]; + if (chunk == NULL) { + print_usage(); + return 1; + } + if (dostring(chunk, "=") != 0) + return 1; + break; + } + case 'l': { + const char *filename = argv[i] + 2; + if (*filename == '\0') filename = argv[++i]; + if (filename == NULL) { + print_usage(); + return 1; + } + if (load_file(filename)) + return 1; /* stop if file fails */ + break; + } + case 'c': { + l_message(progname, "option `-c' is deprecated"); + break; + } + case 's': { + l_message(progname, "option `-s' is deprecated"); + break; + } + default: { + print_usage(); + return 1; + } + } + } endloop: + if (argv[i] != NULL) { + const char *filename = argv[i]; + getargs(argv, i); /* collect arguments */ + lua_setglobal(L, "arg"); + return file_input(filename); /* stop scanning arguments */ + } + } + return 0; +} + + +static void openstdlibs (lua_State *l) { + const luaL_reg *lib = lualibs; + for (; lib->func; lib++) { + lib->func(l); /* open library */ + lua_settop(l, 0); /* discard any results */ + } +} + + +static int handle_luainit (void) { + const char *init = getenv("LUA_INIT"); + if (init == NULL) return 0; /* status OK */ + else if (init[0] == '@') + return file_input(init+1); + else + return dostring(init, "=LUA_INIT"); +} + + +struct Smain { + int argc; + char **argv; + int status; +}; + + +static int pmain (lua_State *l) { + struct Smain *s = (struct Smain *)lua_touserdata(l, 1); + int status; + int interactive = 0; + if (s->argv[0] && s->argv[0][0]) progname = s->argv[0]; + L = l; + lua_userinit(l); /* open libraries */ + status = handle_luainit(); + if (status == 0) { + status = handle_argv(s->argv, &interactive); + if (status == 0 && interactive) manual_input(); + } + s->status = status; + return 0; +} + + +int main (int argc, char *argv[]) { + int status; + struct Smain s; + lua_State *l = lua_open(); /* create state */ + if (l == NULL) { + l_message(argv[0], "cannot create state: not enough memory"); + return EXIT_FAILURE; + } + s.argc = argc; + s.argv = argv; + status = lua_cpcall(l, &pmain, &s); + report(status); + lua_close(l); + return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS; +} + diff --git a/src/luac/Makefile b/src/luac/Makefile new file mode 100644 index 0000000..9e772b4 --- /dev/null +++ b/src/luac/Makefile @@ -0,0 +1,35 @@ +# makefile for Lua compiler + +LUA= ../.. + +include $(LUA)/config + +INCS= -I$(INC) -I.. $(EXTRA_INCS) +OBJS= luac.o print.o lopcodes.o +SRCS= luac.c print.c + +T= $(BIN)/luac + +all: $T + +$T: $(OBJS) $(LIB)/liblua.a $(LIB)/liblualib.a + $(CC) -o $@ $(MYLDFLAGS) $(OBJS) -L$(LIB) -llua -llualib $(EXTRA_LIBS) $(DLLIB) + +# print.c needs opcode names from lopcodes.c +lopcodes.o: ../lopcodes.c ../lopcodes.h + $(CC) -o $@ -c $(CFLAGS) -DLUA_OPNAMES ../lopcodes.c + +$(LIB)/liblua.a: + cd ..; $(MAKE) + +$(LIB)/liblualib.a: + cd ../lib; $(MAKE) + +clean: + rm -f $(OBJS) $T + +co: + co -q -f -M $(SRCS) + +klean: clean + rm -f $(SRCS) diff --git a/src/luac/README b/src/luac/README new file mode 100644 index 0000000..ada7bc4 --- /dev/null +++ b/src/luac/README @@ -0,0 +1,18 @@ +This is luac, the Lua compiler. +There are man pages for it in both nroff and html in ../../doc. + +luac translates Lua programs into binary files that can be loaded latter. +The main advantages of pre-compiling chunks are: faster loading, protecting +source code from user changes, and off-line syntax error detection. +luac can also be used to learn about the Lua virtual machine. + +Usage: /l/luac/luac [options] [filenames]. Available options are: + - process stdin + -l list + -o name output to file `name' (default is "luac.out") + -p parse only + -s strip debug information + -v show version information + -- stop handling options + +luac is also an example of how to use the internals of Lua (politely). diff --git a/src/luac/luac.c b/src/luac/luac.c new file mode 100644 index 0000000..1aff0bd --- /dev/null +++ b/src/luac/luac.c @@ -0,0 +1,193 @@ +/* +** $Id: luac.c,v 1.44a 2003/04/07 20:34:20 lhf Exp $ +** Lua compiler (saves bytecodes to files; also list bytecodes) +** See Copyright Notice in lua.h +*/ + +#include +#include +#include + +#include "lua.h" +#include "lauxlib.h" + +#include "lfunc.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstring.h" +#include "lundump.h" + +#ifndef LUA_DEBUG +#define luaB_opentests(L) +#endif + +#ifndef PROGNAME +#define PROGNAME "luac" /* program name */ +#endif + +#define OUTPUT "luac.out" /* default output file */ + +static int listing=0; /* list bytecodes? */ +static int dumping=1; /* dump bytecodes? */ +static int stripping=0; /* strip debug information? */ +static char Output[]={ OUTPUT }; /* default output file name */ +static const char* output=Output; /* output file name */ +static const char* progname=PROGNAME; /* actual program name */ + +static void fatal(const char* message) +{ + fprintf(stderr,"%s: %s\n",progname,message); + exit(EXIT_FAILURE); +} + +static void cannot(const char* name, const char* what, const char* mode) +{ + fprintf(stderr,"%s: cannot %s %sput file ",progname,what,mode); + perror(name); + exit(EXIT_FAILURE); +} + +static void usage(const char* message, const char* arg) +{ + if (message!=NULL) + { + fprintf(stderr,"%s: ",progname); fprintf(stderr,message,arg); fprintf(stderr,"\n"); + } + fprintf(stderr, + "usage: %s [options] [filenames]. Available options are:\n" + " - process stdin\n" + " -l list\n" + " -o name output to file `name' (default is \"" OUTPUT "\")\n" + " -p parse only\n" + " -s strip debug information\n" + " -v show version information\n" + " -- stop handling options\n", + progname); + exit(EXIT_FAILURE); +} + +#define IS(s) (strcmp(argv[i],s)==0) + +static int doargs(int argc, char* argv[]) +{ + int i; + if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0]; + for (i=1; il.p; +} + +static Proto* combine(lua_State* L, int n) +{ + if (n==1) + return toproto(L,-1); + else + { + int i,pc=0; + Proto* f=luaF_newproto(L); + f->source=luaS_newliteral(L,"=(" PROGNAME ")"); + f->maxstacksize=1; + f->p=luaM_newvector(L,n,Proto*); + f->sizep=n; + f->sizecode=2*n+1; + f->code=luaM_newvector(L,f->sizecode,Instruction); + for (i=0; ip[i]=toproto(L,i-n); + f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i); + f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1); + } + f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,0); + return f; + } +} + +static void strip(lua_State* L, Proto* f) +{ + int i,n=f->sizep; + luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); + luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); + luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); + f->lineinfo=NULL; f->sizelineinfo=0; + f->locvars=NULL; f->sizelocvars=0; + f->upvalues=NULL; f->sizeupvalues=0; + f->source=luaS_newliteral(L,"=(none)"); + for (i=0; ip[i]); +} + +static int writer(lua_State* L, const void* p, size_t size, void* u) +{ + UNUSED(L); + return fwrite(p,size,1,(FILE*)u)==1; +} + +int main(int argc, char* argv[]) +{ + lua_State* L; + Proto* f; + int i=doargs(argc,argv); + argc-=i; argv+=i; + if (argc<=0) usage("no input files given",NULL); + L=lua_open(); + luaB_opentests(L); + for (i=0; i + +#if 0 +#define DEBUG_PRINT +#endif + +#ifndef LUA_OPNAMES +#define LUA_OPNAMES +#endif + +#include "ldebug.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lundump.h" + +#define Sizeof(x) ((int)sizeof(x)) +#define VOID(p) ((const void*)(p)) + +static void PrintString(const Proto* f, int n) +{ + const char* s=svalue(&f->k[n]); + putchar('"'); + for (; *s; s++) + { + switch (*s) + { + case '"': printf("\\\""); break; + case '\a': printf("\\a"); break; + case '\b': printf("\\b"); break; + case '\f': printf("\\f"); break; + case '\n': printf("\\n"); break; + case '\r': printf("\\r"); break; + case '\t': printf("\\t"); break; + case '\v': printf("\\v"); break; + default: putchar(*s); break; + } + } + putchar('"'); +} + +static void PrintConstant(const Proto* f, int i) +{ + const TObject* o=&f->k[i]; + switch (ttype(o)) + { + case LUA_TNUMBER: + printf(LUA_NUMBER_FMT,nvalue(o)); + break; + case LUA_TSTRING: + PrintString(f,i); + break; + case LUA_TNIL: + printf("nil"); + break; + default: /* cannot happen */ + printf("? type=%d",ttype(o)); + break; + } +} + +static void PrintCode(const Proto* f) +{ + const Instruction* code=f->code; + int pc,n=f->sizecode; + for (pc=0; pc0) printf("[%d]\t",line); else printf("[-]\t"); + printf("%-9s\t",luaP_opnames[o]); + switch (getOpMode(o)) + { + case iABC: printf("%d %d %d",a,b,c); break; + case iABx: printf("%d %d",a,bc); break; + case iAsBx: printf("%d %d",a,sbc); break; + } + switch (o) + { + case OP_LOADK: + printf("\t; "); PrintConstant(f,bc); + break; + case OP_GETUPVAL: + case OP_SETUPVAL: + printf("\t; %s", (f->sizeupvalues>0) ? getstr(f->upvalues[b]) : "-"); + break; + case OP_GETGLOBAL: + case OP_SETGLOBAL: + printf("\t; %s",svalue(&f->k[bc])); + break; + case OP_GETTABLE: + case OP_SELF: + if (c>=MAXSTACK) { printf("\t; "); PrintConstant(f,c-MAXSTACK); } + break; + case OP_SETTABLE: + case OP_ADD: + case OP_SUB: + case OP_MUL: + case OP_DIV: + case OP_POW: + case OP_EQ: + case OP_LT: + case OP_LE: + if (b>=MAXSTACK || c>=MAXSTACK) + { + printf("\t; "); + if (b>=MAXSTACK) PrintConstant(f,b-MAXSTACK); else printf("-"); + printf(" "); + if (c>=MAXSTACK) PrintConstant(f,c-MAXSTACK); + } + break; + case OP_JMP: + case OP_FORLOOP: + case OP_TFORPREP: + printf("\t; to %d",sbc+pc+2); + break; + case OP_CLOSURE: + printf("\t; %p",VOID(f->p[bc])); + break; + default: + break; + } + printf("\n"); + } +} + +static const char* Source(const Proto* f) +{ + const char* s=getstr(f->source); + if (*s=='@' || *s=='=') + return s+1; + else if (*s==LUA_SIGNATURE[0]) + return "(bstring)"; + else + return "(string)"; +} + +#define IsMain(f) (f->lineDefined==0) + +#define SS(x) (x==1)?"":"s" +#define S(x) x,SS(x) + +static void PrintHeader(const Proto* f) +{ + printf("\n%s <%s:%d> (%d instruction%s, %d bytes at %p)\n", + IsMain(f)?"main":"function",Source(f),f->lineDefined, + S(f->sizecode),f->sizecode*Sizeof(Instruction),VOID(f)); + printf("%d%s param%s, %d stack%s, %d upvalue%s, ", + f->numparams,f->is_vararg?"+":"",SS(f->numparams),S(f->maxstacksize), + S(f->nups)); + printf("%d local%s, %d constant%s, %d function%s\n", + S(f->sizelocvars),S(f->sizek),S(f->sizep)); +} + +#ifdef DEBUG_PRINT +static void PrintConstants(const Proto* f) +{ + int i,n=f->sizek; + printf("constants (%d) for %p:\n",n,VOID(f)); + for (i=0; isizelocvars; + printf("locals (%d) for %p:\n",n,VOID(f)); + for (i=0; ilocvars[i].varname),f->locvars[i].startpc,f->locvars[i].endpc); + } +} + +static void PrintUpvalues(const Proto* f) +{ + int i,n=f->sizeupvalues; + printf("upvalues (%d) for %p:\n",n,VOID(f)); + if (f->upvalues==NULL) return; + for (i=0; iupvalues[i])); + } +} +#endif + +void luaU_print(const Proto* f) +{ + int i,n=f->sizep; + PrintHeader(f); + PrintCode(f); +#ifdef DEBUG_PRINT + PrintConstants(f); + PrintLocals(f); + PrintUpvalues(f); +#endif + for (i=0; ip[i]); +} diff --git a/src/lundump.cpp b/src/lundump.cpp new file mode 100644 index 0000000..151a850 --- /dev/null +++ b/src/lundump.cpp @@ -0,0 +1,286 @@ +/* +** $Id: lundump.c,v 1.49 2003/04/07 20:34:20 lhf Exp $ +** load pre-compiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#define lundump_c + +#include "lua.h" + +#include "ldebug.h" +#include "lfunc.h" +#include "lmem.h" +#include "lopcodes.h" +#include "lstring.h" +#include "lundump.h" +#include "lzio.h" + +#define LoadByte (lu_byte) ezgetc + +typedef struct { + lua_State* L; + ZIO* Z; + Mbuffer* b; + int swap; + const char* name; +} LoadState; + +static void unexpectedEOZ (LoadState* S) +{ + luaG_runerror(S->L,"unexpected end of file in %s",S->name); +} + +static int ezgetc (LoadState* S) +{ + int c=zgetc(S->Z); + if (c==EOZ) unexpectedEOZ(S); + return c; +} + +static void ezread (LoadState* S, void* b, int n) +{ + int r=luaZ_read(S->Z,b,n); + if (r!=0) unexpectedEOZ(S); +} + +static void LoadBlock (LoadState* S, void* b, size_t size) +{ + if (S->swap) + { + char* p=(char*) b+size-1; + int n=size; + while (n--) *p--=(char)ezgetc(S); + } + else + ezread(S,b,size); +} + +static void LoadVector (LoadState* S, void* b, int m, size_t size) +{ + if (S->swap) + { + char* q=(char*) b; + while (m--) + { + char* p=q+size-1; + int n=size; + while (n--) *p--=(char)ezgetc(S); + q+=size; + } + } + else + ezread(S,b,m*size); +} + +static int LoadInt (LoadState* S) +{ + int x; + LoadBlock(S,&x,sizeof(x)); + if (x<0) luaG_runerror(S->L,"bad integer in %s",S->name); + return x; +} + +static size_t LoadSize (LoadState* S) +{ + size_t x; + LoadBlock(S,&x,sizeof(x)); + return x; +} + +static lua_Number LoadNumber (LoadState* S) +{ + lua_Number x; + LoadBlock(S,&x,sizeof(x)); + return x; +} + +static TString* LoadString (LoadState* S) +{ + size_t size=LoadSize(S); + if (size==0) + return NULL; + else + { + char* s=luaZ_openspace(S->L,S->b,size); + ezread(S,s,size); + return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ + } +} + +static void LoadCode (LoadState* S, Proto* f) +{ + int size=LoadInt(S); + f->code=luaM_newvector(S->L,size,Instruction); + f->sizecode=size; + LoadVector(S,f->code,size,sizeof(*f->code)); +} + +static void LoadLocals (LoadState* S, Proto* f) +{ + int i,n; + n=LoadInt(S); + f->locvars=luaM_newvector(S->L,n,LocVar); + f->sizelocvars=n; + for (i=0; ilocvars[i].varname=LoadString(S); + f->locvars[i].startpc=LoadInt(S); + f->locvars[i].endpc=LoadInt(S); + } +} + +static void LoadLines (LoadState* S, Proto* f) +{ + int size=LoadInt(S); + f->lineinfo=luaM_newvector(S->L,size,int); + f->sizelineinfo=size; + LoadVector(S,f->lineinfo,size,sizeof(*f->lineinfo)); +} + +static void LoadUpvalues (LoadState* S, Proto* f) +{ + int i,n; + n=LoadInt(S); + if (n!=0 && n!=f->nups) + luaG_runerror(S->L,"bad nupvalues in %s: read %d; expected %d", + S->name,n,f->nups); + f->upvalues=luaM_newvector(S->L,n,TString*); + f->sizeupvalues=n; + for (i=0; iupvalues[i]=LoadString(S); +} + +static Proto* LoadFunction (LoadState* S, TString* p); + +static void LoadConstants (LoadState* S, Proto* f) +{ + int i,n; + n=LoadInt(S); + f->k=luaM_newvector(S->L,n,TObject); + f->sizek=n; + for (i=0; ik[i]; + int t=LoadByte(S); + switch (t) + { + case LUA_TNUMBER: + setnvalue(o,LoadNumber(S)); + break; + case LUA_TSTRING: + setsvalue2n(o,LoadString(S)); + break; + case LUA_TNIL: + setnilvalue(o); + break; + default: + luaG_runerror(S->L,"bad constant type (%d) in %s",t,S->name); + break; + } + } + n=LoadInt(S); + f->p=luaM_newvector(S->L,n,Proto*); + f->sizep=n; + for (i=0; ip[i]=LoadFunction(S,f->source); +} + +static Proto* LoadFunction (LoadState* S, TString* p) +{ + Proto* f=luaF_newproto(S->L); + f->source=LoadString(S); if (f->source==NULL) f->source=p; + f->lineDefined=LoadInt(S); + f->nups=LoadByte(S); + f->numparams=LoadByte(S); + f->is_vararg=LoadByte(S); + f->maxstacksize=LoadByte(S); + LoadLines(S,f); + LoadLocals(S,f); + LoadUpvalues(S,f); + LoadConstants(S,f); + LoadCode(S,f); +#ifndef TRUST_BINARIES + if (!luaG_checkcode(f)) luaG_runerror(S->L,"bad code in %s",S->name); +#endif + return f; +} + +static void LoadSignature (LoadState* S) +{ + const char* s=LUA_SIGNATURE; + while (*s!=0 && ezgetc(S)==*s) + ++s; + if (*s!=0) luaG_runerror(S->L,"bad signature in %s",S->name); +} + +static void TestSize (LoadState* S, int s, const char* what) +{ + int r=LoadByte(S); + if (r!=s) + luaG_runerror(S->L,"virtual machine mismatch in %s: " + "size of %s is %d but read %d",S->name,what,s,r); +} + +#define TESTSIZE(s,w) TestSize(S,s,w) +#define V(v) v/16,v%16 + +static void LoadHeader (LoadState* S) +{ + int version; + lua_Number x,tx=TEST_NUMBER; + LoadSignature(S); + version=LoadByte(S); + if (version>VERSION) + luaG_runerror(S->L,"%s too new: " + "read version %d.%d; expected at most %d.%d", + S->name,V(version),V(VERSION)); + if (versionL,"%s too old: " + "read version %d.%d; expected at least %d.%d", + S->name,V(version),V(VERSION0)); + S->swap=(luaU_endianness()!=LoadByte(S)); /* need to swap bytes? */ + TESTSIZE(sizeof(int),"int"); + TESTSIZE(sizeof(size_t), "size_t"); + TESTSIZE(sizeof(Instruction), "Instruction"); + TESTSIZE(SIZE_OP, "OP"); + TESTSIZE(SIZE_A, "A"); + TESTSIZE(SIZE_B, "B"); + TESTSIZE(SIZE_C, "C"); + TESTSIZE(sizeof(lua_Number), "number"); + x=LoadNumber(S); + if ((long)x!=(long)tx) /* disregard errors in last bits of fraction */ + luaG_runerror(S->L,"unknown number format in %s",S->name); +} + +static Proto* LoadChunk (LoadState* S) +{ + LoadHeader(S); + return LoadFunction(S,NULL); +} + +/* +** load precompiled chunk +*/ +Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff) +{ + LoadState S; + const char* s=zname(Z); + if (*s=='@' || *s=='=') + S.name=s+1; + else if (*s==LUA_SIGNATURE[0]) + S.name="binary string"; + else + S.name=s; + S.L=L; + S.Z=Z; + S.b=buff; + return LoadChunk(&S); +} + +/* +** find byte order +*/ +int luaU_endianness (void) +{ + int x=1; + return *(char*)&x; +} diff --git a/src/lundump.h b/src/lundump.h new file mode 100644 index 0000000..c7e6959 --- /dev/null +++ b/src/lundump.h @@ -0,0 +1,34 @@ +/* +** $Id: lundump.h,v 1.30 2003/04/07 20:34:20 lhf Exp $ +** load pre-compiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#ifndef lundump_h +#define lundump_h + +#include "lobject.h" +#include "lzio.h" + +/* load one chunk; from lundump.c */ +Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff); + +/* find byte order; from lundump.c */ +int luaU_endianness (void); + +/* dump one chunk; from ldump.c */ +void luaU_dump (lua_State* L, const Proto* Main, lua_Chunkwriter w, void* data); + +/* print one chunk; from print.c */ +void luaU_print (const Proto* Main); + +/* definitions for headers of binary files */ +#define LUA_SIGNATURE "\033Lua" /* binary files start with "Lua" */ +#define VERSION 0x50 /* last format change was in 5.0 */ +#define VERSION0 0x50 /* last major change was in 5.0 */ + +/* a multiple of PI for testing native format */ +/* multiplying by 1E7 gives non-trivial integer values */ +#define TEST_NUMBER ((lua_Number)3.14159265358979323846E7) + +#endif diff --git a/src/lvm.cpp b/src/lvm.cpp new file mode 100644 index 0000000..94e2802 --- /dev/null +++ b/src/lvm.cpp @@ -0,0 +1,781 @@ +/* +** $Id: lvm.c,v 1.284b 2003/04/03 13:35:34 roberto Exp $ +** Lua virtual machine +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +/* needed only when `lua_number2str' uses `sprintf' */ +#include + +#define lvm_c + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" + + + +/* function to convert a lua_Number to a string */ +#ifndef lua_number2str +#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) +#endif + + +/* limit for table tag-method chains (to avoid loops) */ +#define MAXTAGLOOP 100 + + +const TObject *luaV_tonumber (const TObject *obj, TObject *n) { + lua_Number num; + if (ttisnumber(obj)) return obj; + if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) { + setnvalue(n, num); + return n; + } + else + return NULL; +} + + +int luaV_tostring (lua_State *L, StkId obj) { + if (!ttisnumber(obj)) + return 0; + else { + char s[32]; /* 16 digits, sign, point and \0 (+ some extra...) */ + lua_number2str(s, nvalue(obj)); + setsvalue2s(obj, luaS_new(L, s)); + return 1; + } +} + + +static void traceexec (lua_State *L) { + lu_byte mask = L->hookmask; + if (mask & LUA_MASKCOUNT) { /* instruction-hook set? */ + if (L->hookcount == 0) { + resethookcount(L); + luaD_callhook(L, LUA_HOOKCOUNT, -1); + return; + } + } + if (mask & LUA_MASKLINE) { + CallInfo *ci = L->ci; + Proto *p = ci_func(ci)->l.p; + int newline = getline(p, pcRel(*ci->u.l.pc, p)); + if (!L->hookinit) { + luaG_inithooks(L); + return; + } + lua_assert(ci->state & CI_HASFRAME); + if (pcRel(*ci->u.l.pc, p) == 0) /* tracing may be starting now? */ + ci->u.l.savedpc = *ci->u.l.pc; /* initialize `savedpc' */ + /* calls linehook when enters a new line or jumps back (loop) */ + if (*ci->u.l.pc <= ci->u.l.savedpc || + newline != getline(p, pcRel(ci->u.l.savedpc, p))) { + luaD_callhook(L, LUA_HOOKLINE, newline); + ci = L->ci; /* previous call may reallocate `ci' */ + } + ci->u.l.savedpc = *ci->u.l.pc; + } +} + + +static void callTMres (lua_State *L, const TObject *f, + const TObject *p1, const TObject *p2) { + setobj2s(L->top, f); /* push function */ + setobj2s(L->top+1, p1); /* 1st argument */ + setobj2s(L->top+2, p2); /* 2nd argument */ + luaD_checkstack(L, 3); /* cannot check before (could invalidate p1, p2) */ + L->top += 3; + luaD_call(L, L->top - 3, 1); + L->top--; /* result will be in L->top */ +} + + + +static void callTM (lua_State *L, const TObject *f, + const TObject *p1, const TObject *p2, const TObject *p3) { + setobj2s(L->top, f); /* push function */ + setobj2s(L->top+1, p1); /* 1st argument */ + setobj2s(L->top+2, p2); /* 2nd argument */ + setobj2s(L->top+3, p3); /* 3th argument */ + luaD_checkstack(L, 4); /* cannot check before (could invalidate p1...p3) */ + L->top += 4; + luaD_call(L, L->top - 4, 0); +} + + +static const TObject *luaV_index (lua_State *L, const TObject *t, + TObject *key, int loop) { + const TObject *tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); + if (tm == NULL) return &luaO_nilobject; /* no TM */ + if (ttisfunction(tm)) { + callTMres(L, tm, t, key); + return L->top; + } + else return luaV_gettable(L, tm, key, loop); +} + +static const TObject *luaV_getnotable (lua_State *L, const TObject *t, + TObject *key, int loop) { + const TObject *tm = luaT_gettmbyobj(L, t, TM_INDEX); + if (ttisnil(tm)) + luaG_typeerror(L, t, "index"); + if (ttisfunction(tm)) { + callTMres(L, tm, t, key); + return L->top; + } + else return luaV_gettable(L, tm, key, loop); +} + + +/* +** Function to index a table. +** Receives the table at `t' and the key at `key'. +** leaves the result at `res'. +*/ +const TObject *luaV_gettable (lua_State *L, const TObject *t, TObject *key, + int loop) { + if (loop > MAXTAGLOOP) + luaG_runerror(L, "loop in gettable"); + if (ttistable(t)) { /* `t' is a table? */ + Table *h = hvalue(t); + const TObject *v = luaH_get(h, key); /* do a primitive get */ + if (!ttisnil(v)) return v; + else return luaV_index(L, t, key, loop+1); + } + else return luaV_getnotable(L, t, key, loop+1); +} + + +/* +** Receives table at `t', key at `key' and value at `val'. +*/ +void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val) { + const TObject *tm; + int loop = 0; + do { + if (ttistable(t)) { /* `t' is a table? */ + Table *h = hvalue(t); + TObject *oldval = luaH_set(L, h, key); /* do a primitive set */ + if (!ttisnil(oldval) || /* result is no nil? */ + (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ + setobj2t(oldval, val); /* write barrier */ + return; + } + /* else will try the tag method */ + } + else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) + luaG_typeerror(L, t, "index"); + if (ttisfunction(tm)) { + callTM(L, tm, t, key, val); + return; + } + t = tm; /* else repeat with `tm' */ + } while (++loop <= MAXTAGLOOP); + luaG_runerror(L, "loop in settable"); +} + + +static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2, + StkId res, TMS event) { + ptrdiff_t result = savestack(L, res); + const TObject *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ + if (ttisnil(tm)) + tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ + if (!ttisfunction(tm)) return 0; + callTMres(L, tm, p1, p2); + res = restorestack(L, result); /* previous call may change stack */ + setobjs2s(res, L->top); + return 1; +} + + +static const TObject *get_compTM (lua_State *L, Table *mt1, Table *mt2, + TMS event) { + const TObject *tm1 = fasttm(L, mt1, event); + const TObject *tm2; + if (tm1 == NULL) return NULL; /* no metamethod */ + if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ + tm2 = fasttm(L, mt2, event); + if (tm2 == NULL) return NULL; /* no metamethod */ + if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */ + return tm1; + return NULL; +} + + +static int call_orderTM (lua_State *L, const TObject *p1, const TObject *p2, + TMS event) { + const TObject *tm1 = luaT_gettmbyobj(L, p1, event); + const TObject *tm2; + if (ttisnil(tm1)) return -1; /* no metamethod? */ + tm2 = luaT_gettmbyobj(L, p2, event); + if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */ + return -1; + callTMres(L, tm1, p1, p2); + return !l_isfalse(L->top); +} + + +static int luaV_strcmp (const TString *ls, const TString *rs) { + const char *l = getstr(ls); + size_t ll = ls->tsv.len; + const char *r = getstr(rs); + size_t lr = rs->tsv.len; + for (;;) { + int temp = strcoll(l, r); + if (temp != 0) return temp; + else { /* strings are equal up to a `\0' */ + size_t len = strlen(l); /* index of first `\0' in both strings */ + if (len == lr) /* r is finished? */ + return (len == ll) ? 0 : 1; + else if (len == ll) /* l is finished? */ + return -1; /* l is smaller than r (because r is not finished) */ + /* both strings longer than `len'; go on comparing (after the `\0') */ + len++; + l += len; ll -= len; r += len; lr -= len; + } + } +} + + +int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) { + int res; + if (ttype(l) != ttype(r)) + return luaG_ordererror(L, l, r); + else if (ttisnumber(l)) + return nvalue(l) < nvalue(r); + else if (ttisstring(l)) + return luaV_strcmp(tsvalue(l), tsvalue(r)) < 0; + else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) + return res; + return luaG_ordererror(L, l, r); +} + + +static int luaV_lessequal (lua_State *L, const TObject *l, const TObject *r) { + int res; + if (ttype(l) != ttype(r)) + return luaG_ordererror(L, l, r); + else if (ttisnumber(l)) + return nvalue(l) <= nvalue(r); + else if (ttisstring(l)) + return luaV_strcmp(tsvalue(l), tsvalue(r)) <= 0; + else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ + return res; + else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ + return !res; + return luaG_ordererror(L, l, r); +} + + +int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2) { + const TObject *tm; + lua_assert(ttype(t1) == ttype(t2)); + switch (ttype(t1)) { + case LUA_TNIL: return 1; + case LUA_TNUMBER: return nvalue(t1) == nvalue(t2); + case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ + case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); + case LUA_TUSERDATA: { + if (uvalue(t1) == uvalue(t2)) return 1; + tm = get_compTM(L, uvalue(t1)->uv.metatable, uvalue(t2)->uv.metatable, + TM_EQ); + break; /* will try TM */ + } + case LUA_TTABLE: { + if (hvalue(t1) == hvalue(t2)) return 1; + tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); + break; /* will try TM */ + } + default: return gcvalue(t1) == gcvalue(t2); + } + if (tm == NULL) return 0; /* no TM? */ + callTMres(L, tm, t1, t2); /* call TM */ + return !l_isfalse(L->top); +} + + +void luaV_concat (lua_State *L, int total, int last) { + do { + StkId top = L->base + last + 1; + int n = 2; /* number of elements handled in this pass (at least 2) */ + if (!tostring(L, top-2) || !tostring(L, top-1)) { + if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) + luaG_concaterror(L, top-2, top-1); + } else if (tsvalue(top-1)->tsv.len > 0) { /* if len=0, do nothing */ + /* at least two string values; get as many as possible */ + lu_mem tl = cast(lu_mem, tsvalue(top-1)->tsv.len) + + cast(lu_mem, tsvalue(top-2)->tsv.len); + char *buffer; + int i; + while (n < total && tostring(L, top-n-1)) { /* collect total length */ + tl += tsvalue(top-n-1)->tsv.len; + n++; + } + if (tl > MAX_SIZET) luaG_runerror(L, "string size overflow"); + buffer = luaZ_openspace(L, &G(L)->buff, tl); + tl = 0; + for (i=n; i>0; i--) { /* concat all strings */ + size_t l = tsvalue(top-i)->tsv.len; + memcpy(buffer+tl, svalue(top-i), l); + tl += l; + } + setsvalue2s(top-n, luaS_newlstr(L, buffer, tl)); + } + total -= n-1; /* got `n' strings to create 1 new */ + last -= n-1; + } while (total > 1); /* repeat until only 1 result left */ +} + + +static void Arith (lua_State *L, StkId ra, + const TObject *rb, const TObject *rc, TMS op) { + TObject tempb, tempc; + const TObject *b, *c; + if ((b = luaV_tonumber(rb, &tempb)) != NULL && + (c = luaV_tonumber(rc, &tempc)) != NULL) { + switch (op) { + case TM_ADD: setnvalue(ra, nvalue(b) + nvalue(c)); break; + case TM_SUB: setnvalue(ra, nvalue(b) - nvalue(c)); break; + case TM_MUL: setnvalue(ra, nvalue(b) * nvalue(c)); break; + case TM_DIV: setnvalue(ra, nvalue(b) / nvalue(c)); break; + case TM_POW: { + const TObject *f = luaH_getstr(hvalue(gt(L)), G(L)->tmname[TM_POW]); + ptrdiff_t res = savestack(L, ra); + if (!ttisfunction(f)) + luaG_runerror(L, "`__pow' (`^' operator) is not a function"); + callTMres(L, f, b, c); + ra = restorestack(L, res); /* previous call may change stack */ + setobjs2s(ra, L->top); + break; + } + default: lua_assert(0); break; + } + } + else if (!call_binTM(L, rb, rc, ra, op)) + luaG_aritherror(L, rb, rc); +} + + + +/* +** some macros for common tasks in `luaV_execute' +*/ + +#define runtime_check(L, c) { if (!(c)) return 0; } + +#define RA(i) (base+GETARG_A(i)) +/* to be used after possible stack reallocation */ +#define XRA(i) (L->base+GETARG_A(i)) +#define RB(i) (base+GETARG_B(i)) +#define RKB(i) ((GETARG_B(i) < MAXSTACK) ? RB(i) : k+GETARG_B(i)-MAXSTACK) +#define RC(i) (base+GETARG_C(i)) +#define RKC(i) ((GETARG_C(i) < MAXSTACK) ? RC(i) : k+GETARG_C(i)-MAXSTACK) +#define KBx(i) (k+GETARG_Bx(i)) + + +#define dojump(pc, i) ((pc) += (i)) + + +StkId luaV_execute (lua_State *L) { + LClosure *cl; + TObject *k; + const Instruction *pc; + callentry: /* entry point when calling new functions */ + if (L->hookmask & LUA_MASKCALL) { + L->ci->u.l.pc = &pc; + luaD_callhook(L, LUA_HOOKCALL, -1); + } + retentry: /* entry point when returning to old functions */ + L->ci->u.l.pc = &pc; + lua_assert(L->ci->state == CI_SAVEDPC || + L->ci->state == (CI_SAVEDPC | CI_CALLING)); + L->ci->state = CI_HASFRAME; /* activate frame */ + pc = L->ci->u.l.savedpc; + cl = &clvalue(L->base - 1)->l; + k = cl->p->k; + /* main loop of interpreter */ + for (;;) { + const Instruction i = *pc++; + StkId base, ra; + if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && + (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { + traceexec(L); + if (L->ci->state & CI_YIELD) { /* did hook yield? */ + L->ci->u.l.savedpc = pc - 1; + L->ci->state = CI_YIELD | CI_SAVEDPC; + return NULL; + } + } + /* warning!! several calls may realloc the stack and invalidate `ra' */ + base = L->base; + ra = RA(i); + lua_assert(L->ci->state & CI_HASFRAME); + lua_assert(base == L->ci->base); + lua_assert(L->top <= L->stack + L->stacksize && L->top >= base); + lua_assert(L->top == L->ci->top || + GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || + GET_OPCODE(i) == OP_RETURN || GET_OPCODE(i) == OP_SETLISTO); + switch (GET_OPCODE(i)) { + case OP_MOVE: { + setobjs2s(ra, RB(i)); + break; + } + case OP_LOADK: { + setobj2s(ra, KBx(i)); + break; + } + case OP_LOADBOOL: { + setbvalue(ra, GETARG_B(i)); + if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ + break; + } + case OP_LOADNIL: { + TObject *rb = RB(i); + do { + setnilvalue(rb--); + } while (rb >= ra); + break; + } + case OP_GETUPVAL: { + int b = GETARG_B(i); + setobj2s(ra, cl->upvals[b]->v); + break; + } + case OP_GETGLOBAL: { + TObject *rb = KBx(i); + const TObject *v; + lua_assert(ttisstring(rb) && ttistable(&cl->g)); + v = luaH_getstr(hvalue(&cl->g), tsvalue(rb)); + if (!ttisnil(v)) { setobj2s(ra, v); } + else + setobj2s(XRA(i), luaV_index(L, &cl->g, rb, 0)); + break; + } + case OP_GETTABLE: { + StkId rb = RB(i); + TObject *rc = RKC(i); + if (ttistable(rb)) { + const TObject *v = luaH_get(hvalue(rb), rc); + if (!ttisnil(v)) { setobj2s(ra, v); } + else + setobj2s(XRA(i), luaV_index(L, rb, rc, 0)); + } + else + setobj2s(XRA(i), luaV_getnotable(L, rb, rc, 0)); + break; + } + case OP_SETGLOBAL: { + lua_assert(ttisstring(KBx(i)) && ttistable(&cl->g)); + luaV_settable(L, &cl->g, KBx(i), ra); + break; + } + case OP_SETUPVAL: { + int b = GETARG_B(i); + setobj(cl->upvals[b]->v, ra); /* write barrier */ + break; + } + case OP_SETTABLE: { + luaV_settable(L, ra, RKB(i), RKC(i)); + break; + } + case OP_NEWTABLE: { + int b = GETARG_B(i); + b = fb2int(b); + sethvalue(ra, luaH_new(L, b, GETARG_C(i))); + luaC_checkGC(L); + break; + } + case OP_SELF: { + StkId rb = RB(i); + TObject *rc = RKC(i); + runtime_check(L, ttisstring(rc)); + setobjs2s(ra+1, rb); + if (ttistable(rb)) { + const TObject *v = luaH_getstr(hvalue(rb), tsvalue(rc)); + if (!ttisnil(v)) { setobj2s(ra, v); } + else + setobj2s(XRA(i), luaV_index(L, rb, rc, 0)); + } + else + setobj2s(XRA(i), luaV_getnotable(L, rb, rc, 0)); + break; + } + case OP_ADD: { + TObject *rb = RKB(i); + TObject *rc = RKC(i); + if (ttisnumber(rb) && ttisnumber(rc)) { + setnvalue(ra, nvalue(rb) + nvalue(rc)); + } + else + Arith(L, ra, rb, rc, TM_ADD); + break; + } + case OP_SUB: { + TObject *rb = RKB(i); + TObject *rc = RKC(i); + if (ttisnumber(rb) && ttisnumber(rc)) { + setnvalue(ra, nvalue(rb) - nvalue(rc)); + } + else + Arith(L, ra, rb, rc, TM_SUB); + break; + } + case OP_MUL: { + TObject *rb = RKB(i); + TObject *rc = RKC(i); + if (ttisnumber(rb) && ttisnumber(rc)) { + setnvalue(ra, nvalue(rb) * nvalue(rc)); + } + else + Arith(L, ra, rb, rc, TM_MUL); + break; + } + case OP_DIV: { + TObject *rb = RKB(i); + TObject *rc = RKC(i); + if (ttisnumber(rb) && ttisnumber(rc)) { + setnvalue(ra, nvalue(rb) / nvalue(rc)); + } + else + Arith(L, ra, rb, rc, TM_DIV); + break; + } + case OP_POW: { + Arith(L, ra, RKB(i), RKC(i), TM_POW); + break; + } + case OP_UNM: { + const TObject *rb = RB(i); + TObject temp; + if (tonumber(rb, &temp)) { + setnvalue(ra, -nvalue(rb)); + } + else { + setnilvalue(&temp); + if (!call_binTM(L, RB(i), &temp, ra, TM_UNM)) + luaG_aritherror(L, RB(i), &temp); + } + break; + } + case OP_NOT: { + int res = l_isfalse(RB(i)); /* next assignment may change this value */ + setbvalue(ra, res); + break; + } + case OP_CONCAT: { + int b = GETARG_B(i); + int c = GETARG_C(i); + luaV_concat(L, c-b+1, c); /* may change `base' (and `ra') */ + base = L->base; + setobjs2s(RA(i), base+b); + luaC_checkGC(L); + break; + } + case OP_JMP: { + dojump(pc, GETARG_sBx(i)); + break; + } + case OP_EQ: { + if (equalobj(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; + else dojump(pc, GETARG_sBx(*pc) + 1); + break; + } + case OP_LT: { + if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; + else dojump(pc, GETARG_sBx(*pc) + 1); + break; + } + case OP_LE: { + if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; + else dojump(pc, GETARG_sBx(*pc) + 1); + break; + } + case OP_TEST: { + TObject *rb = RB(i); + if (l_isfalse(rb) == GETARG_C(i)) pc++; + else { + setobjs2s(ra, rb); + dojump(pc, GETARG_sBx(*pc) + 1); + } + break; + } + case OP_CALL: + case OP_TAILCALL: { + StkId firstResult; + int b = GETARG_B(i); + int nresults; + if (b != 0) L->top = ra+b; /* else previous instruction set top */ + nresults = GETARG_C(i) - 1; + firstResult = luaD_precall(L, ra); + if (firstResult) { + if (firstResult > L->top) { /* yield? */ + lua_assert(L->ci->state == (CI_C | CI_YIELD)); + (L->ci - 1)->u.l.savedpc = pc; + (L->ci - 1)->state = CI_SAVEDPC; + return NULL; + } + /* it was a C function (`precall' called it); adjust results */ + luaD_poscall(L, nresults, firstResult); + if (nresults >= 0) L->top = L->ci->top; + } + else { /* it is a Lua function */ + if (GET_OPCODE(i) == OP_CALL) { /* regular call? */ + (L->ci-1)->u.l.savedpc = pc; /* save `pc' to return later */ + (L->ci-1)->state = (CI_SAVEDPC | CI_CALLING); + } + else { /* tail call: put new frame in place of previous one */ + int aux; + base = (L->ci - 1)->base; /* `luaD_precall' may change the stack */ + ra = RA(i); + if (L->openupval) luaF_close(L, base); + for (aux = 0; ra+aux < L->top; aux++) /* move frame down */ + setobjs2s(base+aux-1, ra+aux); + (L->ci - 1)->top = L->top = base+aux; /* correct top */ + lua_assert(L->ci->state & CI_SAVEDPC); + (L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc; + (L->ci - 1)->u.l.tailcalls++; /* one more call lost */ + (L->ci - 1)->state = CI_SAVEDPC; + L->ci--; /* remove new frame */ + L->base = L->ci->base; + } + goto callentry; + } + break; + } + case OP_RETURN: { + CallInfo *ci = L->ci - 1; /* previous function frame */ + int b = GETARG_B(i); + if (b != 0) L->top = ra+b-1; + lua_assert(L->ci->state & CI_HASFRAME); + if (L->openupval) luaF_close(L, base); + L->ci->state = CI_SAVEDPC; /* deactivate current function */ + L->ci->u.l.savedpc = pc; + /* previous function was running `here'? */ + if (!(ci->state & CI_CALLING)) { + lua_assert((ci->state & CI_C) || ci->u.l.pc != &pc); + return ra; /* no: return */ + } + else { /* yes: continue its execution */ + int nresults; + lua_assert(ttisfunction(ci->base - 1) && (ci->state & CI_SAVEDPC)); + lua_assert(GET_OPCODE(*(ci->u.l.savedpc - 1)) == OP_CALL); + nresults = GETARG_C(*(ci->u.l.savedpc - 1)) - 1; + luaD_poscall(L, nresults, ra); + if (nresults >= 0) L->top = L->ci->top; + goto retentry; + } + } + case OP_FORLOOP: { + lua_Number step, idx, limit; + const TObject *plimit = ra+1; + const TObject *pstep = ra+2; + if (!ttisnumber(ra)) + luaG_runerror(L, "`for' initial value must be a number"); + if (!tonumber(plimit, ra+1)) + luaG_runerror(L, "`for' limit must be a number"); + if (!tonumber(pstep, ra+2)) + luaG_runerror(L, "`for' step must be a number"); + step = nvalue(pstep); + idx = nvalue(ra) + step; /* increment index */ + limit = nvalue(plimit); + if (step > 0 ? idx <= limit : idx >= limit) { + dojump(pc, GETARG_sBx(i)); /* jump back */ + chgnvalue(ra, idx); /* update index */ + } + break; + } + case OP_TFORLOOP: { + int nvar = GETARG_C(i) + 1; + StkId cb = ra + nvar + 2; /* call base */ + setobjs2s(cb, ra); + setobjs2s(cb+1, ra+1); + setobjs2s(cb+2, ra+2); + L->top = cb+3; /* func. + 2 args (state and index) */ + luaD_call(L, cb, nvar); + L->top = L->ci->top; + ra = XRA(i) + 2; /* final position of first result */ + cb = ra + nvar; + do { /* move results to proper positions */ + nvar--; + setobjs2s(ra+nvar, cb+nvar); + } while (nvar > 0); + if (ttisnil(ra)) /* break loop? */ + pc++; /* skip jump (break loop) */ + else + dojump(pc, GETARG_sBx(*pc) + 1); /* jump back */ + break; + } + case OP_TFORPREP: { /* for compatibility only */ + if (ttistable(ra)) { + setobjs2s(ra+1, ra); + setobj2s(ra, luaH_getstr(hvalue(gt(L)), luaS_new(L, "next"))); + } + dojump(pc, GETARG_sBx(i)); + break; + } + case OP_SETLIST: + case OP_SETLISTO: { + int bc; + int n; + Table *h; + runtime_check(L, ttistable(ra)); + h = hvalue(ra); + bc = GETARG_Bx(i); + if (GET_OPCODE(i) == OP_SETLIST) + n = (bc&(LFIELDS_PER_FLUSH-1)) + 1; + else { + n = L->top - ra - 1; + L->top = L->ci->top; + } + bc &= ~(LFIELDS_PER_FLUSH-1); /* bc = bc - bc%FPF */ + for (; n > 0; n--) + setobj2t(luaH_setnum(L, h, bc+n), ra+n); /* write barrier */ + break; + } + case OP_CLOSE: { + luaF_close(L, ra); + break; + } + case OP_CLOSURE: { + Proto *p; + Closure *ncl; + int nup, j; + p = cl->p->p[GETARG_Bx(i)]; + nup = p->nups; + ncl = luaF_newLclosure(L, nup, &cl->g); + ncl->l.p = p; + for (j=0; jl.upvals[j] = cl->upvals[GETARG_B(*pc)]; + else { + lua_assert(GET_OPCODE(*pc) == OP_MOVE); + ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); + } + } + setclvalue(ra, ncl); + luaC_checkGC(L); + break; + } + } + } +} + + diff --git a/src/lvm.h b/src/lvm.h new file mode 100644 index 0000000..19cce20 --- /dev/null +++ b/src/lvm.h @@ -0,0 +1,35 @@ +/* +** $Id: lvm.h,v 1.47 2002/11/14 16:16:21 roberto Exp $ +** Lua virtual machine +** See Copyright Notice in lua.h +*/ + +#ifndef lvm_h +#define lvm_h + + +#include "ldo.h" +#include "lobject.h" +#include "ltm.h" + + +#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) + +#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ + (((o) = luaV_tonumber(o,n)) != NULL)) + +#define equalobj(L,o1,o2) \ + (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) + + +int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r); +int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2); +const TObject *luaV_tonumber (const TObject *obj, TObject *n); +int luaV_tostring (lua_State *L, StkId obj); +const TObject *luaV_gettable (lua_State *L, const TObject *t, TObject *key, + int loop); +void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val); +StkId luaV_execute (lua_State *L); +void luaV_concat (lua_State *L, int total, int last); + +#endif diff --git a/src/lzio.cpp b/src/lzio.cpp new file mode 100644 index 0000000..3aeca1c --- /dev/null +++ b/src/lzio.cpp @@ -0,0 +1,81 @@ +/* +** $Id: lzio.c,v 1.24 2003/03/20 16:00:56 roberto Exp $ +** a generic input stream interface +** See Copyright Notice in lua.h +*/ + + +#include + +#define lzio_c + +#include "lua.h" + +#include "llimits.h" +#include "lmem.h" +#include "lzio.h" + + +int luaZ_fill (ZIO *z) { + size_t size; + const char *buff = z->reader(NULL, z->data, &size); + if (buff == NULL || size == 0) return EOZ; + z->n = size - 1; + z->p = buff; + return char2int(*(z->p++)); +} + + +int luaZ_lookahead (ZIO *z) { + if (z->n == 0) { + int c = luaZ_fill(z); + if (c == EOZ) return c; + z->n++; + z->p--; + } + return char2int(*z->p); +} + + +void luaZ_init (ZIO *z, lua_Chunkreader reader, void *data, const char *name) { + z->reader = reader; + z->data = data; + z->name = name; + z->n = 0; + z->p = NULL; +} + + +/* --------------------------------------------------------------- read --- */ +size_t luaZ_read (ZIO *z, void *b, size_t n) { + while (n) { + size_t m; + if (z->n == 0) { + if (luaZ_fill(z) == EOZ) + return n; /* return number of missing bytes */ + else { + ++z->n; /* filbuf removed first byte; put back it */ + --z->p; + } + } + m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ + memcpy(b, z->p, m); + z->n -= m; + z->p += m; + b = (char *)b + m; + n -= m; + } + return 0; +} + +/* ------------------------------------------------------------------------ */ +char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) { + if (n > buff->buffsize) { + if (n < LUA_MINBUFFER) n = LUA_MINBUFFER; + luaM_reallocvector(L, buff->buffer, buff->buffsize, n, char); + buff->buffsize = n; + } + return buff->buffer; +} + + diff --git a/src/lzio.h b/src/lzio.h new file mode 100644 index 0000000..5e73615 --- /dev/null +++ b/src/lzio.h @@ -0,0 +1,64 @@ +/* +** $Id: lzio.h,v 1.15 2003/03/20 16:00:56 roberto Exp $ +** Buffered streams +** See Copyright Notice in lua.h +*/ + + +#ifndef lzio_h +#define lzio_h + +#include "lua.h" + + +#define EOZ (-1) /* end of stream */ + +typedef struct Zio ZIO; + + +#define char2int(c) cast(int, cast(unsigned char, (c))) + +#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z)) + +#define zname(z) ((z)->name) + +void luaZ_init (ZIO *z, lua_Chunkreader reader, void *data, const char *name); +size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ +int luaZ_lookahead (ZIO *z); + + + +typedef struct Mbuffer { + char *buffer; + size_t buffsize; +} Mbuffer; + + +char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); + +#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) + +#define luaZ_sizebuffer(buff) ((buff)->buffsize) +#define luaZ_buffer(buff) ((buff)->buffer) + +#define luaZ_resizebuffer(L, buff, size) \ + (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \ + (buff)->buffsize = size) + +#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) + + +/* --------- Private Part ------------------ */ + +struct Zio { + size_t n; /* bytes still unread */ + const char *p; /* current position in buffer */ + lua_Chunkreader reader; + void* data; /* additional data */ + const char *name; +}; + + +int luaZ_fill (ZIO *z); + +#endif diff --git a/test/README b/test/README new file mode 100644 index 0000000..2a6601c --- /dev/null +++ b/test/README @@ -0,0 +1,27 @@ +These are simple tests for Lua. Some of them contain useful code. +They are meant to be run to make sure Lua is built correctly and also +to be read, to see how Lua programs look. + +Here is a one-line summary of each program: + + bisect.lua bisection method for solving non-linear equations + cf.lua temperature conversion table (celsius to farenheit) + echo.lua echo command line arguments + env.lua environment variables as automatic global variables + factorial.lua factorial without recursion + fib.lua fibonacci function with cache + fibfor.lua fibonacci numbers with coroutines and generators + globals.lua report global variable usage + hello.lua the first program in every language + life.lua Conway's Game of Life + luac.lua bare-bones luac + printf.lua an implementation of printf + readonly.lua make global variables readonly + sieve.lua the sieve of of Eratosthenes programmed with coroutines + sort.lua two implementations of a sort function + table.lua make table, grouping all data for the same item + trace-calls.lua trace calls + trace-globals.lua trace assigments to global variables + undefined.lua catch "undefined" global variables + xd.lua hex dump + diff --git a/test/bisect.lua b/test/bisect.lua new file mode 100644 index 0000000..f91e69b --- /dev/null +++ b/test/bisect.lua @@ -0,0 +1,27 @@ +-- bisection method for solving non-linear equations + +delta=1e-6 -- tolerance + +function bisect(f,a,b,fa,fb) + local c=(a+b)/2 + io.write(n," c=",c," a=",a," b=",b,"\n") + if c==a or c==b or math.abs(a-b) posted to lua-l +-- modified to use ANSI terminal escape sequences +-- modified to use for instead of while + +local write=io.write + +ALIVE="¥" DEAD="þ" +ALIVE="O" DEAD="-" + +function delay() -- NOTE: SYSTEM-DEPENDENT, adjust as necessary + for i=1,10000 do end + -- local i=os.clock()+1 while(os.clock() 0 do + local xm1,x,xp1,xi=self.w-1,self.w,1,self.w + while xi > 0 do + local sum = self[ym1][xm1] + self[ym1][x] + self[ym1][xp1] + + self[y][xm1] + self[y][xp1] + + self[yp1][xm1] + self[yp1][x] + self[yp1][xp1] + next[y][x] = ((sum==2) and self[y][x]) or ((sum==3) and 1) or 0 + xm1,x,xp1,xi = x,xp1,xp1+1,xi-1 + end + ym1,y,yp1,yi = y,yp1,yp1+1,yi-1 + end +end + +-- output the array to screen +function _CELLS:draw() + local out="" -- accumulate to reduce flicker + for y=1,self.h do + for x=1,self.w do + out=out..(((self[y][x]>0) and ALIVE) or DEAD) + end + out=out.."\n" + end + write(out) +end + +-- constructor +function CELLS(w,h) + local c = ARRAY2D(w,h) + c.spawn = _CELLS.spawn + c.evolve = _CELLS.evolve + c.draw = _CELLS.draw + return c +end + +-- +-- shapes suitable for use with spawn() above +-- +HEART = { 1,0,1,1,0,1,1,1,1; w=3,h=3 } +GLIDER = { 0,0,1,1,0,1,0,1,1; w=3,h=3 } +EXPLODE = { 0,1,0,1,1,1,1,0,1,0,1,0; w=3,h=4 } +FISH = { 0,1,1,1,1,1,0,0,0,1,0,0,0,0,1,1,0,0,1,0; w=5,h=4 } +BUTTERFLY = { 1,0,0,0,1,0,1,1,1,0,1,0,0,0,1,1,0,1,0,1,1,0,0,0,1; w=5,h=5 } + +-- the main routine +function LIFE(w,h) + -- create two arrays + local thisgen = CELLS(w,h) + local nextgen = CELLS(w,h) + + -- create some life + -- about 1000 generations of fun, then a glider steady-state + thisgen:spawn(GLIDER,5,4) + thisgen:spawn(EXPLODE,25,10) + thisgen:spawn(FISH,4,12) + + -- run until break + local gen=1 + write("\027[2J") -- ANSI clear screen + while 1 do + thisgen:evolve(nextgen) + thisgen,nextgen = nextgen,thisgen + write("\027[H") -- ANSI home cursor + thisgen:draw() + write("Life - generation ",gen,"\n") + gen=gen+1 + if gen>2000 then break end + --delay() -- no delay + end +end + +LIFE(40,20) diff --git a/test/luac.lua b/test/luac.lua new file mode 100644 index 0000000..b009ae9 --- /dev/null +++ b/test/luac.lua @@ -0,0 +1,7 @@ +-- bare-bones luac in Lua +-- usage: lua luac.lua file.lua + +assert(arg[1]~=nil and arg[2]==nil,"usage: lua luac.lua file.lua") +f=assert(io.open("luac.out","wb")) +f:write(string.dump(assert(loadfile(arg[1])))) +io.close(f) diff --git a/test/printf.lua b/test/printf.lua new file mode 100644 index 0000000..66dfda6 --- /dev/null +++ b/test/printf.lua @@ -0,0 +1,7 @@ +-- an implementation of printf + +function printf(...) + io.write(string.format(unpack(arg))) +end + +printf("Hello %s from %s on %s\n",os.getenv"USER" or "there",_VERSION,os.date()) diff --git a/test/readonly.lua b/test/readonly.lua new file mode 100644 index 0000000..85c0b4e --- /dev/null +++ b/test/readonly.lua @@ -0,0 +1,12 @@ +-- make global variables readonly + +local f=function (t,i) error("cannot redefine global variable `"..i.."'",2) end +local g={} +local G=getfenv() +setmetatable(g,{__index=G,__newindex=f}) +setfenv(1,g) + +-- an example +rawset(g,"x",3) +x=2 +y=1 -- cannot redefine `y' diff --git a/test/sieve.lua b/test/sieve.lua new file mode 100644 index 0000000..0871bb2 --- /dev/null +++ b/test/sieve.lua @@ -0,0 +1,29 @@ +-- the sieve of of Eratosthenes programmed with coroutines +-- typical usage: lua -e N=1000 sieve.lua | column + +-- generate all the numbers from 2 to n +function gen (n) + return coroutine.wrap(function () + for i=2,n do coroutine.yield(i) end + end) +end + +-- filter the numbers generated by `g', removing multiples of `p' +function filter (p, g) + return coroutine.wrap(function () + while 1 do + local n = g() + if n == nil then return end + if math.mod(n, p) ~= 0 then coroutine.yield(n) end + end + end) +end + +N=N or 1000 -- from command line +x = gen(N) -- generate primes up to N +while 1 do + local n = x() -- pick a number until done + if n == nil then break end + print(n) -- must be a prime number + x = filter(n, x) -- now remove its multiples +end diff --git a/test/sort.lua b/test/sort.lua new file mode 100644 index 0000000..0bcb15f --- /dev/null +++ b/test/sort.lua @@ -0,0 +1,66 @@ +-- two implementations of a sort function +-- this is an example only. Lua has now a built-in function "sort" + +-- extracted from Programming Pearls, page 110 +function qsort(x,l,u,f) + if ly end) + show("after reverse selection sort",x) + qsort(x,1,n,function (x,y) return x>> ",string.rep(" ",level)) + if t~=nil and t.currentline>=0 then io.write(t.short_src,":",t.currentline," ") end + t=debug.getinfo(2) + if event=="call" then + level=level+1 + else + level=level-1 if level<0 then level=0 end + end + if t.what=="main" then + if event=="call" then + io.write("begin ",t.short_src) + else + io.write("end ",t.short_src) + end + elseif t.what=="Lua" then +-- table.foreach(t,print) + io.write(event," ",t.name or "(Lua)"," <",t.linedefined,":",t.short_src,">") + else + io.write(event," ",t.name or "(C)"," [",t.what,"] ") + end + io.write("\n") +end + +debug.sethook(hook,"cr") +level=0 diff --git a/test/trace-globals.lua b/test/trace-globals.lua new file mode 100644 index 0000000..295e670 --- /dev/null +++ b/test/trace-globals.lua @@ -0,0 +1,38 @@ +-- trace assigments to global variables + +do + -- a tostring that quotes strings. note the use of the original tostring. + local _tostring=tostring + local tostring=function(a) + if type(a)=="string" then + return string.format("%q",a) + else + return _tostring(a) + end + end + + local log=function (name,old,new) + local t=debug.getinfo(3,"Sl") + local line=t.currentline + io.write(t.short_src) + if line>=0 then io.write(":",line) end + io.write(": ",name," is now ",tostring(new)," (was ",tostring(old),")","\n") + end + + local g={} + local set=function (t,name,value) + log(name,g[name],value) + g[name]=value + end + setmetatable(getfenv(),{__index=g,__newindex=set}) +end + +-- an example + +a=1 +b=2 +a=10 +b=20 +b=nil +b=200 +print(a,b,c) diff --git a/test/undefined.lua b/test/undefined.lua new file mode 100644 index 0000000..efe5f24 --- /dev/null +++ b/test/undefined.lua @@ -0,0 +1,9 @@ +-- catch "undefined" global variables + +local f=function (t,i) error("undefined global variable `"..i.."'",2) end +setmetatable(getfenv(),{__index=f}) + +-- an example +a=1 +c=3 +print(a,b,c) -- `b' is undefined diff --git a/test/xd.lua b/test/xd.lua new file mode 100644 index 0000000..32331dc --- /dev/null +++ b/test/xd.lua @@ -0,0 +1,14 @@ +-- hex dump +-- usage: lua xd.lua < file + +local offset=0 + +while 1 do + local s=io.read(16) + if s==nil then return end + io.write(string.format("%08X ",offset)) + string.gsub(s,"(.)",function (c) io.write(string.format("%02X ",string.byte(c))) end) + io.write(string.rep(" ",3*(16-string.len(s)))) + io.write(" ",string.gsub(s,"%c","."),"\n") + offset=offset+16 +end