Tamar 0.7.5 → 0.7.6
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitmodules +3 -0
- data/HISTORY +22 -5
- data/Tamar.gemspec +114 -1
- data/VERSION +1 -1
- data/src/lua/CMakeLists.txt +176 -0
- data/src/lua/COPYRIGHT +34 -0
- data/src/lua/FindReadline.cmake +25 -0
- data/src/lua/HISTORY +183 -0
- data/src/lua/INSTALL +99 -0
- data/src/lua/Makefile +128 -0
- data/src/lua/README +46 -0
- data/src/lua/dist.cmake +450 -0
- data/src/lua/dist.info +10 -0
- data/src/lua/doc/amazon.gif +0 -0
- data/src/lua/doc/contents.html +499 -0
- data/src/lua/doc/cover.png +0 -0
- data/src/lua/doc/logo.gif +0 -0
- data/src/lua/doc/lua.1 +163 -0
- data/src/lua/doc/lua.css +41 -0
- data/src/lua/doc/lua.html +172 -0
- data/src/lua/doc/luac.1 +136 -0
- data/src/lua/doc/luac.html +145 -0
- data/src/lua/doc/manual.css +13 -0
- data/src/lua/doc/manual.html +8801 -0
- data/src/lua/doc/readme.html +40 -0
- data/src/lua/etc/Makefile +44 -0
- data/src/lua/etc/README +37 -0
- data/src/lua/etc/all.c +38 -0
- data/src/lua/etc/lua.hpp +9 -0
- data/src/lua/etc/lua.ico +0 -0
- data/src/lua/etc/lua.pc +31 -0
- data/src/lua/etc/luavs.bat +28 -0
- data/src/lua/etc/min.c +39 -0
- data/src/lua/etc/noparser.c +50 -0
- data/src/lua/etc/strict.lua +41 -0
- data/src/lua/src/Makefile +182 -0
- data/src/lua/src/lapi.c +1087 -0
- data/src/lua/src/lapi.h +16 -0
- data/src/lua/src/lauxlib.c +652 -0
- data/src/lua/src/lauxlib.h +174 -0
- data/src/lua/src/lbaselib.c +653 -0
- data/src/lua/src/lcode.c +831 -0
- data/src/lua/src/lcode.h +76 -0
- data/src/lua/src/ldblib.c +398 -0
- data/src/lua/src/ldebug.c +638 -0
- data/src/lua/src/ldebug.h +33 -0
- data/src/lua/src/ldo.c +518 -0
- data/src/lua/src/ldo.h +57 -0
- data/src/lua/src/ldump.c +164 -0
- data/src/lua/src/lfunc.c +174 -0
- data/src/lua/src/lfunc.h +34 -0
- data/src/lua/src/lgc.c +711 -0
- data/src/lua/src/lgc.h +110 -0
- data/src/lua/src/linit.c +38 -0
- data/src/lua/src/liolib.c +556 -0
- data/src/lua/src/llex.c +463 -0
- data/src/lua/src/llex.h +81 -0
- data/src/lua/src/llimits.h +128 -0
- data/src/lua/src/lmathlib.c +263 -0
- data/src/lua/src/lmem.c +86 -0
- data/src/lua/src/lmem.h +49 -0
- data/src/lua/src/loadlib.c +666 -0
- data/src/lua/src/loadlib_rel.c +719 -0
- data/src/lua/src/lobject.c +214 -0
- data/src/lua/src/lobject.h +381 -0
- data/src/lua/src/lopcodes.c +102 -0
- data/src/lua/src/lopcodes.h +268 -0
- data/src/lua/src/loslib.c +243 -0
- data/src/lua/src/lparser.c +1339 -0
- data/src/lua/src/lparser.h +82 -0
- data/src/lua/src/lstate.c +214 -0
- data/src/lua/src/lstate.h +169 -0
- data/src/lua/src/lstring.c +111 -0
- data/src/lua/src/lstring.h +31 -0
- data/src/lua/src/lstrlib.c +871 -0
- data/src/lua/src/ltable.c +588 -0
- data/src/lua/src/ltable.h +40 -0
- data/src/lua/src/ltablib.c +287 -0
- data/src/lua/src/ltm.c +75 -0
- data/src/lua/src/ltm.h +54 -0
- data/src/lua/src/lua.c +392 -0
- data/src/lua/src/lua.def +131 -0
- data/src/lua/src/lua.h +388 -0
- data/src/lua/src/lua.rc +28 -0
- data/src/lua/src/lua_dll.rc +26 -0
- data/src/lua/src/luac.c +200 -0
- data/src/lua/src/luac.rc +1 -0
- data/src/lua/src/luaconf.h.in +724 -0
- data/src/lua/src/luaconf.h.orig +763 -0
- data/src/lua/src/lualib.h +53 -0
- data/src/lua/src/lundump.c +227 -0
- data/src/lua/src/lundump.h +36 -0
- data/src/lua/src/lvm.c +766 -0
- data/src/lua/src/lvm.h +36 -0
- data/src/lua/src/lzio.c +82 -0
- data/src/lua/src/lzio.h +67 -0
- data/src/lua/src/print.c +227 -0
- data/src/lua/test/README +26 -0
- data/src/lua/test/bisect.lua +27 -0
- data/src/lua/test/cf.lua +16 -0
- data/src/lua/test/echo.lua +5 -0
- data/src/lua/test/env.lua +7 -0
- data/src/lua/test/factorial.lua +32 -0
- data/src/lua/test/fib.lua +40 -0
- data/src/lua/test/fibfor.lua +13 -0
- data/src/lua/test/globals.lua +13 -0
- data/src/lua/test/hello.lua +3 -0
- data/src/lua/test/life.lua +111 -0
- data/src/lua/test/luac.lua +7 -0
- data/src/lua/test/printf.lua +7 -0
- data/src/lua/test/readonly.lua +12 -0
- data/src/lua/test/sieve.lua +29 -0
- data/src/lua/test/sort.lua +66 -0
- data/src/lua/test/table.lua +12 -0
- data/src/lua/test/trace-calls.lua +32 -0
- data/src/lua/test/trace-globals.lua +38 -0
- data/src/lua/test/xd.lua +14 -0
- metadata +115 -2
@@ -0,0 +1,268 @@
|
|
1
|
+
/*
|
2
|
+
** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $
|
3
|
+
** Opcodes for Lua virtual machine
|
4
|
+
** See Copyright Notice in lua.h
|
5
|
+
*/
|
6
|
+
|
7
|
+
#ifndef lopcodes_h
|
8
|
+
#define lopcodes_h
|
9
|
+
|
10
|
+
#include "llimits.h"
|
11
|
+
|
12
|
+
|
13
|
+
/*===========================================================================
|
14
|
+
We assume that instructions are unsigned numbers.
|
15
|
+
All instructions have an opcode in the first 6 bits.
|
16
|
+
Instructions can have the following fields:
|
17
|
+
`A' : 8 bits
|
18
|
+
`B' : 9 bits
|
19
|
+
`C' : 9 bits
|
20
|
+
`Bx' : 18 bits (`B' and `C' together)
|
21
|
+
`sBx' : signed Bx
|
22
|
+
|
23
|
+
A signed argument is represented in excess K; that is, the number
|
24
|
+
value is the unsigned value minus K. K is exactly the maximum value
|
25
|
+
for that argument (so that -max is represented by 0, and +max is
|
26
|
+
represented by 2*max), which is half the maximum for the corresponding
|
27
|
+
unsigned argument.
|
28
|
+
===========================================================================*/
|
29
|
+
|
30
|
+
|
31
|
+
enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
|
32
|
+
|
33
|
+
|
34
|
+
/*
|
35
|
+
** size and position of opcode arguments.
|
36
|
+
*/
|
37
|
+
#define SIZE_C 9
|
38
|
+
#define SIZE_B 9
|
39
|
+
#define SIZE_Bx (SIZE_C + SIZE_B)
|
40
|
+
#define SIZE_A 8
|
41
|
+
|
42
|
+
#define SIZE_OP 6
|
43
|
+
|
44
|
+
#define POS_OP 0
|
45
|
+
#define POS_A (POS_OP + SIZE_OP)
|
46
|
+
#define POS_C (POS_A + SIZE_A)
|
47
|
+
#define POS_B (POS_C + SIZE_C)
|
48
|
+
#define POS_Bx POS_C
|
49
|
+
|
50
|
+
|
51
|
+
/*
|
52
|
+
** limits for opcode arguments.
|
53
|
+
** we use (signed) int to manipulate most arguments,
|
54
|
+
** so they must fit in LUAI_BITSINT-1 bits (-1 for sign)
|
55
|
+
*/
|
56
|
+
#if SIZE_Bx < LUAI_BITSINT-1
|
57
|
+
#define MAXARG_Bx ((1<<SIZE_Bx)-1)
|
58
|
+
#define MAXARG_sBx (MAXARG_Bx>>1) /* `sBx' is signed */
|
59
|
+
#else
|
60
|
+
#define MAXARG_Bx MAX_INT
|
61
|
+
#define MAXARG_sBx MAX_INT
|
62
|
+
#endif
|
63
|
+
|
64
|
+
|
65
|
+
#define MAXARG_A ((1<<SIZE_A)-1)
|
66
|
+
#define MAXARG_B ((1<<SIZE_B)-1)
|
67
|
+
#define MAXARG_C ((1<<SIZE_C)-1)
|
68
|
+
|
69
|
+
|
70
|
+
/* creates a mask with `n' 1 bits at position `p' */
|
71
|
+
#define MASK1(n,p) ((~((~(Instruction)0)<<n))<<p)
|
72
|
+
|
73
|
+
/* creates a mask with `n' 0 bits at position `p' */
|
74
|
+
#define MASK0(n,p) (~MASK1(n,p))
|
75
|
+
|
76
|
+
/*
|
77
|
+
** the following macros help to manipulate instructions
|
78
|
+
*/
|
79
|
+
|
80
|
+
#define GET_OPCODE(i) (cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0)))
|
81
|
+
#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \
|
82
|
+
((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP))))
|
83
|
+
|
84
|
+
#define GETARG_A(i) (cast(int, ((i)>>POS_A) & MASK1(SIZE_A,0)))
|
85
|
+
#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \
|
86
|
+
((cast(Instruction, u)<<POS_A)&MASK1(SIZE_A,POS_A))))
|
87
|
+
|
88
|
+
#define GETARG_B(i) (cast(int, ((i)>>POS_B) & MASK1(SIZE_B,0)))
|
89
|
+
#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \
|
90
|
+
((cast(Instruction, b)<<POS_B)&MASK1(SIZE_B,POS_B))))
|
91
|
+
|
92
|
+
#define GETARG_C(i) (cast(int, ((i)>>POS_C) & MASK1(SIZE_C,0)))
|
93
|
+
#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \
|
94
|
+
((cast(Instruction, b)<<POS_C)&MASK1(SIZE_C,POS_C))))
|
95
|
+
|
96
|
+
#define GETARG_Bx(i) (cast(int, ((i)>>POS_Bx) & MASK1(SIZE_Bx,0)))
|
97
|
+
#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \
|
98
|
+
((cast(Instruction, b)<<POS_Bx)&MASK1(SIZE_Bx,POS_Bx))))
|
99
|
+
|
100
|
+
#define GETARG_sBx(i) (GETARG_Bx(i)-MAXARG_sBx)
|
101
|
+
#define SETARG_sBx(i,b) SETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx))
|
102
|
+
|
103
|
+
|
104
|
+
#define CREATE_ABC(o,a,b,c) ((cast(Instruction, o)<<POS_OP) \
|
105
|
+
| (cast(Instruction, a)<<POS_A) \
|
106
|
+
| (cast(Instruction, b)<<POS_B) \
|
107
|
+
| (cast(Instruction, c)<<POS_C))
|
108
|
+
|
109
|
+
#define CREATE_ABx(o,a,bc) ((cast(Instruction, o)<<POS_OP) \
|
110
|
+
| (cast(Instruction, a)<<POS_A) \
|
111
|
+
| (cast(Instruction, bc)<<POS_Bx))
|
112
|
+
|
113
|
+
|
114
|
+
/*
|
115
|
+
** Macros to operate RK indices
|
116
|
+
*/
|
117
|
+
|
118
|
+
/* this bit 1 means constant (0 means register) */
|
119
|
+
#define BITRK (1 << (SIZE_B - 1))
|
120
|
+
|
121
|
+
/* test whether value is a constant */
|
122
|
+
#define ISK(x) ((x) & BITRK)
|
123
|
+
|
124
|
+
/* gets the index of the constant */
|
125
|
+
#define INDEXK(r) ((int)(r) & ~BITRK)
|
126
|
+
|
127
|
+
#define MAXINDEXRK (BITRK - 1)
|
128
|
+
|
129
|
+
/* code a constant index as a RK value */
|
130
|
+
#define RKASK(x) ((x) | BITRK)
|
131
|
+
|
132
|
+
|
133
|
+
/*
|
134
|
+
** invalid register that fits in 8 bits
|
135
|
+
*/
|
136
|
+
#define NO_REG MAXARG_A
|
137
|
+
|
138
|
+
|
139
|
+
/*
|
140
|
+
** R(x) - register
|
141
|
+
** Kst(x) - constant (in constant table)
|
142
|
+
** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)
|
143
|
+
*/
|
144
|
+
|
145
|
+
|
146
|
+
/*
|
147
|
+
** grep "ORDER OP" if you change these enums
|
148
|
+
*/
|
149
|
+
|
150
|
+
typedef enum {
|
151
|
+
/*----------------------------------------------------------------------
|
152
|
+
name args description
|
153
|
+
------------------------------------------------------------------------*/
|
154
|
+
OP_MOVE,/* A B R(A) := R(B) */
|
155
|
+
OP_LOADK,/* A Bx R(A) := Kst(Bx) */
|
156
|
+
OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */
|
157
|
+
OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */
|
158
|
+
OP_GETUPVAL,/* A B R(A) := UpValue[B] */
|
159
|
+
|
160
|
+
OP_GETGLOBAL,/* A Bx R(A) := Gbl[Kst(Bx)] */
|
161
|
+
OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */
|
162
|
+
|
163
|
+
OP_SETGLOBAL,/* A Bx Gbl[Kst(Bx)] := R(A) */
|
164
|
+
OP_SETUPVAL,/* A B UpValue[B] := R(A) */
|
165
|
+
OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */
|
166
|
+
|
167
|
+
OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */
|
168
|
+
|
169
|
+
OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
|
170
|
+
|
171
|
+
OP_ADD,/* A B C R(A) := RK(B) + RK(C) */
|
172
|
+
OP_SUB,/* A B C R(A) := RK(B) - RK(C) */
|
173
|
+
OP_MUL,/* A B C R(A) := RK(B) * RK(C) */
|
174
|
+
OP_DIV,/* A B C R(A) := RK(B) / RK(C) */
|
175
|
+
OP_MOD,/* A B C R(A) := RK(B) % RK(C) */
|
176
|
+
OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */
|
177
|
+
OP_UNM,/* A B R(A) := -R(B) */
|
178
|
+
OP_NOT,/* A B R(A) := not R(B) */
|
179
|
+
OP_LEN,/* A B R(A) := length of R(B) */
|
180
|
+
|
181
|
+
OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */
|
182
|
+
|
183
|
+
OP_JMP,/* sBx pc+=sBx */
|
184
|
+
|
185
|
+
OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
|
186
|
+
OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
|
187
|
+
OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
|
188
|
+
|
189
|
+
OP_TEST,/* A C if not (R(A) <=> C) then pc++ */
|
190
|
+
OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
|
191
|
+
|
192
|
+
OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
|
193
|
+
OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
|
194
|
+
OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */
|
195
|
+
|
196
|
+
OP_FORLOOP,/* A sBx R(A)+=R(A+2);
|
197
|
+
if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
|
198
|
+
OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */
|
199
|
+
|
200
|
+
OP_TFORLOOP,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
|
201
|
+
if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++ */
|
202
|
+
OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
|
203
|
+
|
204
|
+
OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/
|
205
|
+
OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
|
206
|
+
|
207
|
+
OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
|
208
|
+
} OpCode;
|
209
|
+
|
210
|
+
|
211
|
+
#define NUM_OPCODES (cast(int, OP_VARARG) + 1)
|
212
|
+
|
213
|
+
|
214
|
+
|
215
|
+
/*===========================================================================
|
216
|
+
Notes:
|
217
|
+
(*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
|
218
|
+
and can be 0: OP_CALL then sets `top' to last_result+1, so
|
219
|
+
next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'.
|
220
|
+
|
221
|
+
(*) In OP_VARARG, if (B == 0) then use actual number of varargs and
|
222
|
+
set top (like in OP_CALL with C == 0).
|
223
|
+
|
224
|
+
(*) In OP_RETURN, if (B == 0) then return up to `top'
|
225
|
+
|
226
|
+
(*) In OP_SETLIST, if (B == 0) then B = `top';
|
227
|
+
if (C == 0) then next `instruction' is real C
|
228
|
+
|
229
|
+
(*) For comparisons, A specifies what condition the test should accept
|
230
|
+
(true or false).
|
231
|
+
|
232
|
+
(*) All `skips' (pc++) assume that next instruction is a jump
|
233
|
+
===========================================================================*/
|
234
|
+
|
235
|
+
|
236
|
+
/*
|
237
|
+
** masks for instruction properties. The format is:
|
238
|
+
** bits 0-1: op mode
|
239
|
+
** bits 2-3: C arg mode
|
240
|
+
** bits 4-5: B arg mode
|
241
|
+
** bit 6: instruction set register A
|
242
|
+
** bit 7: operator is a test
|
243
|
+
*/
|
244
|
+
|
245
|
+
enum OpArgMask {
|
246
|
+
OpArgN, /* argument is not used */
|
247
|
+
OpArgU, /* argument is used */
|
248
|
+
OpArgR, /* argument is a register or a jump offset */
|
249
|
+
OpArgK /* argument is a constant or register/constant */
|
250
|
+
};
|
251
|
+
|
252
|
+
LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES];
|
253
|
+
|
254
|
+
#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3))
|
255
|
+
#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3))
|
256
|
+
#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3))
|
257
|
+
#define testAMode(m) (luaP_opmodes[m] & (1 << 6))
|
258
|
+
#define testTMode(m) (luaP_opmodes[m] & (1 << 7))
|
259
|
+
|
260
|
+
|
261
|
+
LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */
|
262
|
+
|
263
|
+
|
264
|
+
/* number of list items to accumulate before a SETLIST instruction */
|
265
|
+
#define LFIELDS_PER_FLUSH 50
|
266
|
+
|
267
|
+
|
268
|
+
#endif
|
@@ -0,0 +1,243 @@
|
|
1
|
+
/*
|
2
|
+
** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $
|
3
|
+
** Standard Operating System library
|
4
|
+
** See Copyright Notice in lua.h
|
5
|
+
*/
|
6
|
+
|
7
|
+
|
8
|
+
#include <errno.h>
|
9
|
+
#include <locale.h>
|
10
|
+
#include <stdlib.h>
|
11
|
+
#include <string.h>
|
12
|
+
#include <time.h>
|
13
|
+
|
14
|
+
#define loslib_c
|
15
|
+
#define LUA_LIB
|
16
|
+
|
17
|
+
#include "lua.h"
|
18
|
+
|
19
|
+
#include "lauxlib.h"
|
20
|
+
#include "lualib.h"
|
21
|
+
|
22
|
+
|
23
|
+
static int os_pushresult (lua_State *L, int i, const char *filename) {
|
24
|
+
int en = errno; /* calls to Lua API may change this value */
|
25
|
+
if (i) {
|
26
|
+
lua_pushboolean(L, 1);
|
27
|
+
return 1;
|
28
|
+
}
|
29
|
+
else {
|
30
|
+
lua_pushnil(L);
|
31
|
+
lua_pushfstring(L, "%s: %s", filename, strerror(en));
|
32
|
+
lua_pushinteger(L, en);
|
33
|
+
return 3;
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
|
38
|
+
static int os_execute (lua_State *L) {
|
39
|
+
lua_pushinteger(L, system(luaL_optstring(L, 1, NULL)));
|
40
|
+
return 1;
|
41
|
+
}
|
42
|
+
|
43
|
+
|
44
|
+
static int os_remove (lua_State *L) {
|
45
|
+
const char *filename = luaL_checkstring(L, 1);
|
46
|
+
return os_pushresult(L, remove(filename) == 0, filename);
|
47
|
+
}
|
48
|
+
|
49
|
+
|
50
|
+
static int os_rename (lua_State *L) {
|
51
|
+
const char *fromname = luaL_checkstring(L, 1);
|
52
|
+
const char *toname = luaL_checkstring(L, 2);
|
53
|
+
return os_pushresult(L, rename(fromname, toname) == 0, fromname);
|
54
|
+
}
|
55
|
+
|
56
|
+
|
57
|
+
static int os_tmpname (lua_State *L) {
|
58
|
+
char buff[LUA_TMPNAMBUFSIZE];
|
59
|
+
int err;
|
60
|
+
lua_tmpnam(buff, err);
|
61
|
+
if (err)
|
62
|
+
return luaL_error(L, "unable to generate a unique filename");
|
63
|
+
lua_pushstring(L, buff);
|
64
|
+
return 1;
|
65
|
+
}
|
66
|
+
|
67
|
+
|
68
|
+
static int os_getenv (lua_State *L) {
|
69
|
+
lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */
|
70
|
+
return 1;
|
71
|
+
}
|
72
|
+
|
73
|
+
|
74
|
+
static int os_clock (lua_State *L) {
|
75
|
+
lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC);
|
76
|
+
return 1;
|
77
|
+
}
|
78
|
+
|
79
|
+
|
80
|
+
/*
|
81
|
+
** {======================================================
|
82
|
+
** Time/Date operations
|
83
|
+
** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,
|
84
|
+
** wday=%w+1, yday=%j, isdst=? }
|
85
|
+
** =======================================================
|
86
|
+
*/
|
87
|
+
|
88
|
+
static void setfield (lua_State *L, const char *key, int value) {
|
89
|
+
lua_pushinteger(L, value);
|
90
|
+
lua_setfield(L, -2, key);
|
91
|
+
}
|
92
|
+
|
93
|
+
static void setboolfield (lua_State *L, const char *key, int value) {
|
94
|
+
if (value < 0) /* undefined? */
|
95
|
+
return; /* does not set field */
|
96
|
+
lua_pushboolean(L, value);
|
97
|
+
lua_setfield(L, -2, key);
|
98
|
+
}
|
99
|
+
|
100
|
+
static int getboolfield (lua_State *L, const char *key) {
|
101
|
+
int res;
|
102
|
+
lua_getfield(L, -1, key);
|
103
|
+
res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1);
|
104
|
+
lua_pop(L, 1);
|
105
|
+
return res;
|
106
|
+
}
|
107
|
+
|
108
|
+
|
109
|
+
static int getfield (lua_State *L, const char *key, int d) {
|
110
|
+
int res;
|
111
|
+
lua_getfield(L, -1, key);
|
112
|
+
if (lua_isnumber(L, -1))
|
113
|
+
res = (int)lua_tointeger(L, -1);
|
114
|
+
else {
|
115
|
+
if (d < 0)
|
116
|
+
return luaL_error(L, "field " LUA_QS " missing in date table", key);
|
117
|
+
res = d;
|
118
|
+
}
|
119
|
+
lua_pop(L, 1);
|
120
|
+
return res;
|
121
|
+
}
|
122
|
+
|
123
|
+
|
124
|
+
static int os_date (lua_State *L) {
|
125
|
+
const char *s = luaL_optstring(L, 1, "%c");
|
126
|
+
time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL));
|
127
|
+
struct tm *stm;
|
128
|
+
if (*s == '!') { /* UTC? */
|
129
|
+
stm = gmtime(&t);
|
130
|
+
s++; /* skip `!' */
|
131
|
+
}
|
132
|
+
else
|
133
|
+
stm = localtime(&t);
|
134
|
+
if (stm == NULL) /* invalid date? */
|
135
|
+
lua_pushnil(L);
|
136
|
+
else if (strcmp(s, "*t") == 0) {
|
137
|
+
lua_createtable(L, 0, 9); /* 9 = number of fields */
|
138
|
+
setfield(L, "sec", stm->tm_sec);
|
139
|
+
setfield(L, "min", stm->tm_min);
|
140
|
+
setfield(L, "hour", stm->tm_hour);
|
141
|
+
setfield(L, "day", stm->tm_mday);
|
142
|
+
setfield(L, "month", stm->tm_mon+1);
|
143
|
+
setfield(L, "year", stm->tm_year+1900);
|
144
|
+
setfield(L, "wday", stm->tm_wday+1);
|
145
|
+
setfield(L, "yday", stm->tm_yday+1);
|
146
|
+
setboolfield(L, "isdst", stm->tm_isdst);
|
147
|
+
}
|
148
|
+
else {
|
149
|
+
char cc[3];
|
150
|
+
luaL_Buffer b;
|
151
|
+
cc[0] = '%'; cc[2] = '\0';
|
152
|
+
luaL_buffinit(L, &b);
|
153
|
+
for (; *s; s++) {
|
154
|
+
if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */
|
155
|
+
luaL_addchar(&b, *s);
|
156
|
+
else {
|
157
|
+
size_t reslen;
|
158
|
+
char buff[200]; /* should be big enough for any conversion result */
|
159
|
+
cc[1] = *(++s);
|
160
|
+
reslen = strftime(buff, sizeof(buff), cc, stm);
|
161
|
+
luaL_addlstring(&b, buff, reslen);
|
162
|
+
}
|
163
|
+
}
|
164
|
+
luaL_pushresult(&b);
|
165
|
+
}
|
166
|
+
return 1;
|
167
|
+
}
|
168
|
+
|
169
|
+
|
170
|
+
static int os_time (lua_State *L) {
|
171
|
+
time_t t;
|
172
|
+
if (lua_isnoneornil(L, 1)) /* called without args? */
|
173
|
+
t = time(NULL); /* get current time */
|
174
|
+
else {
|
175
|
+
struct tm ts;
|
176
|
+
luaL_checktype(L, 1, LUA_TTABLE);
|
177
|
+
lua_settop(L, 1); /* make sure table is at the top */
|
178
|
+
ts.tm_sec = getfield(L, "sec", 0);
|
179
|
+
ts.tm_min = getfield(L, "min", 0);
|
180
|
+
ts.tm_hour = getfield(L, "hour", 12);
|
181
|
+
ts.tm_mday = getfield(L, "day", -1);
|
182
|
+
ts.tm_mon = getfield(L, "month", -1) - 1;
|
183
|
+
ts.tm_year = getfield(L, "year", -1) - 1900;
|
184
|
+
ts.tm_isdst = getboolfield(L, "isdst");
|
185
|
+
t = mktime(&ts);
|
186
|
+
}
|
187
|
+
if (t == (time_t)(-1))
|
188
|
+
lua_pushnil(L);
|
189
|
+
else
|
190
|
+
lua_pushnumber(L, (lua_Number)t);
|
191
|
+
return 1;
|
192
|
+
}
|
193
|
+
|
194
|
+
|
195
|
+
static int os_difftime (lua_State *L) {
|
196
|
+
lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
|
197
|
+
(time_t)(luaL_optnumber(L, 2, 0))));
|
198
|
+
return 1;
|
199
|
+
}
|
200
|
+
|
201
|
+
/* }====================================================== */
|
202
|
+
|
203
|
+
|
204
|
+
static int os_setlocale (lua_State *L) {
|
205
|
+
static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,
|
206
|
+
LC_NUMERIC, LC_TIME};
|
207
|
+
static const char *const catnames[] = {"all", "collate", "ctype", "monetary",
|
208
|
+
"numeric", "time", NULL};
|
209
|
+
const char *l = luaL_optstring(L, 1, NULL);
|
210
|
+
int op = luaL_checkoption(L, 2, "all", catnames);
|
211
|
+
lua_pushstring(L, setlocale(cat[op], l));
|
212
|
+
return 1;
|
213
|
+
}
|
214
|
+
|
215
|
+
|
216
|
+
static int os_exit (lua_State *L) {
|
217
|
+
exit(luaL_optint(L, 1, EXIT_SUCCESS));
|
218
|
+
}
|
219
|
+
|
220
|
+
static const luaL_Reg syslib[] = {
|
221
|
+
{"clock", os_clock},
|
222
|
+
{"date", os_date},
|
223
|
+
{"difftime", os_difftime},
|
224
|
+
{"execute", os_execute},
|
225
|
+
{"exit", os_exit},
|
226
|
+
{"getenv", os_getenv},
|
227
|
+
{"remove", os_remove},
|
228
|
+
{"rename", os_rename},
|
229
|
+
{"setlocale", os_setlocale},
|
230
|
+
{"time", os_time},
|
231
|
+
{"tmpname", os_tmpname},
|
232
|
+
{NULL, NULL}
|
233
|
+
};
|
234
|
+
|
235
|
+
/* }====================================================== */
|
236
|
+
|
237
|
+
|
238
|
+
|
239
|
+
LUALIB_API int luaopen_os (lua_State *L) {
|
240
|
+
luaL_register(L, LUA_OSLIBNAME, syslib);
|
241
|
+
return 1;
|
242
|
+
}
|
243
|
+
|