2 ** $Id: liolib.c,v 1.41 1999/06/23 13:48:39 roberto Exp $
3 ** Standard I/O (and system) library
4 ** See Copyright Notice in lua.h
23 /* no support for locale and for strerror: fake them */
24 #define setlocale(a,b) 0
31 #define strerror(e) "(no error message provided by operating system)"
37 #define FIRSTARG 2 /* 1st is upvalue */
39 #define CLOSEDTAG(tag) ((tag)-1) /* assume that CLOSEDTAG = iotag-1 */
42 #define FINPUT "_INPUT"
43 #define FOUTPUT "_OUTPUT"
49 #define CLOSEFILE(f) {if (pclose(f) == -1) fclose(f);}
51 /* no support for popen */
52 #define popen(x,y) NULL /* that is, popen always fails */
53 #define CLOSEFILE(f) {fclose(f);}
58 static void pushresult (int i
) {
60 lua_pushuserdata(NULL
);
63 lua_pushstring(strerror(errno
));
64 lua_pushnumber(errno
);
70 ** {======================================================
72 ** =======================================================
75 static int gettag (void) {
76 return (int)lua_getnumber(lua_getparam(IOTAG
));
80 static int ishandle (lua_Object f
) {
81 if (lua_isuserdata(f
)) {
83 if (lua_tag(f
) == CLOSEDTAG(tag
))
84 lua_error("cannot access a closed file");
85 return lua_tag(f
) == tag
;
91 static FILE *getfilebyname (char *name
) {
92 lua_Object f
= lua_getglobal(name
);
94 luaL_verror("global variable `%.50s' is not a file handle", name
);
95 return lua_getuserdata(f
);
99 static FILE *getfile (int arg
) {
100 lua_Object f
= lua_getparam(arg
);
101 return (ishandle(f
)) ? lua_getuserdata(f
) : NULL
;
105 static FILE *getnonullfile (int arg
) {
106 FILE *f
= getfile(arg
);
107 luaL_arg_check(f
, arg
, "invalid file handle");
112 static FILE *getfileparam (char *name
, int *arg
) {
113 FILE *f
= getfile(*arg
);
119 return getfilebyname(name
);
123 static void closefile (FILE *f
) {
124 if (f
!= stdin
&& f
!= stdout
) {
127 lua_pushusertag(f
, tag
);
128 lua_settag(CLOSEDTAG(tag
));
133 static void io_close (void) {
134 closefile(getnonullfile(FIRSTARG
));
138 static void gc_close (void) {
139 FILE *f
= getnonullfile(FIRSTARG
);
140 if (f
!= stdin
&& f
!= stdout
&& f
!= stderr
) {
146 static void io_open (void) {
147 FILE *f
= fopen(luaL_check_string(FIRSTARG
), luaL_check_string(FIRSTARG
+1));
148 if (f
) lua_pushusertag(f
, gettag());
153 static void setfile (FILE *f
, char *name
, int tag
) {
154 lua_pushusertag(f
, tag
);
159 static void setreturn (FILE *f
, char *name
) {
164 setfile(f
, name
, tag
);
165 lua_pushusertag(f
, tag
);
170 static void io_readfrom (void) {
172 lua_Object f
= lua_getparam(FIRSTARG
);
173 if (f
== LUA_NOOBJECT
) {
174 closefile(getfilebyname(FINPUT
));
177 else if (lua_tag(f
) == gettag()) /* deprecated option */
178 current
= lua_getuserdata(f
);
180 char *s
= luaL_check_string(FIRSTARG
);
181 current
= (*s
== '|') ? popen(s
+1, "r") : fopen(s
, "r");
183 setreturn(current
, FINPUT
);
187 static void io_writeto (void) {
189 lua_Object f
= lua_getparam(FIRSTARG
);
190 if (f
== LUA_NOOBJECT
) {
191 closefile(getfilebyname(FOUTPUT
));
194 else if (lua_tag(f
) == gettag()) /* deprecated option */
195 current
= lua_getuserdata(f
);
197 char *s
= luaL_check_string(FIRSTARG
);
198 current
= (*s
== '|') ? popen(s
+1,"w") : fopen(s
, "w");
200 setreturn(current
, FOUTPUT
);
204 static void io_appendto (void) {
205 FILE *current
= fopen(luaL_check_string(FIRSTARG
), "a");
206 setreturn(current
, FOUTPUT
);
212 ** {======================================================
214 ** =======================================================
219 ** We cannot lookahead without need, because this can lock stdin.
220 ** This flag signals when we need to read a next char.
222 #define NEED_OTHER (EOF-1) /* just some flag different from EOF */
225 static int read_pattern (FILE *f
, char *p
) {
226 int inskip
= 0; /* {skip} level */
235 if (!inskip
) lua_error("unbalanced braces in read pattern");
240 char *ep
= luaI_classend(p
); /* get what is next */
241 int m
; /* match result */
242 if (c
== NEED_OTHER
) c
= getc(f
);
243 m
= (c
==EOF
) ? 0 : luaI_singlematch(c
, p
, ep
);
245 if (!inskip
) luaL_addchar(c
);
249 case '+': /* repetition (1 or more) */
250 if (!m
) goto break_while
; /* pattern fails? */
251 /* else go through */
252 case '*': /* repetition (0 or more) */
253 while (m
) { /* reads the same item until it fails */
255 m
= (c
==EOF
) ? 0 : luaI_singlematch(c
, p
, ep
);
256 if (m
&& !inskip
) luaL_addchar(c
);
258 /* go through to continue reading the pattern */
259 case '?': /* optional */
260 p
= ep
+1; /* continues reading the pattern */
263 if (!m
) goto break_while
; /* pattern fails? */
264 p
= ep
; /* else continues reading the pattern */
269 if (c
!= NEED_OTHER
) ungetc(c
, f
);
274 static int read_number (FILE *f
) {
276 if (fscanf(f
, "%lf", &d
) == 1) {
280 else return 0; /* read fails */
284 #define HUNK_LINE 1024
285 #define HUNK_FILE BUFSIZ
287 static int read_line (FILE *f
) {
288 /* equivalent to: return read_pattern(f, "[^\n]*{\n}"); */
292 b
= luaL_openspace(HUNK_LINE
);
293 if (!fgets(b
, HUNK_LINE
, f
)) return 0; /* read fails */
296 } while (b
[n
-1] != '\n');
297 luaL_addsize(-1); /* remove '\n' */
302 static void read_file (FILE *f
) {
303 /* equivalent to: return read_pattern(f, ".*"); */
306 char *b
= luaL_openspace(HUNK_FILE
);
307 n
= fread(b
, sizeof(char), HUNK_FILE
, f
);
309 } while (n
==HUNK_FILE
);
313 static void io_read (void) {
314 static char *options
[] = {"*n", "*l", "*a", ".*", "*w", NULL
};
316 FILE *f
= getfileparam(FINPUT
, &arg
);
317 char *p
= luaL_opt_string(arg
++, "*l");
318 do { /* repeat for each part */
322 switch (luaL_findstring(p
, options
)) {
324 if (!read_number(f
)) return; /* read fails */
325 continue; /* number is already pushed; avoid the "pushstring" */
327 success
= read_line(f
);
329 case 2: case 3: /* file */
331 success
= 1; /* always success */
334 success
= read_pattern(f
, "{%s*}%S+");
337 success
= read_pattern(f
, p
);
340 if (!success
&& l
==0) return; /* read fails */
341 lua_pushlstring(luaL_buffer(), l
);
342 } while ((p
= luaL_opt_string(arg
++, NULL
)) != NULL
);
345 /* }====================================================== */
348 static void io_write (void) {
350 FILE *f
= getfileparam(FOUTPUT
, &arg
);
354 while ((s
= luaL_opt_lstr(arg
++, NULL
, &l
)) != NULL
)
355 status
= status
&& ((long)fwrite(s
, 1, l
, f
) == l
);
360 static void io_seek (void) {
361 static int mode
[] = {SEEK_SET
, SEEK_CUR
, SEEK_END
};
362 static char *modenames
[] = {"set", "cur", "end", NULL
};
363 FILE *f
= getnonullfile(FIRSTARG
);
364 int op
= luaL_findstring(luaL_opt_string(FIRSTARG
+1, "cur"), modenames
);
365 long offset
= luaL_opt_long(FIRSTARG
+2, 0);
366 luaL_arg_check(op
!= -1, FIRSTARG
+1, "invalid mode");
367 op
= fseek(f
, offset
, mode
[op
]);
369 pushresult(0); /* error */
371 lua_pushnumber(ftell(f
));
375 static void io_flush (void) {
376 FILE *f
= getfile(FIRSTARG
);
377 luaL_arg_check(f
|| lua_getparam(FIRSTARG
) == LUA_NOOBJECT
, FIRSTARG
,
378 "invalid file handle");
379 pushresult(fflush(f
) == 0);
382 /* }====================================================== */
386 ** {======================================================
387 ** Other O.S. Operations
388 ** =======================================================
391 static void io_execute (void) {
392 lua_pushnumber(system(luaL_check_string(1)));
396 static void io_remove (void) {
397 pushresult(remove(luaL_check_string(1)) == 0);
401 static void io_rename (void) {
402 pushresult(rename(luaL_check_string(1),
403 luaL_check_string(2)) == 0);
407 static void io_tmpname (void) {
408 lua_pushstring(tmpnam(NULL
));
413 static void io_getenv (void) {
414 lua_pushstring(getenv(luaL_check_string(1))); /* if NULL push nil */
418 static void io_clock (void) {
419 lua_pushnumber(((double)clock())/CLOCKS_PER_SEC
);
423 static void io_date (void) {
425 char *s
= luaL_opt_string(1, "%c");
428 time(&t
); tm
= localtime(&t
);
429 if (strftime(b
,sizeof(b
),s
,tm
))
432 lua_error("invalid `date' format");
436 static void setloc (void) {
437 static int cat
[] = {LC_ALL
, LC_COLLATE
, LC_CTYPE
, LC_MONETARY
, LC_NUMERIC
,
439 static char *catnames
[] = {"all", "collate", "ctype", "monetary",
440 "numeric", "time", NULL
};
441 int op
= luaL_findstring(luaL_opt_string(2, "all"), catnames
);
442 luaL_arg_check(op
!= -1, 2, "invalid option");
443 lua_pushstring(setlocale(cat
[op
], luaL_check_string(1)));
447 static void io_exit (void) {
448 lua_Object o
= lua_getparam(1);
449 exit(lua_isnumber(o
) ? (int)lua_getnumber(o
) : 1);
452 /* }====================================================== */
456 static void io_debug (void) {
459 fprintf(stderr
, "lua_debug> ");
460 if (fgets(buffer
, sizeof(buffer
), stdin
) == 0 ||
461 strcmp(buffer
, "cont\n") == 0)
463 lua_dostring(buffer
);
469 #define MESSAGESIZE 150
470 #define MAXMESSAGE (MESSAGESIZE*10)
476 static void errorfb (void) {
477 char buff
[MAXMESSAGE
];
478 int level
= 1; /* skip level 0 (it's this function) */
480 sprintf(buff
, "lua error: %.200s\n", lua_getstring(lua_getparam(1)));
481 while ((func
= lua_stackedfunction(level
++)) != LUA_NOOBJECT
) {
485 char buffchunk
[MAXSRC
];
487 lua_funcinfo(func
, &chunkname
, &linedefined
);
488 luaL_chunkid(buffchunk
, chunkname
, sizeof(buffchunk
));
489 if (level
== 2) strcat(buff
, "Active Stack:\n");
491 if (strlen(buff
) > MAXMESSAGE
-MESSAGESIZE
) {
492 strcat(buff
, "...\n");
493 break; /* buffer is full */
495 switch (*lua_getobjname(func
, &name
)) {
497 sprintf(buff
+strlen(buff
), "function `%.50s'", name
);
500 sprintf(buff
+strlen(buff
), "`%.50s' tag method", name
);
503 if (linedefined
== 0)
504 sprintf(buff
+strlen(buff
), "main of %.70s", buffchunk
);
505 else if (linedefined
< 0)
506 sprintf(buff
+strlen(buff
), "%.70s", buffchunk
);
508 sprintf(buff
+strlen(buff
), "function <%d:%.70s>",
509 linedefined
, buffchunk
);
513 if ((currentline
= lua_currentline(func
)) > 0)
514 sprintf(buff
+strlen(buff
), " at line %d", currentline
);
516 sprintf(buff
+strlen(buff
), " [%.70s]", buffchunk
);
519 func
= lua_rawgetglobal("_ALERT");
520 if (lua_isfunction(func
)) { /* avoid error loop if _ALERT is not defined */
521 lua_pushstring(buff
);
522 lua_callfunction(func
);
528 static struct luaL_reg iolib
[] = {
529 {"_ERRORMESSAGE", errorfb
},
533 {"execute", io_execute
},
535 {"getenv", io_getenv
},
536 {"remove", io_remove
},
537 {"rename", io_rename
},
538 {"setlocale", setloc
},
539 {"tmpname", io_tmpname
}
543 static struct luaL_reg iolibtag
[] = {
544 {"appendto", io_appendto
},
545 {"closefile", io_close
},
547 {"openfile", io_open
},
549 {"readfrom", io_readfrom
},
552 {"writeto", io_writeto
}
556 static void openwithtags (void) {
558 int iotag
= lua_newtag();
559 lua_newtag(); /* alloc CLOSEDTAG: assume that CLOSEDTAG = iotag-1 */
560 for (i
=0; i
<sizeof(iolibtag
)/sizeof(iolibtag
[0]); i
++) {
561 /* put iotag as upvalue for these functions */
562 lua_pushnumber(iotag
);
563 lua_pushcclosure(iolibtag
[i
].func
, 1);
564 lua_setglobal(iolibtag
[i
].name
);
566 /* predefined file handles */
567 setfile(stdin
, FINPUT
, iotag
);
568 setfile(stdout
, FOUTPUT
, iotag
);
569 setfile(stdin
, "_STDIN", iotag
);
570 setfile(stdout
, "_STDOUT", iotag
);
571 setfile(stderr
, "_STDERR", iotag
);
572 /* close file when collected */
573 lua_pushnumber(iotag
);
574 lua_pushcclosure(gc_close
, 1);
575 lua_settagmethod(iotag
, "gc");
578 void lua_iolibopen (void) {
579 /* register lib functions */
580 luaL_openlib(iolib
, (sizeof(iolib
)/sizeof(iolib
[0])));