From f9458638f1fcfe9a7a26afc8e141118ce0c31278 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 2 Sep 2008 04:23:16 -0400 Subject: [PATCH] Patched Lua to 5.1.4. --- src/lua/Makefile | 36 +- src/lua/doc/manual.html | 281 ++++++------ src/lua/doc/readme.html | 4 +- src/lua/etc/lua.pc | 2 +- src/lua/etc/luavs.bat | 56 +-- src/lua/src/lapi.c | 18 +- src/lua/src/lbaselib.c | 12 +- src/lua/src/ldebug.c | 34 +- src/lua/src/llex.c | 160 ++++--- src/lua/src/llex.h | 27 +- src/lua/src/loadlib.c | 8 +- src/lua/src/lobject.h | 4 +- src/lua/src/lparser.c | 936 ++++++++++++++++++++++------------------ src/lua/src/lstrlib.c | 5 +- src/lua/src/ltablib.c | 22 +- src/lua/src/lua.h | 4 +- src/lua/src/luac.c | 11 - src/lua/src/luaconf.h | 8 +- src/lua/src/lundump.c | 10 +- 19 files changed, 913 insertions(+), 725 deletions(-) diff --git a/src/lua/Makefile b/src/lua/Makefile index fec2011..6e78f66 100644 --- a/src/lua/Makefile +++ b/src/lua/Makefile @@ -7,28 +7,33 @@ # Your platform. See PLATS for possible values. PLAT= none -# Where to install. The installation starts in the src directory, so take care -# if INSTALL_TOP is not an absolute path. (Man pages are installed from the -# doc directory.) You may want to make these paths consistent with LUA_ROOT, -# LUA_LDIR, and LUA_CDIR in luaconf.h (and also with etc/lua.pc). -# +# Where to install. The installation starts in the src and doc directories, +# so take care if INSTALL_TOP is not an absolute path. INSTALL_TOP= /usr/local INSTALL_BIN= $(INSTALL_TOP)/bin INSTALL_INC= $(INSTALL_TOP)/include INSTALL_LIB= $(INSTALL_TOP)/lib INSTALL_MAN= $(INSTALL_TOP)/man/man1 +# +# You probably want to make INSTALL_LMOD and INSTALL_CMOD consistent with +# LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h (and also with etc/lua.pc). INSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V INSTALL_CMOD= $(INSTALL_TOP)/lib/lua/$V -# How to install. If you don't have "install" (unlikely) then get install-sh at -# http://dev.w3.org/cvsweb/libwww/config/install-sh -# or use cp instead. -INSTALL_EXEC= $(INSTALL) -p -m 0755 -INSTALL_DATA= $(INSTALL) -p -m 0644 +# How to install. If your install program does not support "-p", then you +# may have to run ranlib on the installed liblua.a (do "make ranlib"). +INSTALL= install -p +INSTALL_EXEC= $(INSTALL) -m 0755 +INSTALL_DATA= $(INSTALL) -m 0644 +# +# If you don't have install you can use cp instead. +# INSTALL= cp -p +# INSTALL_EXEC= $(INSTALL) +# INSTALL_DATA= $(INSTALL) # Utilities. -INSTALL= install -MKDIR= mkdir +MKDIR= mkdir -p +RANLIB= ranlib # == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE ========= @@ -43,7 +48,7 @@ TO_MAN= lua.1 luac.1 # Lua version and release. V= 5.1 -R= 5.1.3 +R= 5.1.4 all: $(PLAT) @@ -54,12 +59,15 @@ test: dummy src/lua test/hello.lua install: dummy - cd src && $(MKDIR) -p $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD) + cd src && $(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD) cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN) cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC) cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB) cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN) +ranlib: + cd src && cd $(INSTALL_LIB) && $(RANLIB) $(TO_LIB) + local: $(MAKE) install INSTALL_TOP=.. diff --git a/src/lua/doc/manual.html b/src/lua/doc/manual.html index b125c13..f46f17c 100644 --- a/src/lua/doc/manual.html +++ b/src/lua/doc/manual.html @@ -3,8 +3,8 @@ Lua 5.1 Reference Manual - - + + @@ -33,7 +33,7 @@

- + @@ -103,7 +103,8 @@

2 - The Language

