From 29ede6aa13144ff7b69c57a87be1ee93f57ae896 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 22 Nov 1999 11:12:07 -0200 Subject: first implementation of multiple states (reentrant code). --- liolib.c | 362 ++++++++++++++++++++++++++++++++------------------------------- 1 file changed, 182 insertions(+), 180 deletions(-) (limited to 'liolib.c') diff --git a/liolib.c b/liolib.c index c1d2a455..1a414a9d 100644 --- a/liolib.c +++ b/liolib.c @@ -1,5 +1,5 @@ /* -** $Id: liolib.c,v 1.49 1999/10/26 11:00:12 roberto Exp roberto $ +** $Id: liolib.c,v 1.50 1999/11/09 17:59:35 roberto Exp roberto $ ** Standard I/O (and system) library ** See Copyright Notice in lua.h */ @@ -12,6 +12,8 @@ #include #include +#define LUA_REENTRANT + #include "lauxlib.h" #include "lua.h" #include "luadebug.h" @@ -22,7 +24,7 @@ #include #else /* no support for locale and for strerror: fake them */ -#define setlocale(a,b) 0 +#define setlocale(a,b) ((void)a, strcmp((b),"C")==0?"C":NULL) #define LC_ALL 0 #define LC_COLLATE 0 #define LC_CTYPE 0 @@ -37,7 +39,7 @@ #define FIRSTARG 2 /* 1st is upvalue */ -#define CLOSEDTAG(tag) ((tag)-1) /* assume that CLOSEDTAG = iotag-1 */ +#define CLOSEDTAG(L, tag) ((tag)-1) /* assume that CLOSEDTAG = iotag-1 */ #define FINPUT "_INPUT" @@ -47,22 +49,22 @@ #ifdef POPEN /* FILE *popen(); int pclose(); */ -#define CLOSEFILE(f) ((pclose(f) == -1) ? fclose(f) : 0) +#define CLOSEFILE(L, f) ((pclose(f) == -1) ? fclose(f) : 0) #else /* no support for popen */ #define popen(x,y) NULL /* that is, popen always fails */ -#define CLOSEFILE(f) (fclose(f)) +#define CLOSEFILE(L, f) (fclose(f)) #endif -static void pushresult (int i) { +static void pushresult (lua_State *L, int i) { if (i) - lua_pushuserdata(NULL); + lua_pushuserdata(L, NULL); else { - lua_pushnil(); - lua_pushstring(strerror(errno)); - lua_pushnumber(errno); + lua_pushnil(L); + lua_pushstring(L, strerror(errno)); + lua_pushnumber(L, errno); } } @@ -73,144 +75,144 @@ static void pushresult (int i) { ** ======================================================= */ -static int gettag (void) { - return (int)lua_getnumber(lua_getparam(IOTAG)); +static int gettag (lua_State *L) { + return (int)lua_getnumber(L, lua_getparam(L, IOTAG)); } -static int ishandle (lua_Object f) { - if (lua_isuserdata(f)) { - int tag = gettag(); - if (lua_tag(f) == CLOSEDTAG(tag)) - lua_error("cannot access a closed file"); - return lua_tag(f) == tag; +static int ishandle (lua_State *L, lua_Object f) { + if (lua_isuserdata(L, f)) { + int tag = gettag(L); + if (lua_tag(L, f) == CLOSEDTAG(L, tag)) + lua_error(L, "cannot access a closed file"); + return lua_tag(L, f) == tag; } else return 0; } -static FILE *getfilebyname (const char *name) { - lua_Object f = lua_rawgetglobal(name); - if (!ishandle(f)) - luaL_verror("global variable `%.50s' is not a file handle", name); - return lua_getuserdata(f); +static FILE *getfilebyname (lua_State *L, const char *name) { + lua_Object f = lua_rawgetglobal(L, name); + if (!ishandle(L, f)) + luaL_verror(L, "global variable `%.50s' is not a file handle", name); + return lua_getuserdata(L, f); } -static FILE *getfile (int arg) { - lua_Object f = lua_getparam(arg); - return (ishandle(f)) ? lua_getuserdata(f) : NULL; +static FILE *getfile (lua_State *L, int arg) { + lua_Object f = lua_getparam(L, arg); + return (ishandle(L, f)) ? lua_getuserdata(L, f) : NULL; } -static FILE *getnonullfile (int arg) { - FILE *f = getfile(arg); - luaL_arg_check(f, arg, "invalid file handle"); +static FILE *getnonullfile (lua_State *L, int arg) { + FILE *f = getfile(L, arg); + luaL_arg_check(L, f, arg, "invalid file handle"); return f; } -static FILE *getfileparam (const char *name, int *arg) { - FILE *f = getfile(*arg); +static FILE *getfileparam (lua_State *L, const char *name, int *arg) { + FILE *f = getfile(L, *arg); if (f) { (*arg)++; return f; } else - return getfilebyname(name); + return getfilebyname(L, name); } -static int closefile (FILE *f) { +static int closefile (lua_State *L, FILE *f) { if (f == stdin || f == stdout) return 1; else { - int tag = gettag(); - lua_pushusertag(f, tag); - lua_settag(CLOSEDTAG(tag)); - return (CLOSEFILE(f) == 0); + int tag = gettag(L); + lua_pushusertag(L, f, tag); + lua_settag(L, CLOSEDTAG(L, tag)); + return (CLOSEFILE(L, f) == 0); } } -static void io_close (void) { - pushresult(closefile(getnonullfile(FIRSTARG))); +static void io_close (lua_State *L) { + pushresult(L, closefile(L, getnonullfile(L, FIRSTARG))); } -static void gc_close (void) { - FILE *f = getnonullfile(FIRSTARG); +static void gc_close (lua_State *L) { + FILE *f = getnonullfile(L, FIRSTARG); if (f != stdin && f != stdout && f != stderr) { - CLOSEFILE(f); + CLOSEFILE(L, f); } } -static void io_open (void) { - FILE *f = fopen(luaL_check_string(FIRSTARG), luaL_check_string(FIRSTARG+1)); - if (f) lua_pushusertag(f, gettag()); - else pushresult(0); +static void io_open (lua_State *L) { + FILE *f = fopen(luaL_check_string(L, FIRSTARG), luaL_check_string(L, FIRSTARG+1)); + if (f) lua_pushusertag(L, f, gettag(L)); + else pushresult(L, 0); } -static void setfile (FILE *f, const char *name, int tag) { - lua_pushusertag(f, tag); - lua_setglobal(name); +static void setfile (lua_State *L, FILE *f, const char *name, int tag) { + lua_pushusertag(L, f, tag); + lua_setglobal(L, name); } -static void setreturn (FILE *f, const char *name) { +static void setreturn (lua_State *L, FILE *f, const char *name) { if (f == NULL) - pushresult(0); + pushresult(L, 0); else { - int tag = gettag(); - setfile(f, name, tag); - lua_pushusertag(f, tag); + int tag = gettag(L); + setfile(L, f, name, tag); + lua_pushusertag(L, f, tag); } } -static void io_readfrom (void) { +static void io_readfrom (lua_State *L) { FILE *current; - lua_Object f = lua_getparam(FIRSTARG); + lua_Object f = lua_getparam(L, FIRSTARG); if (f == LUA_NOOBJECT) { - if (closefile(getfilebyname(FINPUT))) + if (closefile(L, getfilebyname(L, FINPUT))) current = stdin; else current = NULL; /* to signal error */ } - else if (lua_tag(f) == gettag()) /* deprecated option */ - current = lua_getuserdata(f); + else if (lua_tag(L, f) == gettag(L)) /* deprecated option */ + current = lua_getuserdata(L, f); else { - const char *s = luaL_check_string(FIRSTARG); + const char *s = luaL_check_string(L, FIRSTARG); current = (*s == '|') ? popen(s+1, "r") : fopen(s, "r"); } - setreturn(current, FINPUT); + setreturn(L, current, FINPUT); } -static void io_writeto (void) { +static void io_writeto (lua_State *L) { FILE *current; - lua_Object f = lua_getparam(FIRSTARG); + lua_Object f = lua_getparam(L, FIRSTARG); if (f == LUA_NOOBJECT) { - if (closefile(getfilebyname(FOUTPUT))) + if (closefile(L, getfilebyname(L, FOUTPUT))) current = stdout; else current = NULL; /* to signal error */ } - else if (lua_tag(f) == gettag()) /* deprecated option */ - current = lua_getuserdata(f); + else if (lua_tag(L, f) == gettag(L)) /* deprecated option */ + current = lua_getuserdata(L, f); else { - const char *s = luaL_check_string(FIRSTARG); + const char *s = luaL_check_string(L, FIRSTARG); current = (*s == '|') ? popen(s+1,"w") : fopen(s, "w"); } - setreturn(current, FOUTPUT); + setreturn(L, current, FOUTPUT); } -static void io_appendto (void) { - FILE *current = fopen(luaL_check_string(FIRSTARG), "a"); - setreturn(current, FOUTPUT); +static void io_appendto (lua_State *L) { + FILE *current = fopen(luaL_check_string(L, FIRSTARG), "a"); + setreturn(L, current, FOUTPUT); } @@ -232,7 +234,7 @@ static void io_appendto (void) { #define NEED_OTHER (EOF-1) /* just some flag different from EOF */ -static int read_pattern (FILE *f, const char *p) { +static int read_pattern (lua_State *L, FILE *f, const char *p) { int inskip = 0; /* {skip} level */ int c = NEED_OTHER; while (*p != '\0') { @@ -242,17 +244,17 @@ static int read_pattern (FILE *f, const char *p) { p++; continue; case '}': - if (!inskip) lua_error("unbalanced braces in read pattern"); + if (!inskip) lua_error(L, "unbalanced braces in read pattern"); inskip--; p++; continue; default: { - const char *ep = luaI_classend(p); /* get what is next */ + const char *ep = luaI_classend(L, p); /* get what is next */ int m; /* match result */ if (c == NEED_OTHER) c = getc(f); m = (c==EOF) ? 0 : luaI_singlematch(c, p, ep); if (m) { - if (!inskip) luaL_addchar(c); + if (!inskip) luaL_addchar(L, c); c = NEED_OTHER; } switch (*ep) { @@ -263,7 +265,7 @@ static int read_pattern (FILE *f, const char *p) { while (m) { /* reads the same item until it fails */ c = getc(f); m = (c==EOF) ? 0 : luaI_singlematch(c, p, ep); - if (m && !inskip) luaL_addchar(c); + if (m && !inskip) luaL_addchar(L, c); } /* go through to continue reading the pattern */ case '?': /* optional */ @@ -282,26 +284,26 @@ static int read_pattern (FILE *f, const char *p) { #else -#define read_pattern(f,p) (lua_error("read patterns are deprecated"), 0) +#define read_pattern(L, f,p) (lua_error(L, "read patterns are deprecated"), 0) #endif -static int read_number (FILE *f) { +static int read_number (lua_State *L, FILE *f) { double d; if (fscanf(f, "%lf", &d) == 1) { - lua_pushnumber(d); + lua_pushnumber(L, d); return 1; } else return 0; /* read fails */ } -static void read_word (FILE *f) { +static void read_word (lua_State *L, FILE *f) { int c; do { c = fgetc(f); } while isspace(c); /* skip spaces */ while (c != EOF && !isspace(c)) { - luaL_addchar(c); + luaL_addchar(L, c); c = fgetc(f); } ungetc(c, f); @@ -311,127 +313,127 @@ static void read_word (FILE *f) { #define HUNK_LINE 256 #define HUNK_FILE BUFSIZ -static int read_line (FILE *f) { +static int read_line (lua_State *L, FILE *f) { int n; char *b; do { - b = luaL_openspace(HUNK_LINE); + b = luaL_openspace(L, HUNK_LINE); if (!fgets(b, HUNK_LINE, f)) return 0; /* read fails */ n = strlen(b); - luaL_addsize(n); + luaL_addsize(L, n); } while (b[n-1] != '\n'); - luaL_addsize(-1); /* remove '\n' */ + luaL_addsize(L, -1); /* remove '\n' */ return 1; } -static void read_file (FILE *f) { +static void read_file (lua_State *L, FILE *f) { int n; do { - char *b = luaL_openspace(HUNK_FILE); + char *b = luaL_openspace(L, HUNK_FILE); n = fread(b, sizeof(char), HUNK_FILE, f); - luaL_addsize(n); + luaL_addsize(L, n); } while (n==HUNK_FILE); } -static int read_chars (FILE *f, int n) { - char *b = luaL_openspace(n); +static int read_chars (lua_State *L, FILE *f, int n) { + char *b = luaL_openspace(L, n); int n1 = fread(b, sizeof(char), n, f); - luaL_addsize(n1); + luaL_addsize(L, n1); return (n == n1); } -static void io_read (void) { +static void io_read (lua_State *L) { int arg = FIRSTARG; - FILE *f = getfileparam(FINPUT, &arg); - lua_Object op = lua_getparam(arg); + FILE *f = getfileparam(L, FINPUT, &arg); + lua_Object op = lua_getparam(L, arg); do { /* repeat for each part */ long l; int success; - luaL_resetbuffer(); - if (lua_isnumber(op)) - success = read_chars(f, (int)lua_getnumber(op)); + luaL_resetbuffer(L); + if (lua_isnumber(L, op)) + success = read_chars(L, f, (int)lua_getnumber(L, op)); else { - const char *p = luaL_opt_string(arg, "*l"); + const char *p = luaL_opt_string(L, arg, "*l"); if (p[0] != '*') - success = read_pattern(f, p); /* deprecated! */ + success = read_pattern(L, f, p); /* deprecated! */ else { switch (p[1]) { case 'n': /* number */ - if (!read_number(f)) return; /* read fails */ + if (!read_number(L, f)) return; /* read fails */ continue; /* number is already pushed; avoid the "pushstring" */ case 'l': /* line */ - success = read_line(f); + success = read_line(L, f); break; case 'a': /* file */ - read_file(f); + read_file(L, f); success = 1; /* always success */ break; case 'w': /* word */ - read_word(f); + read_word(L, f); success = 0; /* must read something to succeed */ break; default: - luaL_argerror(arg, "invalid format"); + luaL_argerror(L, arg, "invalid format"); success = 0; /* to avoid warnings */ } } } - l = luaL_getsize(); + l = luaL_getsize(L); if (!success && l==0) return; /* read fails */ - lua_pushlstring(luaL_buffer(), l); - } while ((op = lua_getparam(++arg)) != LUA_NOOBJECT); + lua_pushlstring(L, luaL_buffer(L), l); + } while ((op = lua_getparam(L, ++arg)) != LUA_NOOBJECT); } /* }====================================================== */ -static void io_write (void) { +static void io_write (lua_State *L) { int arg = FIRSTARG; - FILE *f = getfileparam(FOUTPUT, &arg); + FILE *f = getfileparam(L, FOUTPUT, &arg); int status = 1; lua_Object o; - while ((o = lua_getparam(arg++)) != LUA_NOOBJECT) { - switch (lua_type(o)[2]) { + while ((o = lua_getparam(L, arg++)) != LUA_NOOBJECT) { + switch (lua_type(L, o)[2]) { case 'r': { /* stRing? */ - long l = lua_strlen(o); + long l = lua_strlen(L, o); status = status && - ((long)fwrite(lua_getstring(o), sizeof(char), l, f) == l); + ((long)fwrite(lua_getstring(L, o), sizeof(char), l, f) == l); break; } case 'm': /* nuMber? */ /* LUA_NUMBER */ /* optimization: could be done exactly as for strings */ - status = status && fprintf(f, "%.16g", lua_getnumber(o)) > 0; + status = status && fprintf(f, "%.16g", lua_getnumber(L, o)) > 0; break; - default: luaL_argerror(arg-1, "string expected"); + default: luaL_argerror(L, arg-1, "string expected"); } } - pushresult(status); + pushresult(L, status); } -static void io_seek (void) { +static void io_seek (lua_State *L) { static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; static const char *const modenames[] = {"set", "cur", "end", NULL}; - FILE *f = getnonullfile(FIRSTARG); - int op = luaL_findstring(luaL_opt_string(FIRSTARG+1, "cur"), modenames); - long offset = luaL_opt_long(FIRSTARG+2, 0); - luaL_arg_check(op != -1, FIRSTARG+1, "invalid mode"); + FILE *f = getnonullfile(L, FIRSTARG); + int op = luaL_findstring(luaL_opt_string(L, FIRSTARG+1, "cur"), modenames); + long offset = luaL_opt_long(L, FIRSTARG+2, 0); + luaL_arg_check(L, op != -1, FIRSTARG+1, "invalid mode"); op = fseek(f, offset, mode[op]); if (op) - pushresult(0); /* error */ + pushresult(L, 0); /* error */ else - lua_pushnumber(ftell(f)); + lua_pushnumber(L, ftell(f)); } -static void io_flush (void) { - FILE *f = getfile(FIRSTARG); - luaL_arg_check(f || lua_getparam(FIRSTARG) == LUA_NOOBJECT, FIRSTARG, +static void io_flush (lua_State *L) { + FILE *f = getfile(L, FIRSTARG); + luaL_arg_check(L, f || lua_getparam(L, FIRSTARG) == LUA_NOOBJECT, FIRSTARG, "invalid file handle"); - pushresult(fflush(f) == 0); + pushresult(L, fflush(f) == 0); } /* }====================================================== */ @@ -443,102 +445,102 @@ static void io_flush (void) { ** ======================================================= */ -static void io_execute (void) { - lua_pushnumber(system(luaL_check_string(1))); +static void io_execute (lua_State *L) { + lua_pushnumber(L, system(luaL_check_string(L, 1))); } -static void io_remove (void) { - pushresult(remove(luaL_check_string(1)) == 0); +static void io_remove (lua_State *L) { + pushresult(L, remove(luaL_check_string(L, 1)) == 0); } -static void io_rename (void) { - pushresult(rename(luaL_check_string(1), - luaL_check_string(2)) == 0); +static void io_rename (lua_State *L) { + pushresult(L, rename(luaL_check_string(L, 1), + luaL_check_string(L, 2)) == 0); } -static void io_tmpname (void) { - lua_pushstring(tmpnam(NULL)); +static void io_tmpname (lua_State *L) { + lua_pushstring(L, tmpnam(NULL)); } -static void io_getenv (void) { - lua_pushstring(getenv(luaL_check_string(1))); /* if NULL push nil */ +static void io_getenv (lua_State *L) { + lua_pushstring(L, getenv(luaL_check_string(L, 1))); /* if NULL push nil */ } -static void io_clock (void) { - lua_pushnumber(((double)clock())/CLOCKS_PER_SEC); +static void io_clock (lua_State *L) { + lua_pushnumber(L, ((double)clock())/CLOCKS_PER_SEC); } -static void io_date (void) { +static void io_date (lua_State *L) { char b[256]; - const char *s = luaL_opt_string(1, "%c"); + const char *s = luaL_opt_string(L, 1, "%c"); struct tm *tm; time_t t; time(&t); tm = localtime(&t); if (strftime(b,sizeof(b),s,tm)) - lua_pushstring(b); + lua_pushstring(L, b); else - lua_error("invalid `date' format"); + lua_error(L, "invalid `date' format"); } -static void setloc (void) { +static void setloc (lua_State *L) { static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME}; static const char *const catnames[] = {"all", "collate", "ctype", "monetary", "numeric", "time", NULL}; - int op = luaL_findstring(luaL_opt_string(2, "all"), catnames); - luaL_arg_check(op != -1, 2, "invalid option"); - lua_pushstring(setlocale(cat[op], luaL_check_string(1))); + int op = luaL_findstring(luaL_opt_string(L, 2, "all"), catnames); + luaL_arg_check(L, op != -1, 2, "invalid option"); + lua_pushstring(L, setlocale(cat[op], luaL_check_string(L, 1))); } -static void io_exit (void) { - exit(luaL_opt_int(1, EXIT_SUCCESS)); +static void io_exit (lua_State *L) { + exit(luaL_opt_int(L, 1, EXIT_SUCCESS)); } /* }====================================================== */ -static void io_debug (void) { +static void io_debug (lua_State *L) { for (;;) { char buffer[250]; fprintf(stderr, "lua_debug> "); if (fgets(buffer, sizeof(buffer), stdin) == 0 || strcmp(buffer, "cont\n") == 0) return; - lua_dostring(buffer); + lua_dostring(L, buffer); } } #define MESSAGESIZE 150 -#define MAXMESSAGE (MESSAGESIZE*10) +#define MAXMESSAGE (MESSAGESIZE*10) #define MAXSRC 60 -static void errorfb (void) { +static void errorfb (lua_State *L) { char buff[MAXMESSAGE]; int level = 1; /* skip level 0 (it's this function) */ lua_Object func; - sprintf(buff, "lua error: %.200s\n", lua_getstring(lua_getparam(1))); - while ((func = lua_stackedfunction(level++)) != LUA_NOOBJECT) { + sprintf(buff, "lua error: %.200s\n", lua_getstring(L, lua_getparam(L, 1))); + while ((func = lua_stackedfunction(L, level++)) != LUA_NOOBJECT) { const char *name; int currentline; const char *chunkname; char buffchunk[MAXSRC]; int linedefined; - lua_funcinfo(func, &chunkname, &linedefined); + lua_funcinfo(L, func, &chunkname, &linedefined); luaL_chunkid(buffchunk, chunkname, sizeof(buffchunk)); if (level == 2) strcat(buff, "Active Stack:\n"); strcat(buff, " "); @@ -546,7 +548,7 @@ static void errorfb (void) { strcat(buff, "...\n"); break; /* buffer is full */ } - switch (*lua_getobjname(func, &name)) { + switch (*lua_getobjname(L, func, &name)) { case 'g': sprintf(buff+strlen(buff), "function `%.50s'", name); break; @@ -564,16 +566,16 @@ static void errorfb (void) { chunkname = NULL; } } - if ((currentline = lua_currentline(func)) > 0) + if ((currentline = lua_currentline(L, func)) > 0) sprintf(buff+strlen(buff), " at line %d", currentline); if (chunkname) sprintf(buff+strlen(buff), " [%.70s]", buffchunk); strcat(buff, "\n"); } - func = lua_rawgetglobal("_ALERT"); - if (lua_isfunction(func)) { /* avoid error loop if _ALERT is not defined */ - lua_pushstring(buff); - lua_callfunction(func); + func = lua_rawgetglobal(L, "_ALERT"); + if (lua_isfunction(L, func)) { /* avoid error loop if _ALERT is not defined */ + lua_pushstring(L, buff); + lua_callfunction(L, func); } } @@ -607,31 +609,31 @@ static const struct luaL_reg iolibtag[] = { }; -static void openwithtags (void) { +static void openwithtags (lua_State *L) { unsigned int i; - int iotag = lua_newtag(); - lua_newtag(); /* alloc CLOSEDTAG: assume that CLOSEDTAG = iotag-1 */ + int iotag = lua_newtag(L); + lua_newtag(L); /* alloc CLOSEDTAG: assume that CLOSEDTAG = iotag-1 */ for (i=0; i