Imported from ../lua-3.1.tar.gz.
[lua.git] / src / lib / liolib.c
blob15ea6587d09b321615d816f539dcf9197c2fb902
1 /*
2 ** $Id: liolib.c,v 1.21 1998/06/18 17:04:28 roberto Exp $
3 ** Standard I/O (and system) library
4 ** See Copyright Notice in lua.h
5 */
8 #include <errno.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <time.h>
14 #include "lauxlib.h"
15 #include "lua.h"
16 #include "luadebug.h"
17 #include "lualib.h"
20 #ifndef OLD_ANSI
21 #include <locale.h>
22 #else
23 #define setlocale(a,b) 0
24 #define LC_ALL 0
25 #define LC_COLLATE 0
26 #define LC_CTYPE 0
27 #define LC_MONETARY 0
28 #define LC_NUMERIC 0
29 #define LC_TIME 0
30 #define strerror(e) "(no error message provided by operating system)"
31 #endif
34 #define CLOSEDTAG 2
35 #define IOTAG 1
37 #define FIRSTARG 3 /* 1st and 2nd are upvalues */
39 #define FINPUT "_INPUT"
40 #define FOUTPUT "_OUTPUT"
43 #ifdef POPEN
44 FILE *popen();
45 int pclose();
46 #else
47 #define popen(x,y) NULL /* that is, popen always fails */
48 #define pclose(x) (-1)
49 #endif
52 static int gettag (int i)
54 return lua_getnumber(lua_getparam(i));
58 static void pushresult (int i)
60 if (i)
61 lua_pushuserdata(NULL);
62 else {
63 lua_pushnil();
64 lua_pushstring(strerror(errno));
69 static int ishandler (lua_Object f)
71 if (lua_isuserdata(f)) {
72 if (lua_tag(f) == gettag(CLOSEDTAG))
73 lua_error("cannot access a closed file");
74 return lua_tag(f) == gettag(IOTAG);
76 else return 0;
79 static FILE *getfile (char *name)
81 lua_Object f = lua_getglobal(name);
82 if (!ishandler(f))
83 luaL_verror("global variable `%.50s' is not a file handle", name);
84 return lua_getuserdata(f);
88 static FILE *getfileparam (char *name, int *arg)
90 lua_Object f = lua_getparam(*arg);
91 if (ishandler(f)) {
92 (*arg)++;
93 return lua_getuserdata(f);
95 else
96 return getfile(name);
100 static void closefile (char *name)
102 FILE *f = getfile(name);
103 if (f == stdin || f == stdout) return;
104 if (pclose(f) == -1)
105 fclose(f);
106 lua_pushobject(lua_getglobal(name));
107 lua_settag(gettag(CLOSEDTAG));
111 static void setfile (FILE *f, char *name, int tag)
113 lua_pushusertag(f, tag);
114 lua_setglobal(name);
118 static void setreturn (FILE *f, char *name)
120 int tag = gettag(IOTAG);
121 setfile(f, name, tag);
122 lua_pushusertag(f, tag);
126 static void io_readfrom (void)
128 FILE *current;
129 lua_Object f = lua_getparam(FIRSTARG);
130 if (f == LUA_NOOBJECT) {
131 closefile(FINPUT);
132 current = stdin;
134 else if (lua_tag(f) == gettag(IOTAG))
135 current = lua_getuserdata(f);
136 else {
137 char *s = luaL_check_string(FIRSTARG);
138 current = (*s == '|') ? popen(s+1, "r") : fopen(s, "r");
139 if (current == NULL) {
140 pushresult(0);
141 return;
144 setreturn(current, FINPUT);
148 static void io_writeto (void)
150 FILE *current;
151 lua_Object f = lua_getparam(FIRSTARG);
152 if (f == LUA_NOOBJECT) {
153 closefile(FOUTPUT);
154 current = stdout;
156 else if (lua_tag(f) == gettag(IOTAG))
157 current = lua_getuserdata(f);
158 else {
159 char *s = luaL_check_string(FIRSTARG);
160 current = (*s == '|') ? popen(s+1,"w") : fopen(s,"w");
161 if (current == NULL) {
162 pushresult(0);
163 return;
166 setreturn(current, FOUTPUT);
170 static void io_appendto (void)
172 char *s = luaL_check_string(FIRSTARG);
173 FILE *fp = fopen (s, "a");
174 if (fp != NULL)
175 setreturn(fp, FOUTPUT);
176 else
177 pushresult(0);
181 #define NEED_OTHER (EOF-1) /* just some flag different from EOF */
184 static void read_until (FILE *f, int lim) {
185 int l = 0;
186 int c;
187 for (c = getc(f); c != EOF && c != lim; c = getc(f)) {
188 luaL_addchar(c);
189 l++;
191 if (l > 0 || c == lim) /* read anything? */
192 lua_pushlstring(luaL_buffer(), l);
195 static void io_read (void) {
196 int arg = FIRSTARG;
197 FILE *f = getfileparam(FINPUT, &arg);
198 char *p = luaL_opt_string(arg, NULL);
199 luaL_resetbuffer();
200 if (p == NULL) /* default: read a line */
201 read_until(f, '\n');
202 else if (p[0] == '.' && p[1] == '*' && p[2] == 0) /* p = ".*" */
203 read_until(f, EOF);
204 else {
205 int l = 0; /* number of chars read in buffer */
206 int inskip = 0; /* to control {skips} */
207 int c = NEED_OTHER;
208 while (*p) {
209 switch (*p) {
210 case '{':
211 inskip++;
212 p++;
213 continue;
214 case '}':
215 if (inskip == 0)
216 lua_error("unbalanced braces in read pattern");
217 inskip--;
218 p++;
219 continue;
220 default: {
221 char *ep; /* get what is next */
222 int m; /* match result */
223 if (c == NEED_OTHER) c = getc(f);
224 if (c == EOF) {
225 luaI_singlematch(0, p, &ep); /* to set "ep" */
226 m = 0;
228 else {
229 m = luaI_singlematch(c, p, &ep);
230 if (m) {
231 if (inskip == 0) {
232 luaL_addchar(c);
233 l++;
235 c = NEED_OTHER;
238 switch (*ep) {
239 case '*': /* repetition */
240 if (!m) p = ep+1; /* else stay in (repeat) the same item */
241 continue;
242 case '?': /* optional */
243 p = ep+1; /* continues reading the pattern */
244 continue;
245 default:
246 if (m) p = ep; /* continues reading the pattern */
247 else
248 goto break_while; /* pattern fails */
252 } break_while:
253 if (c >= 0) /* not EOF nor NEED_OTHER? */
254 ungetc(c, f);
255 if (l > 0 || *p == 0) /* read something or did not fail? */
256 lua_pushlstring(luaL_buffer(), l);
261 static void io_write (void)
263 int arg = FIRSTARG;
264 FILE *f = getfileparam(FOUTPUT, &arg);
265 int status = 1;
266 char *s;
267 long l;
268 while ((s = luaL_opt_lstr(arg++, NULL, &l)) != NULL)
269 status = status && (fwrite(s, 1, l, f) == l);
270 pushresult(status);
274 static void io_execute (void)
276 lua_pushnumber(system(luaL_check_string(1)));
280 static void io_remove (void)
282 pushresult(remove(luaL_check_string(1)) == 0);
286 static void io_rename (void)
288 pushresult(rename(luaL_check_string(1),
289 luaL_check_string(2)) == 0);
293 static void io_tmpname (void)
295 lua_pushstring(tmpnam(NULL));
300 static void io_getenv (void)
302 lua_pushstring(getenv(luaL_check_string(1))); /* if NULL push nil */
306 static void io_clock (void) {
307 lua_pushnumber(((double)clock())/CLOCKS_PER_SEC);
311 static void io_date (void)
313 time_t t;
314 struct tm *tm;
315 char *s = luaL_opt_string(1, "%c");
316 char b[BUFSIZ];
317 time(&t); tm = localtime(&t);
318 if (strftime(b,sizeof(b),s,tm))
319 lua_pushstring(b);
320 else
321 lua_error("invalid `date' format");
325 static void setloc (void)
327 static int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC,
328 LC_TIME};
329 static char *catnames[] = {"all", "collate", "ctype", "monetary",
330 "numeric", "time", NULL};
331 int op = luaL_findstring(luaL_opt_string(2, "all"), catnames);
332 luaL_arg_check(op != -1, 2, "invalid option");
333 lua_pushstring(setlocale(cat[op], luaL_check_string(1)));
337 static void io_exit (void)
339 lua_Object o = lua_getparam(1);
340 exit(lua_isnumber(o) ? (int)lua_getnumber(o) : 1);
344 static void io_debug (void)
346 while (1) {
347 char buffer[250];
348 fprintf(stderr, "lua_debug> ");
349 if (fgets(buffer, sizeof(buffer), stdin) == 0) return;
350 if (strcmp(buffer, "cont\n") == 0) return;
351 lua_dostring(buffer);
356 static void lua_printstack (FILE *f)
358 int level = 1; /* skip level 0 (it's this function) */
359 lua_Object func;
360 while ((func = lua_stackedfunction(level++)) != LUA_NOOBJECT) {
361 char *name;
362 int currentline;
363 char *filename;
364 int linedefined;
365 lua_funcinfo(func, &filename, &linedefined);
366 fprintf(f, (level==2) ? "Active Stack:\n\t" : "\t");
367 switch (*lua_getobjname(func, &name)) {
368 case 'g':
369 fprintf(f, "function %s", name);
370 break;
371 case 't':
372 fprintf(f, "`%s' tag method", name);
373 break;
374 default: {
375 if (linedefined == 0)
376 fprintf(f, "main of %s", filename);
377 else if (linedefined < 0)
378 fprintf(f, "%s", filename);
379 else
380 fprintf(f, "function (%s:%d)", filename, linedefined);
381 filename = NULL;
384 if ((currentline = lua_currentline(func)) > 0)
385 fprintf(f, " at line %d", currentline);
386 if (filename)
387 fprintf(f, " [in file %s]", filename);
388 fprintf(f, "\n");
393 static void errorfb (void)
395 fprintf(stderr, "lua: %s\n", lua_getstring(lua_getparam(1)));
396 lua_printstack(stderr);
401 static struct luaL_reg iolib[] = {
402 {"setlocale", setloc},
403 {"execute", io_execute},
404 {"remove", io_remove},
405 {"rename", io_rename},
406 {"tmpname", io_tmpname},
407 {"getenv", io_getenv},
408 {"date", io_date},
409 {"clock", io_clock},
410 {"exit", io_exit},
411 {"debug", io_debug},
412 {"print_stack", errorfb}
415 static struct luaL_reg iolibtag[] = {
416 {"readfrom", io_readfrom},
417 {"writeto", io_writeto},
418 {"appendto", io_appendto},
419 {"read", io_read},
420 {"write", io_write}
423 static void openwithtags (void)
425 int iotag = lua_newtag();
426 int closedtag = lua_newtag();
427 int i;
428 for (i=0; i<sizeof(iolibtag)/sizeof(iolibtag[0]); i++) {
429 /* put both tags as upvalues for these functions */
430 lua_pushnumber(iotag);
431 lua_pushnumber(closedtag);
432 lua_pushcclosure(iolibtag[i].func, 2);
433 lua_setglobal(iolibtag[i].name);
435 setfile(stdin, FINPUT, iotag);
436 setfile(stdout, FOUTPUT, iotag);
437 setfile(stdin, "_STDIN", iotag);
438 setfile(stdout, "_STDOUT", iotag);
439 setfile(stderr, "_STDERR", iotag);
442 void lua_iolibopen (void)
444 luaL_openlib(iolib, (sizeof(iolib)/sizeof(iolib[0])));
445 openwithtags();
446 lua_pushcfunction(errorfb);
447 lua_seterrormethod();