Non-terminals are shown like non-terminal, keywords are shown like kword, and other terminal symbols are shown like `=´. -The complete syntax of Lua can be found at the end of this manual. +The complete syntax of Lua can be found in §8 +at the end of this manual. @@ -139,7 +140,7 @@

2.1 - Lexical Conventions

and is a reserved word, but And and AND are two different, valid names. As a convention, names starting with an underscore followed by -uppercase letters (such as _VERSION) +uppercase letters (such as _VERSION) are reserved for internal global variables used by Lua. @@ -169,26 +170,15 @@

2.1 - Lexical Conventions

and '\'' (apostrophe [single quote]). Moreover, 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 +A character in a string can also be specified by its numerical value using the escape sequence \ddd, where ddd is a sequence of up to three decimal digits. (Note that if a numerical escape is to be followed by a digit, it must be expressed using exactly three digits.) -Strings in Lua may contain any 8-bit value, including embedded zeros, +Strings in Lua can contain any 8-bit value, including embedded zeros, which can be specified as '\0'. -

-To put a double (single) quote, a newline, a backslash, -a carriage return, -or an embedded zero -inside a literal string enclosed by double (single) quotes -you must use an escape sequence. -Any other character may be directly inserted into the literal. -(Some control characters may cause problems for the file system, -but Lua has no problem with them.) - -

Literal strings can also be defined using a long format enclosed by long brackets. @@ -202,10 +192,10 @@

2.1 - Lexical Conventions

for instance, a closing long bracket of level 4 is written as ]====]. A long string starts with an opening long bracket of any level and ends at the first closing long bracket of the same level. -Literals in this bracketed form may run for several lines, +Literals in this bracketed form can run for several lines, do not interpret any escape sequences, and ignore long brackets of any other level. -They may contain anything except a closing bracket of the proper level. +They can contain anything except a closing bracket of the proper level.

@@ -215,7 +205,7 @@

2.1 - Lexical Conventions

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 five literals below denote the same string: +the five literal strings below denote the same string:
      a = 'alo\n123"'
@@ -229,7 +219,7 @@ 

2.1 - Lexical Conventions

-A numerical constant may be written with an optional decimal part +A numerical constant can be written with an optional decimal part and an optional decimal exponent. Lua also accepts integer hexadecimal constants, by prefixing them with 0x. @@ -288,7 +278,7 @@

2.2 - Values and Types

String represents arrays of characters. Lua is 8-bit clean: -strings may contain any 8-bit character, +strings can contain any 8-bit character, including embedded zeros ('\0') (see §2.1). @@ -327,7 +317,7 @@

2.2 - Values and Types

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, +they can 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 @@ -341,8 +331,8 @@

2.2 - Values and Types

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.9). +table fields can contain functions. +Thus tables can also carry methods (see §2.5.9).

@@ -477,7 +467,7 @@

2.4 - Statements

Lua supports an almost conventional set of statements, similar to those in Pascal or C. This set includes -assignment, control structures, function calls, +assignments, control structures, function calls, and variable declarations. @@ -505,15 +495,15 @@

2.4.1 - Chunks

-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 instructions for -a virtual machine, -and then the compiled code is executed -by an interpreter for the virtual machine. +A chunk can be stored in a file or in a string inside the host program. +To execute a chunk, +Lua first pre-compiles the chunk into instructions for a virtual machine, +and then it executes the compiled code +with an interpreter for the virtual machine.

-Chunks may also be pre-compiled into binary form; +Chunks can 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. @@ -532,7 +522,7 @@

2.4.2 - Blocks

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

 	stat ::= do block end
@@ -550,7 +540,7 @@ 

2.4.2 - Blocks

2.4.3 - Assignment

-Lua allows multiple assignment. +Lua allows multiple assignments. Therefore, the syntax for assignment defines a list of variables on the left side and a list of expressions on the right side. @@ -573,7 +563,7 @@

2.4.3 - Assignment

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 this call enter in the list of values, +then all values returned by that call enter the list of values, before the adjustment (except when the call is enclosed in parentheses; see §2.5). @@ -595,7 +585,13 @@

2.4.3 - Assignment

      x, y = y, x
 

-exchanges the values of x and y. +exchanges the values of x and y, +and + +

+     x, y, z = y, z, x
+

+cyclically permutes the values of x, y, and z.

@@ -644,7 +640,7 @@

2.4.4 - Control Structures

The condition expression of a -control structure may return any value. +control structure can 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). @@ -662,8 +658,8 @@

2.4.4 - Control Structures

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

 	stat ::= return [explist]
@@ -745,7 +741,7 @@ 

2.4.5 - For Statement

  • var, limit, and step are invisible variables. -The names are here for explanatory purposes only. +The names shown here are for explanatory purposes only.
  • @@ -842,8 +838,8 @@

    2.4.6 - Function Calls as Statements

    2.4.7 - Local Declarations

    -Local variables may be declared anywhere inside a block. -The declaration may include an initial assignment: +Local variables can be declared anywhere inside a block. +The declaration can include an initial assignment:

     	stat ::= local namelist [`=´ explist]
    @@ -908,12 +904,12 @@ 

    2.5 - Expressions

    -Both function calls and vararg expressions may result in multiple values. -If the expression is used as a statement (see §2.4.6) -(only possible for function calls), +Both function calls and vararg expressions can result in multiple values. +If an expression is used as a statement +(only possible for function calls (see §2.4.6)), then its return list is adjusted to zero elements, thus discarding all returned values. -If the expression is used as the last (or the only) element +If an expression is used as the last (or the only) element of a list of expressions, then no adjustment is made (unless the call is enclosed in parentheses). @@ -931,7 +927,7 @@

    2.5 - Expressions

    g(x, f()) -- g gets x plus all results from f() a,b,c = f(), x -- f() is adjusted to 1 result (c gets nil) a,b = ... -- a gets the first vararg parameter, b gets - -- the second (both a and b may get nil if there + -- the second (both a and b can get nil if there -- is no corresponding vararg parameter) a,b,c = x, f() -- f() is adjusted to 2 results @@ -945,7 +941,7 @@

    2.5 - Expressions

    -An expression enclosed in parentheses always results in only one value. +Any 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. @@ -1023,6 +1019,8 @@

    2.5.2 - Relational Operators

    then their values are compared according to the current locale. Otherwise, Lua tries to call the "lt" or the "le" metamethod (see §2.8). +A comparison a > b is translated to b < a +and a >= b is translated to b <= a. @@ -1060,7 +1058,7 @@

    2.5.3 - Logical Operators

    10 and 20 --> 20

  • (In this manual, ---> indicates the result of the preceding expression.) +--> indicates the result of the preceding expression.) @@ -1090,13 +1088,13 @@

    2.5.5 - The Length Operator

    The length of a table t is defined to be any integer index n such that t[n] is not nil and t[n+1] is nil; -moreover, if t[1] is nil, n may be zero. +moreover, if t[1] is nil, n can be zero. For a regular array, with non-nil values from 1 to a given n, its length is exactly that n, the index of its last value. If the array has "holes" (that is, nil values between other non-nil values), -then #t may be any of the indices that +then #t can be any of the indices that directly precedes a nil value (that is, it may consider any such nil value as the end of the array). @@ -1132,7 +1130,7 @@

    2.5.6 - Precedence

    2.5.7 - 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, +A constructor can be used to create an empty table or to create a table and initialize some of its fields. The general syntax for constructors is @@ -1179,12 +1177,12 @@

    2.5.7 - Table Constructors

    then all values returned by this expression enter the list consecutively (see §2.5.8). To avoid this, -enclose the function call (or the vararg expression) +enclose the function call or the vararg expression in parentheses (see §2.5).

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

    2.5.9 - Function Definitions

    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. +can refer to different external local variables +and can have different environment tables.

    @@ -1377,7 +1375,7 @@

    2.5.9 - Function Definitions

    then its return list is adjusted to one element. If the expression is used as the last element of a list of expressions, then no adjustment is made -(unless the call is enclosed in parentheses). +(unless that last expression is enclosed in parentheses).

    @@ -1520,7 +1518,7 @@

    2.7 - Error Handling

    2.8 - Metatables

    -Every value in Lua may have a metatable. +Every value in Lua can have a metatable. This metatable is an ordinary Lua table that defines the behavior of the original value under certain special operations. @@ -1549,22 +1547,22 @@

    2.8 - Metatables

    through the setmetatable function. You cannot change the metatable of other types from Lua -(except using the debug library); +(except by using the debug library); you must use the C API for that.

    Tables and full userdata have individual metatables -(although multiple tables and userdata can share their metatables); -values of all other types share one single metatable per type. -So, there is one single metatable for all numbers, +(although multiple tables and userdata can share their metatables). +Values of all other types share one single metatable per type; +that is, there is one single metatable for all numbers, one for all strings, etc.

    -A metatable may control how an object behaves in arithmetic operations, +A metatable controls how an object behaves in arithmetic operations, order comparisons, concatenation, length operation, and indexing. -A metatable can also define a function to be called when a userdata +A metatable also can define a function to be called when a userdata is garbage collected. For each of these operations Lua associates a specific key called an event. @@ -1806,7 +1804,7 @@

    2.8 - Metatables

    if h then return (h(op1, op2)) else - error(···); + error(···) end end end @@ -1833,7 +1831,7 @@

    2.8 - Metatables

    if h then return not h(op2, op1) else - error(···); + error(···) end end end @@ -1860,7 +1858,7 @@

    2.8 - Metatables

    else h = metatable(table).__index if h == nil then - error(···); + error(···) end end if type(h) == "function" then @@ -1886,7 +1884,7 @@

    2.8 - Metatables

    else h = metatable(table).__newindex if h == nil then - error(···); + error(···) end end if type(h) == "function" then @@ -1933,6 +1931,17 @@

    2.9 - Environments

    multiple objects can share the same environment. +

    +Threads are created sharing the environment of the creating thread. +Userdata and C functions are created sharing the environment +of the creating C function. +Non-nested Lua functions +(created by loadfile, loadstring or load) +are created sharing the environment of the creating thread. +Nested Lua functions are created sharing the environment of +the creating Lua function. + +

    Environments associated with userdata have no meaning for Lua. It is only a convenience feature for programmers to associate a table to @@ -1942,23 +1951,22 @@

    2.9 - Environments

    Environments associated with threads are called global environments. -They are used as the default environment for their threads and -non-nested functions created by the thread -(through loadfile, loadstring or load) +They are used as the default environment for threads and +non-nested Lua functions created by the thread and can be directly accessed by C code (see §3.3).

    -Environments associated with C functions can be directly +The environment associated with a C function can be directly accessed by C code (see §3.3). -They are used as the default environment for other C functions -created by the function. +It is used as the default environment for other C functions +and userdata created by the function.

    Environments associated with Lua functions are used to resolve all accesses to global variables within the function (see §2.3). -They are used as the default environment for other Lua functions +They are used as the default environment for nested Lua functions created by the function. @@ -1985,9 +1993,9 @@

    2.10 - Garbage Collection

    Lua manages memory automatically by running a garbage collector from time to time to collect all dead objects -(that is, these objects that are no longer accessible from Lua). -All objects in Lua are subject to automatic management: -tables, userdata, functions, threads, and strings. +(that is, objects that are no longer accessible from Lua). +All memory used by Lua is subject to automatic management: +tables, userdata, functions, threads, strings, etc.

    @@ -1995,15 +2003,17 @@

    2.10 - Garbage Collection

    It uses two numbers to control its garbage-collection cycles: the garbage-collector pause and the garbage-collector step multiplier. +Both use percentage points as units +(so that a value of 100 means an internal value of 1).

    The garbage-collector pause controls how long the collector waits before starting a new cycle. Larger values make the collector less aggressive. -Values smaller than 1 mean the collector will not wait to +Values smaller than 100 mean the collector will not wait to start a new cycle. -A value of 2 means that the collector waits for the total memory in use +A value of 200 means that the collector waits for the total memory in use to double before starting a new cycle. @@ -2013,17 +2023,15 @@

    2.10 - Garbage Collection

    memory allocation. Larger values make the collector more aggressive but also increase the size of each incremental step. -Values smaller than 1 make the collector too slow and -may result in the collector never finishing a cycle. -The default, 2, means that the collector runs at "twice" +Values smaller than 100 make the collector too slow and +can result in the collector never finishing a cycle. +The default, 200, means that the collector runs at "twice" the speed of memory allocation.

    You can change these numbers by calling lua_gc in C or collectgarbage in Lua. -Both get percentage points as arguments -(so an argument of 100 means a real value of 1). With these functions you can also control the collector directly (e.g., stop and restart it). @@ -2100,7 +2108,7 @@

    2.10.2 - Weak Tables

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

    2.11 - Coroutines

    When you first call coroutine.resume, passing as its first argument -the thread returned by coroutine.create, +a 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 passed on @@ -2383,7 +2391,7 @@

    3.4 - C Closures

    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, +current function (but not greater than 256), produces an acceptable (but invalid) index. @@ -2431,7 +2439,7 @@

    3.6 - Error Handling in C

    -Most functions in the API may throw an error, +Most functions in the API can throw an error, for instance due to a memory allocation error. The documentation for each function indicates whether it can throw errors. @@ -2459,7 +2467,7 @@

    3.7 - Functions and Types

    The second field, p, is how many elements the function pushes onto the stack. (Any function always pushes its results after popping its arguments.) -A field in the form x|y means the function may push (or pop) +A field in the form x|y means the function can push (or pop) x or y elements, depending on the situation; an interrogation mark '?' means that @@ -2544,7 +2552,7 @@

    3.7 - Functions and Types

    Lua calls a panic function and then calls exit(EXIT_FAILURE), thus exiting the host application. -Your panic function may avoid this exit by +Your panic function can avoid this exit by never returning (e.g., doing a long jump). @@ -2589,7 +2597,7 @@

    3.7 - Functions and Types

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

    @@ -2858,13 +2866,13 @@ 

    3.7 - Functions and Types

  • LUA_GCSETPAUSE: -sets data/100 as the new value +sets data as the new value for the pause of the collector (see §2.10). The function returns the previous value of the pause.
  • LUA_GCSETSTEPMUL: -sets data/100 as the new value for the step multiplier of +sets data as the new value for the step multiplier of the collector (see §2.10). The function returns the previous value of the step multiplier.
  • @@ -3485,6 +3493,10 @@

    3.7 - Functions and Types

    lua_pushcclosure also pops these values from the stack. +

    +The maximum value for n is 255. + + @@ -3774,7 +3786,8 @@

    3.7 - Functions and Types

    with a new piece of the chunk and set size to the block size. The block must exist until the reader function is called again. -To signal the end of the chunk, the reader must return NULL. +To signal the end of the chunk, +the reader must return NULL or set size to zero. The reader function may return pieces of any size greater than zero. @@ -4081,7 +4094,7 @@

    3.7 - Functions and Types

    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. +but can contain other zeros in its body. Because Lua has garbage collection, there is no guarantee that the pointer returned by lua_tolstring will be valid after the corresponding value is removed from the stack. @@ -4112,7 +4125,7 @@

    3.7 - Functions and Types

    Converts the value at the given acceptable index to a generic C pointer (void*). -The value may be a userdata, a table, a thread, or a function; +The value can be a userdata, a table, a thread, or a function; otherwise, lua_topointer returns NULL. Different objects will give different pointers. There is no way to convert the pointer back to its original value. @@ -4350,8 +4363,8 @@

    3.8 - The Debug Interface

    a reasonable name for the given function. Because functions in Lua are first-class values, they do not have a fixed name: -some functions may be the value of multiple global variables, -while others may be stored only in a table field. +some functions can be the value of multiple global variables, +while others can be stored only in a table field. The lua_getinfo function checks how the function was called to find a suitable name. If it cannot find a name, @@ -4581,7 +4594,7 @@

    3.8 - The Debug Interface

    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, +For return events, event can 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; @@ -5632,7 +5645,7 @@

    5 - Standard Libraries

      -
    • basic library;
    • +
    • basic library,
    • which includes the coroutine sub-library;
    • package library;
    • @@ -5731,13 +5744,15 @@

      5.1 - Basic Functions

    • "setpause": -sets arg/100 as the new value for the pause of +sets arg as the new value for the pause of the collector (see §2.10). +Returns the previous value for pause.
    • "setstepmul": -sets arg/100 as the new value for the step multiplier of +sets arg as the new value for the step multiplier of the collector (see §2.10). +Returns the previous value for step.
    @@ -5842,7 +5857,7 @@

    5.1 - Basic Functions

    Loads a chunk using function func to get its pieces. Each call to func must return a string that concatenates with previous results. -A return of nil (or no value) signals the end of the chunk. +A return of an empty string, nil, or no value signals the end of the chunk.

    @@ -6088,7 +6103,7 @@

    5.1 - Basic Functions

    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, +In base 10 (the default), the number can have a decimal part, as well as an optional exponent part (see §2.1). In other bases, only unsigned integers are accepted. @@ -6335,7 +6350,7 @@

    5.3 - Modules

    -This function may receive optional options after +This function can receive optional options after the module name, where each option is a function to be applied over the module. @@ -6442,7 +6457,7 @@

    5.3 - Modules

    require calls each of these searchers in ascending order, with the module name (the argument given to require) as its sole parameter. -The function may return another function (the module loader) +The function can return another function (the module loader) or a string explaining why it did not find that module (or nil if it has nothing to say). Lua initializes this table with four functions. @@ -6617,6 +6632,10 @@

    5.4 - String Manipulation

    can be written as s:byte(i). +

    +The string library assumes one-byte character encodings. + +


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

    Returns the internal numerical codes of the characters s[i], @@ -6667,7 +6686,7 @@

    5.4 - String Manipulation

    otherwise, it returns nil. A third, optional numerical argument init specifies where to start the search; -its default value is 1 and may be negative. +its default value is 1 and can 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, @@ -6771,7 +6790,7 @@

    5.4 - String Manipulation

    in which all (or the first n, if given) occurrences of the pattern have been replaced by a replacement string specified by repl, -which may be a string, a table, or a function. +which can be a string, a table, or a function. gsub also returns, as its second value, the total number of matches that occurred. @@ -6869,7 +6888,7 @@

    5.4 - String Manipulation

    then the whole match is returned. A third, optional numerical argument init specifies where to start the search; -its default value is 1 and may be negative. +its default value is 1 and can be negative. @@ -6893,7 +6912,7 @@

    5.4 - String Manipulation


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

    Returns the substring of s that starts at i and continues until j; -i and j may be negative. +i and j can 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, @@ -6962,9 +6981,9 @@

    Character Class:

  • [set]: represents the class which is the union of all characters in set. -A range of characters may be specified by +A range of characters can be specified by separating the end characters of the range with a '-'. -All classes %x described above may also be used as +All classes %x described above can also be used as components in set. All other characters in set represent themselves. For example, [%w_] (or [_%w]) @@ -7001,7 +7020,7 @@

    Character Class:

    Pattern Item:

    -A pattern item may be +A pattern item can be

      @@ -7070,7 +7089,7 @@

      Pattern:

      Captures:

      -A pattern may contain sub-patterns enclosed in parentheses; +A pattern can 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. @@ -7320,7 +7339,8 @@

      5.6 - Mathematical Functions

      -Returns the remainder of the division of x by y. +Returns the remainder of the division of x by y +that rounds the quotient towards zero. @@ -7657,7 +7677,7 @@

      5.7 - Input and Output Facilities

    • "a+": append update mode, previous data is preserved, writing is only allowed at the end of file.

    -The mode string may also have a 'b' at the end, +The mode string can 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. @@ -8115,6 +8135,22 @@

    5.8 - Operating System Facilities

    and explicitly removed when no longer needed. +

    +On some systems (POSIX), +this function also creates a file with that name, +to avoid security risks. +(Someone else might create the file with wrong permissions +in the time between getting the name and creating the file.) +You still have to open the file to use it +and to remove it (even if you do not use it). + + +

    +When possible, +you may prefer to use io.tmpfile, +which automatically removes the file when the program ends. + + @@ -8207,7 +8243,7 @@

    5.9 - The Debug Library

    -The returned table may contain all the fields returned by lua_getinfo, +The returned table can contain 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, except the table of valid lines. @@ -8326,7 +8362,8 @@

    5.9 - The Debug Library

    When the hook is called, its first parameter is a string describing the event that has triggered its call: -"call", "return" (or "tail return"), +"call", "return" (or "tail return", +when simulating a return from a tail call), "line", and "count". For line events, the hook also gets the new line number as its second parameter. @@ -8754,10 +8791,10 @@

    8 - The Complete Syntax of Lua


    Last update: -Fri Jan 18 22:32:24 BRST 2008 +Mon Aug 18 13:25:46 BRT 2008 diff --git a/src/lua/doc/readme.html b/src/lua/doc/readme.html index 972fadd..38be6db 100644 --- a/src/lua/doc/readme.html +++ b/src/lua/doc/readme.html @@ -12,7 +12,7 @@

    Documentation

    -This is the documentation included in the source distribution of Lua 5.1.3. +This is the documentation included in the source distribution of Lua 5.1.4.
    • Reference manual @@ -33,7 +33,7 @@


      Last update: -Wed Dec 19 13:59:14 BRST 2007 +Tue Aug 12 14:46:07 BRT 2008 diff --git a/src/lua/etc/lua.pc b/src/lua/etc/lua.pc index 19a5c91..f52f55b 100644 --- a/src/lua/etc/lua.pc +++ b/src/lua/etc/lua.pc @@ -5,7 +5,7 @@ # grep '^V=' ../Makefile V= 5.1 # grep '^R=' ../Makefile -R= 5.1.3 +R= 5.1.4 # grep '^INSTALL_.*=' ../Makefile | sed 's/INSTALL_TOP/prefix/' prefix= /usr/local diff --git a/src/lua/etc/luavs.bat b/src/lua/etc/luavs.bat index 054b462..08c2bed 100644 --- a/src/lua/etc/luavs.bat +++ b/src/lua/etc/luavs.bat @@ -1,28 +1,28 @@ -@rem Script to build Lua under "Visual Studio .NET Command Prompt". -@rem Do not run from this directory; run it from the toplevel: etc\luavs.bat . -@rem It creates lua51.dll, lua51.lib, lua.exe, and luac.exe in src. -@rem (contributed by David Manura and Mike Pall) - -@setlocal -@set MYCOMPILE=cl /nologo /MD /O2 /W3 /c /D_CRT_SECURE_NO_DEPRECATE -@set MYLINK=link /nologo -@set MYMT=mt /nologo - -cd src -%MYCOMPILE% /DLUA_BUILD_AS_DLL l*.c -del lua.obj luac.obj -%MYLINK% /DLL /out:lua51.dll l*.obj -if exist lua51.dll.manifest^ - %MYMT% -manifest lua51.dll.manifest -outputresource:lua51.dll;2 -%MYCOMPILE% /DLUA_BUILD_AS_DLL lua.c -%MYLINK% /out:lua.exe lua.obj lua51.lib -if exist lua.exe.manifest^ - %MYMT% -manifest lua.exe.manifest -outputresource:lua.exe -%MYCOMPILE% l*.c print.c -del lua.obj linit.obj lbaselib.obj ldblib.obj liolib.obj lmathlib.obj^ - loslib.obj ltablib.obj lstrlib.obj loadlib.obj -%MYLINK% /out:luac.exe *.obj -if exist luac.exe.manifest^ - %MYMT% -manifest luac.exe.manifest -outputresource:luac.exe -del *.obj *.manifest -cd .. +@rem Script to build Lua under "Visual Studio .NET Command Prompt". +@rem Do not run from this directory; run it from the toplevel: etc\luavs.bat . +@rem It creates lua51.dll, lua51.lib, lua.exe, and luac.exe in src. +@rem (contributed by David Manura and Mike Pall) + +@setlocal +@set MYCOMPILE=cl /nologo /MD /O2 /W3 /c /D_CRT_SECURE_NO_DEPRECATE +@set MYLINK=link /nologo +@set MYMT=mt /nologo + +cd src +%MYCOMPILE% /DLUA_BUILD_AS_DLL l*.c +del lua.obj luac.obj +%MYLINK% /DLL /out:lua51.dll l*.obj +if exist lua51.dll.manifest^ + %MYMT% -manifest lua51.dll.manifest -outputresource:lua51.dll;2 +%MYCOMPILE% /DLUA_BUILD_AS_DLL lua.c +%MYLINK% /out:lua.exe lua.obj lua51.lib +if exist lua.exe.manifest^ + %MYMT% -manifest lua.exe.manifest -outputresource:lua.exe +%MYCOMPILE% l*.c print.c +del lua.obj linit.obj lbaselib.obj ldblib.obj liolib.obj lmathlib.obj^ + loslib.obj ltablib.obj lstrlib.obj loadlib.obj +%MYLINK% /out:luac.exe *.obj +if exist luac.exe.manifest^ + %MYMT% -manifest luac.exe.manifest -outputresource:luac.exe +del *.obj *.manifest +cd .. diff --git a/src/lua/src/lapi.c b/src/lua/src/lapi.c index d7e8931..5d5145d 100644 --- a/src/lua/src/lapi.c +++ b/src/lua/src/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.55.1.3 2008/01/03 15:20:39 roberto Exp $ +** $Id: lapi.c,v 2.55.1.5 2008/07/04 18:41:18 roberto Exp $ ** Lua API ** See Copyright Notice in lua.h */ @@ -93,15 +93,14 @@ void luaA_pushobject (lua_State *L, const TValue *o) { LUA_API int lua_checkstack (lua_State *L, int size) { - int res; + int res = 1; lua_lock(L); - if ((L->top - L->base + size) > LUAI_MAXCSTACK) + if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) res = 0; /* stack overflow */ - else { + else if (size > 0) { luaD_checkstack(L, size); if (L->ci->top < L->top + size) L->ci->top = L->top + size; - res = 1; } lua_unlock(L); return res; @@ -930,10 +929,13 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { g->GCthreshold = g->totalbytes - a; else g->GCthreshold = 0; - while (g->GCthreshold <= g->totalbytes) + while (g->GCthreshold <= g->totalbytes) { luaC_step(L); - if (g->gcstate == GCSpause) /* end of cycle? */ - res = 1; /* signal it */ + if (g->gcstate == GCSpause) { /* end of cycle? */ + res = 1; /* signal it */ + break; + } + } break; } case LUA_GCSETPAUSE: { diff --git a/src/lua/src/lbaselib.c b/src/lua/src/lbaselib.c index eb06bce..2a4c079 100644 --- a/src/lua/src/lbaselib.c +++ b/src/lua/src/lbaselib.c @@ -1,5 +1,5 @@ /* -** $Id: lbaselib.c,v 1.191.1.4 2008/01/20 13:53:22 roberto Exp $ +** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $ ** Basic library ** See Copyright Notice in lua.h */ @@ -344,10 +344,12 @@ static int luaB_unpack (lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); i = luaL_optint(L, 2, 1); e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1)); + if (i > e) return 0; /* empty range */ n = e - i + 1; /* number of elements */ - if (n <= 0) return 0; /* empty range */ - luaL_checkstack(L, n, "table too big to unpack"); - for (; i<=e; i++) /* push arg[i...e] */ + if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ + return luaL_error(L, "too many results to unpack"); + lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ + while (i++ < e) /* push arg[i + 1...e] */ lua_rawgeti(L, 1, i); return n; } @@ -526,7 +528,7 @@ static int auxresume (lua_State *L, lua_State *co, int narg) { status = lua_resume(co, narg); if (status == 0 || status == LUA_YIELD) { int nres = lua_gettop(co); - if (!lua_checkstack(L, nres)) + if (!lua_checkstack(L, nres + 1)) luaL_error(L, "too many results to resume"); lua_xmove(co, L, nres); /* move yielded values */ return nres; diff --git a/src/lua/src/ldebug.c b/src/lua/src/ldebug.c index 9eac4a9..50ad3d3 100644 --- a/src/lua/src/ldebug.c +++ b/src/lua/src/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.29.1.3 2007/12/28 15:32:23 roberto Exp $ +** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -275,12 +275,12 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { static int precheck (const Proto *pt) { check(pt->maxstacksize <= MAXSTACK); - lua_assert(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize); - lua_assert(!(pt->is_vararg & VARARG_NEEDSARG) || + check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize); + check(!(pt->is_vararg & VARARG_NEEDSARG) || (pt->is_vararg & VARARG_HASARG)); check(pt->sizeupvalues <= pt->nups); check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0); - check(GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); + check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); return 1; } @@ -346,9 +346,18 @@ static Instruction symbexec (const Proto *pt, int lastpc, int reg) { int dest = pc+1+b; check(0 <= dest && dest < pt->sizecode); if (dest > 0) { - /* cannot jump to a setlist count */ - Instruction d = pt->code[dest-1]; - check(!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)); + int j; + /* check that it does not jump to a setlist count; this + is tricky, because the count from a previous setlist may + have the same value of an invalid setlist; so, we must + go all the way back to the first of them (if any) */ + for (j = 0; j < dest; j++) { + Instruction d = pt->code[dest-1-j]; + if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break; + } + /* if 'j' is even, previous value is not a setlist (even if + it looks like one) */ + check((j&1) == 0); } } break; @@ -363,7 +372,11 @@ static Instruction symbexec (const Proto *pt, int lastpc, int reg) { } switch (op) { case OP_LOADBOOL: { - check(c == 0 || pc+2 < pt->sizecode); /* check its jump */ + if (c == 1) { /* does it jump? */ + check(pc+2 < pt->sizecode); /* check its jump */ + check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST || + GETARG_C(pt->code[pc+1]) != 0); + } break; } case OP_LOADNIL: { @@ -428,7 +441,10 @@ static Instruction symbexec (const Proto *pt, int lastpc, int reg) { } case OP_SETLIST: { if (b > 0) checkreg(pt, a + b); - if (c == 0) pc++; + if (c == 0) { + pc++; + check(pc < pt->sizecode - 1); + } break; } case OP_CLOSURE: { diff --git a/src/lua/src/llex.c b/src/lua/src/llex.c index 8a00c53..6dc3193 100644 --- a/src/lua/src/llex.c +++ b/src/lua/src/llex.c @@ -1,5 +1,5 @@ /* -** $Id: llex.c,v 2.20 2006/03/09 18:14:31 roberto Exp $ +** $Id: llex.c,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -35,14 +35,12 @@ /* ORDER RESERVED */ const char *const luaX_tokens [] = { - "and", "else", "elseif", - "endfunction", "endif", "endfor", "endwhile", - "false", "for", "function", "if", "to", "downto", "step", "of", - "not", "or", - "number", "string", "boolean", "array", "nothing", - "return", "returns", "true", "while", + "and", "break", "do", "else", "elseif", + "end", "false", "for", "function", "if", + "in", "local", "nil", "not", "or", "repeat", + "return", "then", "true", "until", "while", "..", "...", "==", ">=", "<=", "~=", - "", "", "", "", "", + "", "", "", "", NULL }; @@ -91,8 +89,8 @@ const char *luaX_token2str (LexState *ls, int token) { static const char *txtToken (LexState *ls, int token) { switch (token) { case TK_NAME: - case TK_STRINGLIT: - case TK_NUMBERLIT: + case TK_STRING: + case TK_NUMBER: save(ls, '\0'); return luaZ_buffer(ls->buff); default: @@ -138,10 +136,6 @@ static void inclinenumber (LexState *ls) { void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { - lua_newtable(L); /* build table for resolving Toby functions at the end. */ - ls->to_resolve_table = lua_gettop(L); - lua_newtable(L); /* build table for resolving Toby functions at the end. */ - ls->resolved_table = lua_gettop(L); ls->decpoint = '.'; ls->L = L; ls->lookahead.token = TK_EOS; /* no look-ahead token */ @@ -150,7 +144,6 @@ void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { ls->linenumber = 1; ls->lastline = 1; ls->source = source; - ls->infunc = 0; luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ next(ls); /* read first char */ } @@ -190,7 +183,7 @@ static void trydecpoint (LexState *ls, SemInfo *seminfo) { if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) { /* format error with correct decimal point: no more options */ buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ - luaX_lexerror(ls, "malformed number", TK_NUMBERLIT); + luaX_lexerror(ls, "malformed number", TK_NUMBER); } } @@ -212,6 +205,74 @@ static void read_numeral (LexState *ls, SemInfo *seminfo) { } +static int skip_sep (LexState *ls) { + int count = 0; + int s = ls->current; + lua_assert(s == '[' || s == ']'); + save_and_next(ls); + while (ls->current == '=') { + save_and_next(ls); + count++; + } + return (ls->current == s) ? count : (-count) - 1; +} + + +static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { + int cont = 0; + (void)(cont); /* avoid warnings when `cont' is not used */ + save_and_next(ls); /* skip 2nd `[' */ + if (currIsNewline(ls)) /* string starts with a newline? */ + inclinenumber(ls); /* skip it */ + for (;;) { + switch (ls->current) { + case EOZ: + luaX_lexerror(ls, (seminfo) ? "unfinished long string" : + "unfinished long comment", TK_EOS); + break; /* to avoid warnings */ +#if defined(LUA_COMPAT_LSTR) + case '[': { + if (skip_sep(ls) == sep) { + save_and_next(ls); /* skip 2nd `[' */ + cont++; +#if LUA_COMPAT_LSTR == 1 + if (sep == 0) + luaX_lexerror(ls, "nesting of [[...]] is deprecated", '['); +#endif + } + break; + } +#endif + case ']': { + if (skip_sep(ls) == sep) { + save_and_next(ls); /* skip 2nd `]' */ +#if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2 + cont--; + if (sep == 0 && cont >= 0) break; +#endif + goto endloop; + } + break; + } + case '\n': + case '\r': { + save(ls, '\n'); + inclinenumber(ls); + if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ + break; + } + default: { + if (seminfo) save_and_next(ls); + else next(ls); + } + } + } endloop: + if (seminfo) + seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), + luaZ_bufflen(ls->buff) - 2*(2 + sep)); +} + + static void read_string (LexState *ls, int del, SemInfo *seminfo) { save_and_next(ls); while (ls->current != del) { @@ -221,7 +282,7 @@ static void read_string (LexState *ls, int del, SemInfo *seminfo) { continue; /* to avoid warnings */ case '\n': case '\r': - luaX_lexerror(ls, "unfinished string", TK_STRINGLIT); + luaX_lexerror(ls, "unfinished string", TK_STRING); continue; /* to avoid warnings */ case '\\': { int c; @@ -248,7 +309,7 @@ static void read_string (LexState *ls, int del, SemInfo *seminfo) { next(ls); } while (++i<3 && isdigit(ls->current)); if (c > UCHAR_MAX) - luaX_lexerror(ls, "escape sequence too large", TK_STRINGLIT); + luaX_lexerror(ls, "escape sequence too large", TK_STRING); save(ls, c); } continue; @@ -275,40 +336,35 @@ static int llex (LexState *ls, SemInfo *seminfo) { case '\n': case '\r': { inclinenumber(ls); - return TK_EOL; + continue; } - case '/': { + case '-': { next(ls); - if (ls->current == '*') { - int saweol = 0; - do { - next(ls); - if (currIsNewline(ls)) { - inclinenumber(ls); - saweol = 1; - } - if (ls->current == '*') { - next(ls); - if (ls->current == '/') { - next(ls); - /* return EOL if we passed one */ - if (saweol) - return TK_EOL; - break; /* otherwise, keep lexing... */ - } - } - } while (ls->current != EOZ); - if (ls->current == EOZ) { - luaX_lexerror(ls, "unfinished multiline comment", TK_EOS); + if (ls->current != '-') return '-'; + /* else is a comment */ + next(ls); + if (ls->current == '[') { + int sep = skip_sep(ls); + luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ + if (sep >= 0) { + read_long_string(ls, NULL, sep); /* long comment */ + luaZ_resetbuffer(ls->buff); + continue; } - } else if (ls->current != '/') { /* not a comment at all. */ - return '/'; - } else { /* singleline comment */ - do { - next(ls); - } while (!currIsNewline(ls) && ls->current != EOZ); } - continue; /* just in case... */ + /* else short comment */ + while (!currIsNewline(ls) && ls->current != EOZ) + next(ls); + continue; + } + case '[': { + int sep = skip_sep(ls); + if (sep >= 0) { + read_long_string(ls, seminfo, sep); + return TK_STRING; + } + else if (sep == -1) return '['; + else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING); } case '=': { next(ls); @@ -333,7 +389,7 @@ static int llex (LexState *ls, SemInfo *seminfo) { case '"': case '\'': { read_string(ls, ls->current, seminfo); - return TK_STRINGLIT; + return TK_STRING; } case '.': { save_and_next(ls); @@ -345,7 +401,7 @@ static int llex (LexState *ls, SemInfo *seminfo) { else if (!isdigit(ls->current)) return '.'; else { read_numeral(ls, seminfo); - return TK_NUMBERLIT; + return TK_NUMBER; } } case EOZ: { @@ -359,14 +415,12 @@ static int llex (LexState *ls, SemInfo *seminfo) { } else if (isdigit(ls->current)) { read_numeral(ls, seminfo); - return TK_NUMBERLIT; + return TK_NUMBER; } else if (isalpha(ls->current) || ls->current == '_') { /* identifier or reserved word */ TString *ts; do { - /* force to lowercase, since Toby is case-insensitive. */ - ls->current = tolower(ls->current); save_and_next(ls); } while (isalnum(ls->current) || ls->current == '_'); ts = luaX_newstring(ls, luaZ_buffer(ls->buff), diff --git a/src/lua/src/llex.h b/src/lua/src/llex.h index e23d171..a9201ce 100644 --- a/src/lua/src/llex.h +++ b/src/lua/src/llex.h @@ -1,11 +1,11 @@ /* -** $Id: llex.h,v 1.58 2006/03/23 18:23:32 roberto Exp $ +** $Id: llex.h,v 1.58.1.1 2007/12/27 13:02:25 roberto Exp $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ -#ifndef tobylex_h -#define tobylex_h +#ifndef llex_h +#define llex_h #include "lobject.h" #include "lzio.h" @@ -23,20 +23,15 @@ */ enum RESERVED { /* terminal symbols denoted by reserved words */ - TK_AND = FIRST_RESERVED, - TK_ELSE, TK_ELSEIF, TK_ENDFUNCTION, TK_ENDIF, TK_ENDFOR, TK_ENDWHILE, - TK_FALSE, TK_FOR, TK_FUNCTION, - TK_IF, TK_TO, TK_DOWNTO, TK_STEP, TK_OF, TK_NOT, TK_OR, - TK_NUMBER, TK_STRING, TK_BOOLEAN, TK_ARRAY, TK_NOTHING, - TK_RETURN, TK_RETURNS, TK_TRUE, TK_WHILE, - /* DON'T ADD RESERVED KEYWORDS AFTER TK_WHILE! */ + 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_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBERLIT, - TK_NAME, TK_STRINGLIT, TK_EOL, TK_EOS + TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, + TK_NAME, TK_STRING, TK_EOS }; -#define TOBY_MAINLINE_FNNAME "main" - /* number of reserved words */ #define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) @@ -69,9 +64,6 @@ typedef struct LexState { Mbuffer *buff; /* buffer for tokens */ TString *source; /* current source name */ char decpoint; /* locale decimal point */ - int infunc; /* non-zero if we're parsing a function body, 0 if we're not. */ - int to_resolve_table; /* pos of table of to-be-resolved on Lua stack. */ - int resolved_table; /* pos of table of resolved on Lua stack. */ } LexState; @@ -85,4 +77,5 @@ LUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token); LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s); LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); + #endif diff --git a/src/lua/src/loadlib.c b/src/lua/src/loadlib.c index d955f3e..0d401eb 100644 --- a/src/lua/src/loadlib.c +++ b/src/lua/src/loadlib.c @@ -1,5 +1,5 @@ /* -** $Id: loadlib.c,v 1.52.1.2 2007/12/28 14:58:43 roberto Exp $ +** $Id: loadlib.c,v 1.52.1.3 2008/08/06 13:29:28 roberto Exp $ ** Dynamic library loader for Lua ** See Copyright Notice in lua.h ** @@ -506,8 +506,10 @@ static int ll_require (lua_State *L) { static void setfenv (lua_State *L) { lua_Debug ar; - lua_getstack(L, 1, &ar); - lua_getinfo(L, "f", &ar); + if (lua_getstack(L, 1, &ar) == 0 || + lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ + lua_iscfunction(L, -1)) + luaL_error(L, LUA_QL("module") " not called from a Lua function"); lua_pushvalue(L, -2); lua_setfenv(L, -2); lua_pop(L, 1); diff --git a/src/lua/src/lobject.h b/src/lua/src/lobject.h index e7199df..f1e447e 100644 --- a/src/lua/src/lobject.h +++ b/src/lua/src/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lobject.h,v 2.20.1.2 2008/08/06 13:29:48 roberto Exp $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -208,7 +208,7 @@ typedef union TString { #define getstr(ts) cast(const char *, (ts) + 1) -#define svalue(o) getstr(tsvalue(o)) +#define svalue(o) getstr(rawtsvalue(o)) diff --git a/src/lua/src/lparser.c b/src/lua/src/lparser.c index 588fb9b..1e2a9a8 100644 --- a/src/lua/src/lparser.c +++ b/src/lua/src/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 2.42 2006/06/05 15:57:59 roberto Exp $ +** $Id: lparser.c,v 2.42.1.3 2007/12/28 15:32:23 roberto Exp $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -50,12 +50,12 @@ typedef struct BlockCnt { /* ** prototypes for recursive non-terminal functions */ -static void chunk (LexState *ls, int mainline); +static void chunk (LexState *ls); static void expr (LexState *ls, expdesc *v); static void anchor_token (LexState *ls) { - if (ls->t.token == TK_NAME || ls->t.token == TK_STRINGLIT) { + if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { TString *ts = ls->t.seminfo.ts; luaX_newstring(ls, getstr(ts), ts->tsv.len); } @@ -96,10 +96,6 @@ static void checknext (LexState *ls, int c) { luaX_next(ls); } -static void skip_blank_lines (LexState *ls) { - while (testnext(ls, TK_EOL)) {} -} - #define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } @@ -139,6 +135,11 @@ static void codestring (LexState *ls, expdesc *e, TString *s) { } +static void checkname(LexState *ls, expdesc *e) { + codestring(ls, e, str_checkname(ls)); +} + + static int registerlocalvar (LexState *ls, TString *varname) { FuncState *fs = ls->fs; Proto *f = fs->f; @@ -244,57 +245,11 @@ static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { } -static void lookupvar(LexState *ls, TString *varname, expdesc *var, - int create) -{ - FuncState *fs = ls->fs; - int add_to_table = ls->resolved_table; - int already_added = 0; - lua_State *L = ls->L; - - if (singlevaraux(fs, varname, var, 1) == VGLOBAL) { - int missing; - /* see if it's an existing global provided in native code... */ - lua_getglobal(ls->L, getstr(varname)); - missing = lua_isnil(ls->L, -1); - lua_pop(ls->L, 1); - - if (create) { - int on_line = 0; - if (missing) { - /* see if it's an existing symbol in the user's program. */ - lua_getfield(L, ls->resolved_table, getstr(varname)); - missing = lua_isnil(L, -1); - if (!missing) - on_line = lua_tointeger(L, -1); - lua_pop(L, 1); - } - if (!missing) { - luaX_syntaxerror(ls, - luaO_pushfstring(ls->L, LUA_QS " already defined on line %d", getstr(varname), on_line)); - } - } else { /* add it to a table to resolve after parsing... */ - if (missing) - add_to_table = ls->to_resolve_table; - else - already_added = 1; - } - - if (!already_added) { - lua_getfield(L, add_to_table, getstr(varname)); - already_added = !lua_isnil(L, -1); - lua_pop(L, 1); - if (!already_added) { - lua_pushinteger(L, ls->linenumber); - lua_setfield(L, add_to_table, getstr(varname)); - } - } - var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */ - } -} - static void singlevar (LexState *ls, expdesc *var) { - lookupvar(ls, str_checkname(ls), var, 0); + TString *varname = str_checkname(ls); + FuncState *fs = ls->fs; + if (singlevaraux(fs, varname, var, 1) == VGLOBAL) + var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */ } @@ -424,30 +379,6 @@ static void close_func (LexState *ls) { if (fs) anchor_token(ls); } -static void resolve_toby_functions(LexState *ls) { - lua_State *L = ls->L; - const int to_resolve_table = ls->to_resolve_table; - const int resolved_table = ls->resolved_table; - int missing = 0; - - lua_pushnil(L); /* first key for iteration... */ - while (lua_next(L, to_resolve_table)) { /* replaces key, pushes value. */ - const char *sym = lua_tostring(L, -2); - const int on_line = lua_tointeger(L, -1); - lua_getfield(L, resolved_table, sym); - missing = lua_isnil(L, -1); - lua_pop(L, 1); - - if (missing) { - lua_pop(L, 2); /* remove iterator value and key. */ - luaX_syntaxerror(ls, - luaO_pushfstring(ls->L, "undefined symbol " LUA_QS " on line %d", sym, on_line)); - } - - lua_pop(L, 1); /* remove value, keep key for next iteration. */ - } -} - Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { struct LexState lexstate; @@ -457,13 +388,9 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { open_func(&lexstate, &funcstate); funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */ luaX_next(&lexstate); /* read first token */ - chunk(&lexstate, 1); + chunk(&lexstate); check(&lexstate, TK_EOS); close_func(&lexstate); - resolve_toby_functions(&lexstate); /* we're less dynamic than Lua. :) */ - lua_assert(lexstate.to_resolve_table == lua_gettop(L)-1); - lua_assert(lexstate.resolved_table == lua_gettop(L)); - lua_pop(L, 2); lua_assert(funcstate.prev == NULL); lua_assert(funcstate.f->nups == 0); lua_assert(lexstate.fs == NULL); @@ -476,6 +403,18 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { /* GRAMMAR RULES */ /*============================================================*/ + +static void field (LexState *ls, expdesc *v) { + /* field -> ['.' | ':'] NAME */ + FuncState *fs = ls->fs; + expdesc key; + luaK_exp2anyreg(fs, v); + luaX_next(ls); /* skip the dot or colon */ + checkname(ls, &key); + luaK_indexed(fs, v, &key); +} + + static void yindex (LexState *ls, expdesc *v) { /* index -> '[' expr ']' */ luaX_next(ls); /* skip the '[' */ @@ -485,8 +424,121 @@ static void yindex (LexState *ls, expdesc *v) { } -static void vardeclstat (LexState *ls, int global, int initialize); -static int toby_intrinsic_type(int token, int allownothing); +/* +** {====================================================================== +** 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; + int rkkey; + if (ls->t.token == TK_NAME) { + luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); + checkname(ls, &key); + } + else /* ls->t.token == '[' */ + yindex(ls, &key); + cc->nh++; + checknext(ls, '='); + rkkey = luaK_exp2RK(fs, &key); + expr(ls, &val); + luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val)); + 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_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); /* flush */ + cc->tostore = 0; /* no more items pending */ + } +} + + +static void lastlistfield (FuncState *fs, struct ConsControl *cc) { + if (cc->tostore == 0) return; + if (hasmultret(cc->v.k)) { + luaK_setmultret(fs, &cc->v); + luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET); + cc->na--; /* do not count last expression (unknown number of elements) */ + } + else { + if (cc->v.k != VVOID) + luaK_exp2nextreg(fs, &cc->v); + luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); + } +} + + +static void listfield (LexState *ls, struct ConsControl *cc) { + expr(ls, &cc->v); + luaY_checklimit(ls->fs, cc->na, MAX_INT, "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) */ + checknext(ls, '{'); + do { + lua_assert(cc.v.k == VVOID || cc.tostore > 0); + if (ls->t.token == '}') break; + closelistfield(fs, &cc); + switch(ls->t.token) { + case TK_NAME: { /* may be listfields or recfields */ + luaX_lookahead(ls); + if (ls->lookahead.token != '=') /* expression? */ + listfield(ls, &cc); + else + recfield(ls, &cc); + break; + } + case '[': { /* constructor_item -> recfield */ + recfield(ls, &cc); + break; + } + default: { /* constructor_part -> listfield */ + listfield(ls, &cc); + break; + } + } + } 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_int2fb(cc.nh)); /* set initial table size */ +} + +/* }====================================================================== */ + + static void parlist (LexState *ls) { /* parlist -> [ param { `,' param } ] */ @@ -496,46 +548,46 @@ static void parlist (LexState *ls) { f->is_vararg = 0; if (ls->t.token != ')') { /* is `parlist' not empty? */ do { - vardeclstat(ls, 0, 0); - nparams++; - } while (testnext(ls, ',')); + switch (ls->t.token) { + case TK_NAME: { /* param -> NAME */ + new_localvar(ls, str_checkname(ls), nparams++); + break; + } + case TK_DOTS: { /* param -> `...' */ + luaX_next(ls); +#if defined(LUA_COMPAT_VARARG) + /* use `arg' as default name */ + new_localvarliteral(ls, "arg", nparams++); + f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG; +#endif + f->is_vararg |= VARARG_ISVARARG; + break; + } + default: luaX_syntaxerror(ls, " or " LUA_QL("...") " expected"); + } + } while (!f->is_vararg && testnext(ls, ',')); } + adjustlocalvars(ls, nparams); f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG)); luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ } -static void check_intrinsic_type(LexState *ls, int allownothing) { - const int c = toby_intrinsic_type(ls->t.token, allownothing); - check_condition(ls, c, "data type expected"); -} -static void body (LexState *ls, expdesc *e, int line) { +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; checknext(ls, '('); + if (needself) { + new_localvarliteral(ls, "self", 0); + adjustlocalvars(ls, 1); + } parlist(ls); checknext(ls, ')'); - - checknext(ls, TK_RETURNS); - check_intrinsic_type(ls, 1); - luaX_next(ls); /* !!! FIXME: store return type info somewhere... */ - checknext(ls, TK_EOL); - - /* Toby requires variable predeclaration at the start of a function. */ - /* ...maybe we should change that... */ - skip_blank_lines(ls); - while (toby_intrinsic_type(ls->t.token, 0)) { - vardeclstat(ls, 0, 1); - checknext(ls, TK_EOL); - skip_blank_lines(ls); - } - - chunk(ls, 0); + chunk(ls); new_fs.f->lastlinedefined = ls->linenumber; - check_match(ls, TK_ENDFUNCTION, TK_FUNCTION, line); - checknext(ls, TK_EOL); + check_match(ls, TK_END, TK_FUNCTION, line); close_func(ls); pushclosure(ls, &new_fs, e); } @@ -573,6 +625,15 @@ static void funcargs (LexState *ls, expdesc *f) { check_match(ls, ')', '(', line); break; } + case '{': { /* funcargs -> constructor */ + constructor(ls, &args); + break; + } + case TK_STRING: { /* funcargs -> STRING */ + codestring(ls, &args, ls->t.seminfo.ts); + luaX_next(ls); /* must use `seminfo' before `next' */ + break; + } default: { luaX_syntaxerror(ls, "function arguments expected"); return; @@ -633,6 +694,10 @@ static void primaryexp (LexState *ls, expdesc *v) { prefixexp(ls, v); for (;;) { switch (ls->t.token) { + case '.': { /* field */ + field(ls, v); + break; + } case '[': { /* `[' exp1 `]' */ expdesc key; luaK_exp2anyreg(fs, v); @@ -640,7 +705,15 @@ static void primaryexp (LexState *ls, expdesc *v) { luaK_indexed(fs, v, &key); break; } - case '(': { /* funcargs */ + case ':': { /* `:' NAME funcargs */ + expdesc key; + luaX_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; @@ -655,15 +728,19 @@ static void simpleexp (LexState *ls, expdesc *v) { /* simpleexp -> NUMBER | STRING | NIL | true | false | ... | constructor | FUNCTION body | primaryexp */ switch (ls->t.token) { - case TK_NUMBERLIT: { + case TK_NUMBER: { init_exp(v, VKNUM, 0); v->u.nval = ls->t.seminfo.r; break; } - case TK_STRINGLIT: { + case TK_STRING: { codestring(ls, v, ls->t.seminfo.ts); break; } + case TK_NIL: { + init_exp(v, VNIL, 0); + break; + } case TK_TRUE: { init_exp(v, VTRUE, 0); break; @@ -672,6 +749,23 @@ static void simpleexp (LexState *ls, expdesc *v) { init_exp(v, VFALSE, 0); break; } + case TK_DOTS: { /* vararg */ + FuncState *fs = ls->fs; + check_condition(ls, fs->f->is_vararg, + "cannot use " LUA_QL("...") " outside a vararg function"); + fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */ + init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); + break; + } + case '{': { /* constructor */ + constructor(ls, v); + return; + } + case TK_FUNCTION: { + luaX_next(ls); + body(ls, v, 0, ls->linenumber); + return; + } default: { primaryexp(ls, v); return; @@ -776,29 +870,9 @@ static void expr (LexState *ls, expdesc *v) { static int block_follow (int token) { switch (token) { - case TK_ELSE: - case TK_ELSEIF: - case TK_ENDFUNCTION: - case TK_ENDIF: - case TK_ENDFOR: - case TK_ENDWHILE: - case TK_EOS: - return 1; - default: return 0; - } -} - - -static int toby_intrinsic_type(int token, int allownothing) -{ - switch (token) { - case TK_NUMBER: - case TK_STRING: - case TK_BOOLEAN: - case TK_ARRAY: + case TK_ELSE: case TK_ELSEIF: case TK_END: + case TK_UNTIL: case TK_EOS: return 1; - case TK_NOTHING: - return allownothing ? 1 : 0; default: return 0; } } @@ -809,19 +883,82 @@ static void block (LexState *ls) { FuncState *fs = ls->fs; BlockCnt bl; enterblock(fs, &bl, 0); - chunk(ls, 0); + chunk(ls); lua_assert(bl.breaklist == NO_JUMP); leaveblock(fs); } -static void assignment (LexState *ls, expdesc *v) { - /* Toby form: var = expr */ + +/* +** 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.u.s.info == v->u.s.info) { /* conflict? */ + conflict = 1; + lh->v.u.s.info = extra; /* previous assignment will use safe copy */ + } + if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */ + conflict = 1; + lh->v.u.s.aux = extra; /* previous assignment will use safe copy */ + } + } + } + if (conflict) { + luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.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 <= v->k && v->k <= VINDEXED, "syntax error"); - checknext(ls, '='); - expr(ls, &e); - luaK_setoneret(ls->fs, &e); /* close last expression */ - luaK_storevar(ls->fs, v, &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); + luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, + "variables in assignment"); + assignment(ls, &nv, nvars+1); + } + else { /* assignment -> `=' explist1 */ + int nexps; + checknext(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_setoneret(ls->fs, &e); /* 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); } @@ -834,6 +971,23 @@ static int cond (LexState *ls) { return v.f; } + +static void breakstat (LexState *ls) { + FuncState *fs = ls->fs; + BlockCnt *bl = fs->bl; + int upval = 0; + 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 void whilestat (LexState *ls, int line) { /* whilestat -> WHILE cond DO block END */ FuncState *fs = ls->fs; @@ -843,16 +997,42 @@ static void whilestat (LexState *ls, int line) { luaX_next(ls); /* skip WHILE */ whileinit = luaK_getlabel(fs); condexit = cond(ls); - checknext(ls, TK_EOL); enterblock(fs, &bl, 1); + checknext(ls, TK_DO); block(ls); luaK_patchlist(fs, luaK_jump(fs), whileinit); - check_match(ls, TK_ENDWHILE, TK_WHILE, line); - checknext(ls, TK_EOL); + check_match(ls, TK_END, TK_WHILE, line); leaveblock(fs); luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ } + +static void repeatstat (LexState *ls, int line) { + /* repeatstat -> REPEAT block UNTIL cond */ + int condexit; + FuncState *fs = ls->fs; + int repeat_init = luaK_getlabel(fs); + BlockCnt bl1, bl2; + enterblock(fs, &bl1, 1); /* loop block */ + enterblock(fs, &bl2, 0); /* scope block */ + luaX_next(ls); /* skip REPEAT */ + chunk(ls); + check_match(ls, TK_UNTIL, TK_REPEAT, line); + condexit = cond(ls); /* read condition (inside scope block) */ + if (!bl2.upval) { /* no upvalues? */ + leaveblock(fs); /* finish scope */ + luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */ + } + else { /* complete semantics when there are upvalues */ + breakstat(ls); /* if condition then break */ + luaK_patchtohere(ls->fs, condexit); /* else... */ + leaveblock(fs); /* finish scope... */ + luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */ + } + leaveblock(fs); /* finish loop */ +} + + static int exp1 (LexState *ls) { expdesc e; int k; @@ -862,77 +1042,88 @@ static int exp1 (LexState *ls) { return k; } -static void forstat (LexState *ls, int line) { - /* forstat -> FOR var = exp1 [TO|DOWNTO] exp1 [STEP exp1] block ENDFOR */ - FuncState *fs = ls->fs; - BinOpr op; - expdesc v; - expdesc v1; - expdesc v1copy; - expdesc v1copy2; - expdesc v2; - int base = 0; - int defaultstep = 1; - int whileinit = 0; - int condexit = 0; - BlockCnt bl; - - luaX_next(ls); /* skip `for' */ - singlevar(ls, &v); - memcpy(&v1, &v, sizeof (expdesc)); /* save for later... */ - memcpy(&v1copy, &v1, sizeof (expdesc)); /* for when v1 gets mangled... */ - memcpy(&v1copy2, &v1, sizeof (expdesc)); /* and so on... */ - assignment(ls, &v); - - if (testnext(ls, TK_TO)) { - defaultstep = 1; - } else if (testnext(ls, TK_DOWNTO)) { - defaultstep = -1; - } else { - luaX_syntaxerror(ls, LUA_QL("TO") " or " LUA_QL("DOWNTO") " expected"); - } +static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { + /* forbody -> DO block */ + BlockCnt bl; + FuncState *fs = ls->fs; + int prep, endfor; + adjustlocalvars(ls, 3); /* control variables */ + checknext(ls, TK_DO); + prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs); + enterblock(fs, &bl, 0); /* scope for declared variables */ + adjustlocalvars(ls, nvars); + luaK_reserveregs(fs, nvars); + block(ls); + leaveblock(fs); /* end of scope for declared variables */ + luaK_patchtohere(fs, prep); + endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : + luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); + luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ + luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1); +} - base = fs->freereg; - new_localvarliteral(ls, "(for limit)", 0); - new_localvarliteral(ls, "(for step)", 1); +static void fornum (LexState *ls, TString *varname, int line) { + /* fornum -> NAME = exp1,exp1[,exp1] forbody */ + FuncState *fs = ls->fs; + int base = fs->freereg; + new_localvarliteral(ls, "(for index)", 0); + new_localvarliteral(ls, "(for limit)", 1); + new_localvarliteral(ls, "(for step)", 2); + new_localvar(ls, varname, 3); + checknext(ls, '='); + exp1(ls); /* initial value */ + checknext(ls, ','); exp1(ls); /* limit */ - - if (testnext(ls, TK_STEP)) + if (testnext(ls, ',')) exp1(ls); /* optional step */ - else { /* default step = 1 (or -1 for downto) */ - luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, defaultstep)); + else { /* default step = 1 */ + luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); luaK_reserveregs(fs, 1); } - checknext(ls, TK_EOL); - - adjustlocalvars(ls, 2); /* control variables */ - - whileinit = luaK_getlabel(fs); - - op = ((defaultstep > 0) ? OPR_LE : OPR_GE); - luaK_infix(fs, op, &v1); - init_exp(&v2, VLOCAL, base); - luaK_posfix(fs, op, &v1, &v2); - luaK_goiftrue(fs, &v1); + forbody(ls, base, line, 1, 1); +} - condexit = v1.f; - enterblock(fs, &bl, 1); - block(ls); - check_match(ls, TK_ENDFOR, TK_FOR, line); - checknext(ls, TK_EOL); - op = OPR_ADD; - luaK_infix(fs, OPR_ADD, &v1copy); - init_exp(&v2, VLOCAL, base+1); /* add step value to iterator variable. */ - luaK_posfix(fs, op, &v1copy, &v2); - luaK_storevar(ls->fs, &v1copy2, &v1copy); +static void forlist (LexState *ls, TString *indexname) { + /* forlist -> NAME {,NAME} IN explist1 forbody */ + FuncState *fs = ls->fs; + expdesc e; + int nvars = 0; + int line; + int base = fs->freereg; + /* create control variables */ + new_localvarliteral(ls, "(for generator)", nvars++); + new_localvarliteral(ls, "(for state)", nvars++); + new_localvarliteral(ls, "(for control)", nvars++); + /* create declared variables */ + new_localvar(ls, indexname, nvars++); + while (testnext(ls, ',')) + new_localvar(ls, str_checkname(ls), nvars++); + checknext(ls, TK_IN); + line = ls->linenumber; + adjust_assign(ls, 3, explist1(ls, &e), &e); + luaK_checkstack(fs, 3); /* extra space to call generator */ + forbody(ls, base, line, nvars - 3, 0); +} - luaK_patchlist(fs, luaK_jump(fs), whileinit); - leaveblock(fs); - luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ +static void forstat (LexState *ls, int line) { + /* forstat -> FOR (fornum | forlist) END */ + FuncState *fs = ls->fs; + TString *varname; + BlockCnt bl; + enterblock(fs, &bl, 1); /* scope for loop and control variables */ + luaX_next(ls); /* skip `for' */ + varname = str_checkname(ls); /* first variable name */ + switch (ls->t.token) { + case '=': fornum(ls, varname, line); break; + case ',': case TK_IN: forlist(ls, varname); break; + default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected"); + } + check_match(ls, TK_END, TK_FOR, line); + leaveblock(fs); /* loop scope (`break' jumps to this point) */ } @@ -941,7 +1132,7 @@ static int test_then_block (LexState *ls) { int condexit; luaX_next(ls); /* skip IF or ELSEIF */ condexit = cond(ls); - checknext(ls, TK_EOL); + checknext(ls, TK_THEN); block(ls); /* `then' part */ return condexit; } @@ -962,231 +1153,123 @@ static void ifstat (LexState *ls, int line) { luaK_concat(fs, &escapelist, luaK_jump(fs)); luaK_patchtohere(fs, flist); luaX_next(ls); /* skip ELSE (after patch, for correct line info) */ - checknext(ls, TK_EOL); block(ls); /* `else' part */ } else luaK_concat(fs, &escapelist, flist); luaK_patchtohere(fs, escapelist); - check_match(ls, TK_ENDIF, TK_IF, line); - checknext(ls, TK_EOL); + check_match(ls, TK_END, TK_IF, line); } -static void funcstat (LexState *ls, int line) { - /* funcstat -> FUNCTION funcname body */ +static void localfunc (LexState *ls) { expdesc v, b; - - /* No nested functions in Toby. */ - check_condition(ls, !ls->infunc, "function inside function"); - - ls->infunc = 1; - luaX_next(ls); /* skip FUNCTION */ - lookupvar(ls, str_checkname(ls), &v, 1); - lua_assert(v.k == VGLOBAL); /* All functions are globals in Toby. */ - body(ls, &b, line); - luaK_storevar(ls->fs, &v, &b); - luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ - ls->infunc = 0; -} - -static void default_var_value (LexState *ls, int token, expdesc *e) { - /* Initialize variables with a sane default. */ - if (token == TK_NUMBER) { - init_exp(e, VKNUM, 0); - e->u.nval = 0; - } else if (token == TK_BOOLEAN) { - init_exp(e, VFALSE, 0); - } else if (token == TK_STRING) { - codestring(ls, e, luaX_newstring(ls, "", 0)); - } else { - luaX_syntaxerror(ls, "data type expected"); - } + 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 int check_int_next(LexState *ls) { - /* !!! FIXME: check for floating point... */ - int retval = (int) ls->t.seminfo.r; - checknext(ls, TK_NUMBERLIT); - return retval; -} - -static void build_array_initializer2(LexState *ls, int datatype) { - if (testnext(ls, '[')) { - FuncState *fs = ls->fs; - int base = fs->freereg; - expdesc defval; - expdesc var; - BlockCnt bl1; - BlockCnt bl2; - int lo, hi; - int prep, endfor; - - lo = check_int_next(ls); - checknext(ls, TK_TO); - hi = check_int_next(ls); - checknext(ls, ']'); - /* !!! FIXME: change this error message. */ - check_condition(ls, (lo <= hi), "array is backwards"); - - /* reserve a register for this dimension of the array... */ - enterblock(fs, &bl1, 1); /* scope for declared variables */ - new_localvarliteral(ls, "(array register)", 0); - - /* Create an array in the register... */ - luaK_codeABC(fs, OP_NEWTABLE, base, (hi - lo) + 1, 0); - luaK_reserveregs(fs, 1); - adjustlocalvars(ls, 1); - - /* - * Build for-loop, enter level. - * Largely chopped from original Lua for loop parser... not sure how - * much of this is needed, but OP_FORLOOP expects the locals, etc. - */ - new_localvarliteral(ls, "(for index)", 0); - new_localvarliteral(ls, "(for limit)", 1); - new_localvarliteral(ls, "(for step)", 2); - new_localvarliteral(ls, "(for local)", 3); - - luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, lo)); - luaK_reserveregs(fs, 1); - luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, hi)); - luaK_reserveregs(fs, 1); - luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); - luaK_reserveregs(fs, 1); - adjustlocalvars(ls, 3); /* control variables */ - - prep = luaK_codeAsBx(fs, OP_FORPREP, base+1, NO_JUMP); - enterblock(fs, &bl2, 0); /* scope for declared variables */ - adjustlocalvars(ls, 1); - luaK_reserveregs(fs, 1); - - init_exp(&var, VINDEXED, base); - var.u.s.aux = base+4; - enterlevel(ls); - - /* if token is TK_NAME, loop assigns default value to each index */ - if (ls->t.token == TK_NAME) { - default_var_value(ls, datatype, &defval); - luaK_storevar(fs, &var, &defval); - } else { /* otherwise, go deeper... */ - build_array_initializer2(ls, datatype); - /* !!! FIXME: register (base+5) gets set in the recursion. Scary! */ - luaK_codeABC(fs, OP_SETTABLE, base, base+4, base+5); - } - - leavelevel(ls); - leaveblock(fs); /* end of scope for declared variables */ - luaK_patchtohere(fs, prep); - endfor = luaK_codeAsBx(fs, OP_FORLOOP, base+1, NO_JUMP); - luaK_patchlist(fs, endfor, prep+1); - - leaveblock(fs); /* end of scope for all of this. */ +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 void build_array_initializer(LexState *ls, int datatype, expdesc *e) { - check(ls, '['); - build_array_initializer2(ls, datatype); - /* !!! FIXME: This eats a free'd register! */ - /* !!! FIXME: for now, we'll reserve it, so luaK_storevar() can free it. */ - luaK_reserveregs(ls->fs, 1); - init_exp(e, VLOCAL, ls->fs->freereg-1); -} - -static void vardeclstat (LexState *ls, int global, int initialize) { - /* stat -> INTRINSICTYPE NAME */ - TString *varname = NULL; - int isarray = 0; - expdesc v, e; - int datatype = ls->t.token; - luaX_next(ls); /* skip data type. */ - - if (datatype == TK_ARRAY) { - isarray = 1; - checknext(ls, TK_OF); - datatype = ls->t.token; - luaX_next(ls); - if (initialize) { - build_array_initializer(ls, datatype, &e); - } - } - - /* Prevent symbol clash with the mainline. */ - varname = str_checkname(ls); - check_condition(ls, (strcmp(getstr(varname), TOBY_MAINLINE_FNNAME) != 0), - LUA_QL(TOBY_MAINLINE_FNNAME) " must be a function"); - - if (global) { - lookupvar(ls, varname, &v, 1); - lua_assert(v.k == VGLOBAL); - } else { - new_localvar(ls, varname, 0); +static int funcname (LexState *ls, expdesc *v) { + /* funcname -> NAME {field} [`:' NAME] */ + int needself = 0; + singlevar(ls, v); + while (ls->t.token == '.') + field(ls, v); + if (ls->t.token == ':') { + needself = 1; + field(ls, v); } + return needself; +} - if (initialize) { - if (!isarray) { - if (testnext(ls, '=')) { - expr(ls, &e); - } else { - default_var_value(ls, datatype, &e); - } - } - if (global) { - luaK_storevar(ls->fs, &v, &e); - } else { - adjust_assign(ls, 1, 1, &e); - } - } - if (!global) { - adjustlocalvars(ls, 1); - } +static void funcstat (LexState *ls, int line) { + /* funcstat -> FUNCTION funcname body */ + int needself; + expdesc v, b; + luaX_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; - expdesc v; - primaryexp(ls, &v); - if (v.k == VCALL) /* stat -> func */ - SETARG_C(getcode(fs, &v), 1); /* call statement uses no results */ + struct LHS_assign v; + primaryexp(ls, &v.v); + if (v.v.k == VCALL) /* stat -> func */ + SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ else { /* stat -> assignment */ - assignment(ls, &v); + v.prev = NULL; + assignment(ls, &v, 1); } - checknext(ls, TK_EOL); } static void retstat (LexState *ls) { - /* stat -> RETURN expr */ + /* stat -> RETURN explist */ FuncState *fs = ls->fs; expdesc e; - int first; /* registers with returned values */ + int first, nret; /* registers with returned values */ luaX_next(ls); /* skip RETURN */ - expr(ls, &e); /* return values */ - checknext(ls, TK_EOL); - first = luaK_exp2anyreg(fs, &e); - luaK_ret(fs, first, 1); + if (block_follow(ls->t.token) || ls->t.token == ';') + first = nret = 0; /* return no values */ + else { + nret = explist1(ls, &e); /* optional return values */ + if (hasmultret(e.k)) { + luaK_setmultret(fs, &e); + if (e.k == VCALL && nret == 1) { /* tail call? */ + SET_OPCODE(getcode(fs,&e), OP_TAILCALL); + lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); + } + 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_ret(fs, first, nret); } static int statement (LexState *ls) { int line = ls->linenumber; /* may be needed for error messages */ - - skip_blank_lines(ls); - - /* - * Can't have code outside of a static function in Toby other than a - * function declaration. Mainline code goes into a function called "main", - * like in C. - */ - if (!ls->infunc) - check(ls, TK_FUNCTION); - switch (ls->t.token) { case TK_IF: { /* stat -> ifstat */ ifstat(ls, line); @@ -1196,18 +1279,41 @@ static int statement (LexState *ls) { whilestat(ls, line); return 0; } + case TK_DO: { /* stat -> DO block END */ + luaX_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 */ + luaX_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 */ + luaX_next(ls); /* skip BREAK */ + breakstat(ls); + return 1; /* must be last statement */ + } default: { exprstat(ls); return 0; /* to avoid warnings */ @@ -1216,49 +1322,17 @@ static int statement (LexState *ls) { } -static void chunk (LexState *ls, int mainline) { +static void chunk (LexState *ls) { /* chunk -> { stat [`;'] } */ int islast = 0; enterlevel(ls); - - /* Toby requires global variable predeclaration at the start of the code. */ - if (mainline) { - skip_blank_lines(ls); - while (toby_intrinsic_type(ls->t.token, 0)) { - vardeclstat(ls, 1, 1); - checknext(ls, TK_EOL); - skip_blank_lines(ls); - } - } - - skip_blank_lines(ls); - while (!islast && !block_follow(ls->t.token)) { islast = statement(ls); + testnext(ls, ';'); lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && ls->fs->freereg >= ls->fs->nactvar); ls->fs->freereg = ls->fs->nactvar; /* free registers */ - skip_blank_lines(ls); - } - - /* This is the mainline chunk, so tuck a call to user's main() at the end. */ - if (mainline) { - /* largely cut-and-pasted from funcargs(). This could be cleaned up... */ - const int line = ls->linenumber; - const char *fn = TOBY_MAINLINE_FNNAME; - FuncState *fs = ls->fs; - int base = 0; - int nparams = 0; - expdesc f; - lookupvar(ls, luaX_newstring(ls, fn, strlen(fn)), &f, 0); - luaK_exp2nextreg(fs, &f); - base = f.u.s.info; /* base register for call */ - nparams = fs->freereg - (base+1); - init_exp(&f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); - luaK_fixline(fs, line); - ls->fs->freereg = ls->fs->nactvar; /* free registers */ } - leavelevel(ls); } diff --git a/src/lua/src/lstrlib.c b/src/lua/src/lstrlib.c index ca333ba..1b4763d 100644 --- a/src/lua/src/lstrlib.c +++ b/src/lua/src/lstrlib.c @@ -1,5 +1,5 @@ /* -** $Id: lstrlib.c,v 1.132.1.3 2007/12/28 15:32:23 roberto Exp $ +** $Id: lstrlib.c,v 1.132.1.4 2008/07/11 17:27:21 roberto Exp $ ** Standard library for string operations and pattern-matching ** See Copyright Notice in lua.h */ @@ -35,7 +35,8 @@ static int str_len (lua_State *L) { static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) { /* relative string position: negative means back from end */ - return (pos>=0) ? pos : (ptrdiff_t)len+pos+1; + if (pos < 0) pos += (ptrdiff_t)len + 1; + return (pos >= 0) ? pos : 0; } diff --git a/src/lua/src/ltablib.c b/src/lua/src/ltablib.c index 06f1c37..b6d9cb4 100644 --- a/src/lua/src/ltablib.c +++ b/src/lua/src/ltablib.c @@ -1,5 +1,5 @@ /* -** $Id: ltablib.c,v 1.38.1.2 2007/12/28 15:32:23 roberto Exp $ +** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $ ** Library for Table Manipulation ** See Copyright Notice in lua.h */ @@ -132,6 +132,15 @@ static int tremove (lua_State *L) { } +static void addfield (lua_State *L, luaL_Buffer *b, int i) { + lua_rawgeti(L, 1, i); + if (!lua_isstring(L, -1)) + luaL_error(L, "invalid value (%s) at index %d in table for " + LUA_QL("concat"), luaL_typename(L, -1), i); + luaL_addvalue(b); +} + + static int tconcat (lua_State *L) { luaL_Buffer b; size_t lsep; @@ -141,13 +150,12 @@ static int tconcat (lua_State *L) { i = luaL_optint(L, 3, 1); last = luaL_opt(L, luaL_checkint, 4, luaL_getn(L, 1)); luaL_buffinit(L, &b); - for (; i <= last; i++) { - lua_rawgeti(L, 1, i); - luaL_argcheck(L, lua_isstring(L, -1), 1, "table contains non-strings"); - luaL_addvalue(&b); - if (i != last) - luaL_addlstring(&b, sep, lsep); + for (; i < last; i++) { + addfield(L, &b, i); + luaL_addlstring(&b, sep, lsep); } + if (i == last) /* add last value (if interval was not empty) */ + addfield(L, &b, i); luaL_pushresult(&b); return 1; } diff --git a/src/lua/src/lua.h b/src/lua/src/lua.h index 5bc97b7..e4bdfd3 100644 --- a/src/lua/src/lua.h +++ b/src/lua/src/lua.h @@ -1,5 +1,5 @@ /* -** $Id: lua.h,v 1.218.1.4 2008/01/03 15:41:15 roberto Exp $ +** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $ ** Lua - An Extensible Extension Language ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** See Copyright Notice at the end of this file @@ -17,7 +17,7 @@ #define LUA_VERSION "Lua 5.1" -#define LUA_RELEASE "Lua 5.1.3" +#define LUA_RELEASE "Lua 5.1.4" #define LUA_VERSION_NUM 501 #define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio" #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" diff --git a/src/lua/src/luac.c b/src/lua/src/luac.c index 2307bbf..d070173 100644 --- a/src/lua/src/luac.c +++ b/src/lua/src/luac.c @@ -14,7 +14,6 @@ #include "lua.h" #include "lauxlib.h" -#include "lualib.h" #include "ldo.h" #include "lfunc.h" @@ -163,16 +162,6 @@ static int pmain(lua_State* L) char** argv=s->argv; const Proto* f; int i; - - /* - * Toby needs the standard libraries added even when just compiling, since - * missing globals are considered fatal at parse time, due to the - * requirement to predeclare symbols. - */ - lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */ - luaL_openlibs(L); /* open libraries */ - lua_gc(L, LUA_GCRESTART, 0); - if (!lua_checkstack(L,argc)) fatal("too many input files"); for (i=0; i SHRT_MAX ? SHRT_MAX : LUAI_MCS_AUX) +#define LUAI_MAXCSTACK 8000 diff --git a/src/lua/src/lundump.c b/src/lua/src/lundump.c index 731c064..8010a45 100644 --- a/src/lua/src/lundump.c +++ b/src/lua/src/lundump.c @@ -1,5 +1,5 @@ /* -** $Id: lundump.c,v 2.7.1.2 2008/01/18 16:39:11 roberto Exp $ +** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $ ** load precompiled Lua chunks ** See Copyright Notice in lua.h */ @@ -48,7 +48,6 @@ static void error(LoadState* S, const char* why) static void LoadBlock(LoadState* S, void* b, size_t size) { size_t r=luaZ_read(S->Z,b,size); - UNUSED(r); IF (r!=0, "unexpected end"); } @@ -115,7 +114,7 @@ static void LoadConstants(LoadState* S, Proto* f) setnilvalue(o); break; case LUA_TBOOLEAN: - setbvalue(o,LoadChar(S)); + setbvalue(o,LoadChar(S)!=0); break; case LUA_TNUMBER: setnvalue(o,LoadNumber(S)); @@ -161,7 +160,9 @@ static void LoadDebug(LoadState* S, Proto* f) static Proto* LoadFunction(LoadState* S, TString* p) { - Proto* f=luaF_newproto(S->L); + Proto* f; + if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep"); + f=luaF_newproto(S->L); setptvalue2s(S->L,S->L->top,f); incr_top(S->L); f->source=LoadString(S); if (f->source==NULL) f->source=p; f->linedefined=LoadInt(S); @@ -175,6 +176,7 @@ static Proto* LoadFunction(LoadState* S, TString* p) LoadDebug(S,f); IF (!luaG_checkcode(f), "bad code"); S->L->top--; + S->L->nCcalls--; return f; }