diff options
Diffstat (limited to 'liolib.c')
-rw-r--r-- | liolib.c | 359 |
1 files changed, 359 insertions, 0 deletions
diff --git a/liolib.c b/liolib.c new file mode 100644 index 00000000..f44a1f76 --- /dev/null +++ b/liolib.c | |||
@@ -0,0 +1,359 @@ | |||
1 | /* | ||
2 | ** $Id: $ | ||
3 | ** Standard I/O (and system) library | ||
4 | ** See Copyright Notice in lua.h | ||
5 | */ | ||
6 | |||
7 | |||
8 | #include <stdio.h> | ||
9 | #include <string.h> | ||
10 | #include <time.h> | ||
11 | #include <stdlib.h> | ||
12 | #include <errno.h> | ||
13 | |||
14 | #include "lauxlib.h" | ||
15 | #include "lua.h" | ||
16 | #include "luadebug.h" | ||
17 | #include "lualib.h" | ||
18 | |||
19 | |||
20 | #ifndef OLD_ANSI | ||
21 | #include <locale.h> | ||
22 | #else | ||
23 | #define strcoll(a,b) strcmp(a,b) | ||
24 | #define setlocale(a,b) 0 | ||
25 | #define LC_ALL 0 | ||
26 | #define LC_COLLATE 0 | ||
27 | #define LC_CTYPE 0 | ||
28 | #define LC_MONETARY 0 | ||
29 | #define LC_NUMERIC 0 | ||
30 | #define LC_TIME 0 | ||
31 | #define strerror(e) "O.S. is unable to define the error" | ||
32 | #endif | ||
33 | |||
34 | |||
35 | #ifdef POPEN | ||
36 | FILE *popen(); | ||
37 | int pclose(); | ||
38 | #else | ||
39 | #define popen(x,y) NULL /* that is, popen always fails */ | ||
40 | #define pclose(x) (-1) | ||
41 | #endif | ||
42 | |||
43 | |||
44 | int lua_tagio; | ||
45 | |||
46 | |||
47 | static void pushresult (int i) | ||
48 | { | ||
49 | if (i) | ||
50 | lua_pushuserdata(NULL); | ||
51 | else { | ||
52 | lua_pushnil(); | ||
53 | lua_pushstring(strerror(errno)); | ||
54 | } | ||
55 | } | ||
56 | |||
57 | |||
58 | |||
59 | static FILE *getfile (char *name) | ||
60 | { | ||
61 | lua_Object f = lua_getglobal(name); | ||
62 | if (!lua_isuserdata(f) || lua_tag(f) != lua_tagio) | ||
63 | luaL_verror("global variable %s is not a file handle", name); | ||
64 | return lua_getuserdata(f); | ||
65 | } | ||
66 | |||
67 | |||
68 | static void closefile (char *name) | ||
69 | { | ||
70 | FILE *f = getfile(name); | ||
71 | if (f == stdin || f == stdout) return; | ||
72 | if (pclose(f) == -1) | ||
73 | fclose(f); | ||
74 | } | ||
75 | |||
76 | |||
77 | static void setfile (FILE *f, char *name) | ||
78 | { | ||
79 | lua_pushusertag(f, lua_tagio); | ||
80 | lua_setglobal(name); | ||
81 | } | ||
82 | |||
83 | |||
84 | static void setreturn (FILE *f, char *name) | ||
85 | { | ||
86 | setfile(f, name); | ||
87 | lua_pushusertag(f, lua_tagio); | ||
88 | } | ||
89 | |||
90 | |||
91 | static void io_readfrom (void) | ||
92 | { | ||
93 | FILE *current; | ||
94 | lua_Object f = lua_getparam(1); | ||
95 | if (f == LUA_NOOBJECT) { | ||
96 | closefile("_INPUT"); | ||
97 | current = stdin; | ||
98 | } | ||
99 | else if (lua_tag(f) == lua_tagio) | ||
100 | current = lua_getuserdata(f); | ||
101 | else { | ||
102 | char *s = luaL_check_string(1); | ||
103 | current = (*s == '|') ? popen(s+1, "r") : fopen(s, "r"); | ||
104 | if (current == NULL) { | ||
105 | pushresult(0); | ||
106 | return; | ||
107 | } | ||
108 | } | ||
109 | setreturn(current, "_INPUT"); | ||
110 | } | ||
111 | |||
112 | |||
113 | static void io_writeto (void) | ||
114 | { | ||
115 | FILE *current; | ||
116 | lua_Object f = lua_getparam(1); | ||
117 | if (f == LUA_NOOBJECT) { | ||
118 | closefile("_OUTPUT"); | ||
119 | current = stdout; | ||
120 | } | ||
121 | else if (lua_tag(f) == lua_tagio) | ||
122 | current = lua_getuserdata(f); | ||
123 | else { | ||
124 | char *s = luaL_check_string(1); | ||
125 | current = (*s == '|') ? popen(s+1,"w") : fopen(s,"w"); | ||
126 | if (current == NULL) { | ||
127 | pushresult(0); | ||
128 | return; | ||
129 | } | ||
130 | } | ||
131 | setreturn(current, "_OUTPUT"); | ||
132 | } | ||
133 | |||
134 | |||
135 | static void io_appendto (void) | ||
136 | { | ||
137 | char *s = luaL_check_string(1); | ||
138 | FILE *fp = fopen (s, "a"); | ||
139 | if (fp != NULL) | ||
140 | setreturn(fp, "_OUTPUT"); | ||
141 | else | ||
142 | pushresult(0); | ||
143 | } | ||
144 | |||
145 | |||
146 | #define NEED_OTHER (EOF-1) /* just some flag different from EOF */ | ||
147 | |||
148 | static void io_read (void) | ||
149 | { | ||
150 | FILE *f = getfile("_INPUT"); | ||
151 | char *buff; | ||
152 | char *p = luaL_opt_string(1, "[^\n]*{\n}"); | ||
153 | int inskip = 0; /* to control {skips} */ | ||
154 | int c = NEED_OTHER; | ||
155 | luaI_emptybuff(); | ||
156 | while (*p) { | ||
157 | if (*p == '{') { | ||
158 | inskip++; | ||
159 | p++; | ||
160 | } | ||
161 | else if (*p == '}') { | ||
162 | if (inskip == 0) | ||
163 | lua_error("unbalanced braces in read pattern"); | ||
164 | inskip--; | ||
165 | p++; | ||
166 | } | ||
167 | else { | ||
168 | char *ep; /* get what is next */ | ||
169 | int m; /* match result */ | ||
170 | if (c == NEED_OTHER) c = getc(f); | ||
171 | m = luaI_singlematch((c == EOF) ? 0 : (char)c, p, &ep); | ||
172 | if (m) { | ||
173 | if (inskip == 0) luaI_addchar(c); | ||
174 | c = NEED_OTHER; | ||
175 | } | ||
176 | switch (*ep) { | ||
177 | case '*': /* repetition */ | ||
178 | if (!m) p = ep+1; /* else stay in (repeat) the same item */ | ||
179 | break; | ||
180 | case '?': /* optional */ | ||
181 | p = ep+1; /* continues reading the pattern */ | ||
182 | break; | ||
183 | default: | ||
184 | if (m) p = ep; /* continues reading the pattern */ | ||
185 | else | ||
186 | goto break_while; /* pattern fails */ | ||
187 | } | ||
188 | } | ||
189 | } break_while: | ||
190 | if (c >= 0) /* not EOF nor NEED_OTHER? */ | ||
191 | ungetc(c, f); | ||
192 | buff = luaI_addchar(0); | ||
193 | if (*buff != 0 || *p == 0) /* read something or did not fail? */ | ||
194 | lua_pushstring(buff); | ||
195 | } | ||
196 | |||
197 | |||
198 | static void io_write (void) | ||
199 | { | ||
200 | FILE *f = getfile("_OUTPUT"); | ||
201 | int arg = 1; | ||
202 | int status = 1; | ||
203 | char *s; | ||
204 | while ((s = luaL_opt_string(arg++, NULL)) != NULL) | ||
205 | status = status && (fputs(s, f) != EOF); | ||
206 | pushresult(status); | ||
207 | } | ||
208 | |||
209 | |||
210 | static void io_execute (void) | ||
211 | { | ||
212 | lua_pushnumber(system(luaL_check_string(1))); | ||
213 | } | ||
214 | |||
215 | |||
216 | static void io_remove (void) | ||
217 | { | ||
218 | pushresult(remove(luaL_check_string(1)) == 0); | ||
219 | } | ||
220 | |||
221 | |||
222 | static void io_rename (void) | ||
223 | { | ||
224 | pushresult(rename(luaL_check_string(1), | ||
225 | luaL_check_string(2)) == 0); | ||
226 | } | ||
227 | |||
228 | |||
229 | static void io_tmpname (void) | ||
230 | { | ||
231 | lua_pushstring(tmpnam(NULL)); | ||
232 | } | ||
233 | |||
234 | |||
235 | |||
236 | static void io_getenv (void) | ||
237 | { | ||
238 | lua_pushstring(getenv(luaL_check_string(1))); /* if NULL push nil */ | ||
239 | } | ||
240 | |||
241 | |||
242 | static void io_date (void) | ||
243 | { | ||
244 | time_t t; | ||
245 | struct tm *tm; | ||
246 | char *s = luaL_opt_string(1, "%c"); | ||
247 | char b[BUFSIZ]; | ||
248 | time(&t); tm = localtime(&t); | ||
249 | if (strftime(b,sizeof(b),s,tm)) | ||
250 | lua_pushstring(b); | ||
251 | else | ||
252 | lua_error("invalid `date' format"); | ||
253 | } | ||
254 | |||
255 | |||
256 | static void setloc (void) | ||
257 | { | ||
258 | static int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, | ||
259 | LC_TIME}; | ||
260 | int op = (int)luaL_opt_number(2, 0); | ||
261 | luaL_arg_check(0 <= op && op <= 5, 2, "invalid option"); | ||
262 | lua_pushstring(setlocale(cat[op], luaL_check_string(1))); | ||
263 | } | ||
264 | |||
265 | |||
266 | static void io_exit (void) | ||
267 | { | ||
268 | lua_Object o = lua_getparam(1); | ||
269 | exit(lua_isnumber(o) ? (int)lua_getnumber(o) : 1); | ||
270 | } | ||
271 | |||
272 | |||
273 | static void io_debug (void) | ||
274 | { | ||
275 | while (1) { | ||
276 | char buffer[250]; | ||
277 | fprintf(stderr, "lua_debug> "); | ||
278 | if (fgets(buffer, sizeof(buffer), stdin) == 0) return; | ||
279 | if (strcmp(buffer, "cont\n") == 0) return; | ||
280 | lua_dostring(buffer); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | |||
285 | static void lua_printstack (FILE *f) | ||
286 | { | ||
287 | int level = 1; /* skip level 0 (it's this function) */ | ||
288 | lua_Object func; | ||
289 | while ((func = lua_stackedfunction(level++)) != LUA_NOOBJECT) { | ||
290 | char *name; | ||
291 | int currentline; | ||
292 | char *filename; | ||
293 | int linedefined; | ||
294 | lua_funcinfo(func, &filename, &linedefined); | ||
295 | fprintf(f, (level==2) ? "Active Stack:\n\t" : "\t"); | ||
296 | switch (*lua_getobjname(func, &name)) { | ||
297 | case 'g': | ||
298 | fprintf(f, "function %s", name); | ||
299 | break; | ||
300 | case 't': | ||
301 | fprintf(f, "`%s' tag method", name); | ||
302 | break; | ||
303 | default: { | ||
304 | if (linedefined == 0) | ||
305 | fprintf(f, "main of %s", filename); | ||
306 | else if (linedefined < 0) | ||
307 | fprintf(f, "%s", filename); | ||
308 | else | ||
309 | fprintf(f, "function (%s:%d)", filename, linedefined); | ||
310 | filename = NULL; | ||
311 | } | ||
312 | } | ||
313 | if ((currentline = lua_currentline(func)) > 0) | ||
314 | fprintf(f, " at line %d", currentline); | ||
315 | if (filename) | ||
316 | fprintf(f, " [in file %s]", filename); | ||
317 | fprintf(f, "\n"); | ||
318 | } | ||
319 | } | ||
320 | |||
321 | |||
322 | static void errorfb (void) | ||
323 | { | ||
324 | fprintf(stderr, "lua: %s\n", lua_getstring(lua_getparam(1))); | ||
325 | lua_printstack(stderr); | ||
326 | } | ||
327 | |||
328 | |||
329 | |||
330 | static struct luaL_reg iolib[] = { | ||
331 | {"setlocale", setloc}, | ||
332 | {"readfrom", io_readfrom}, | ||
333 | {"writeto", io_writeto}, | ||
334 | {"appendto", io_appendto}, | ||
335 | {"read", io_read}, | ||
336 | {"write", io_write}, | ||
337 | {"execute", io_execute}, | ||
338 | {"remove", io_remove}, | ||
339 | {"rename", io_rename}, | ||
340 | {"tmpname", io_tmpname}, | ||
341 | {"getenv", io_getenv}, | ||
342 | {"date", io_date}, | ||
343 | {"exit", io_exit}, | ||
344 | {"debug", io_debug}, | ||
345 | {"print_stack", errorfb} | ||
346 | }; | ||
347 | |||
348 | void lua_iolibopen (void) | ||
349 | { | ||
350 | lua_tagio = lua_newtag(); | ||
351 | setfile(stdin, "_INPUT"); | ||
352 | setfile(stdout, "_OUTPUT"); | ||
353 | setfile(stdin, "_STDIN"); | ||
354 | setfile(stdout, "_STDOUT"); | ||
355 | setfile(stderr, "_STDERR"); | ||
356 | luaL_openlib(iolib, (sizeof(iolib)/sizeof(iolib[0]))); | ||
357 | lua_pushcfunction(errorfb); | ||
358 | lua_seterrormethod(); | ||
359 | } | ||