summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>1997-06-26 17:39:10 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>1997-06-26 17:39:10 -0300
commitda585783e33f92f8dff6fd47a89671494adc11e0 (patch)
treeaa1a0f59eea602c6622427b573e9b85e94f79b66
parente81f1841644405845e7de6bd70a0f074cced3d81 (diff)
downloadlua-github-da585783e33f92f8dff6fd47a89671494adc11e0.tar.gz
new method to handle current files, with global variables
_INPUT and _OUTPUT.
-rw-r--r--iolib.c89
-rw-r--r--manual.tex91
2 files changed, 105 insertions, 75 deletions
diff --git a/iolib.c b/iolib.c
index 3a532c8a..d367097e 100644
--- a/iolib.c
+++ b/iolib.c
@@ -10,8 +10,6 @@
#include "lualib.h"
-FILE *lua_infile, *lua_outfile;
-
int lua_tagio;
@@ -39,59 +37,80 @@ static void pushresult (int i)
}
-static void closefile (FILE *f)
+
+static FILE *getfile (char *name)
{
- if (f == stdin || f == stdout)
- return;
- if (f == lua_infile)
- lua_infile = stdin;
- if (f == lua_outfile)
- lua_outfile = stdout;
+ lua_Object f = lua_getglobal(name);
+ if (lua_tag(f) != lua_tagio)
+ luaL_verror("global variable %s is not a file handle", name);
+ return lua_getuserdata(f);
+}
+
+
+static void closefile (char *name)
+{
+ FILE *f = getfile(name);
+ if (f == stdin || f == stdout) return;
if (pclose(f) == -1)
fclose(f);
}
+static void setfile (FILE *f, char *name)
+{
+ lua_pushusertag(f, lua_tagio);
+ lua_setglobal(name);
+}
+
+
+static void setreturn (FILE *f, char *name)
+{
+ setfile(f, name);
+ lua_pushusertag(f, lua_tagio);
+}
+
static void io_readfrom (void)
{
+ FILE *current;
lua_Object f = lua_getparam(1);
- if (f == LUA_NOOBJECT)
- closefile(lua_infile); /* restore standart input */
+ if (f == LUA_NOOBJECT) {
+ closefile("_INPUT");
+ current = stdin;
+ }
else if (lua_tag(f) == lua_tagio)
- lua_infile = lua_getuserdata(f);
+ current = lua_getuserdata(f);
else {
char *s = luaL_check_string(1);
- FILE *fp = (*s == '|') ? popen(s+1, "r") : fopen(s, "r");
- if (fp)
- lua_infile = fp;
- else {
+ current = (*s == '|') ? popen(s+1, "r") : fopen(s, "r");
+ if (current == NULL) {
pushresult(0);
return;
}
}
- lua_pushusertag(lua_infile, lua_tagio);
+ setreturn(current, "_INPUT");
}
static void io_writeto (void)
{
+ FILE *current;
lua_Object f = lua_getparam(1);
- if (f == LUA_NOOBJECT)
- closefile(lua_outfile); /* restore standart output */
+ if (f == LUA_NOOBJECT) {
+ closefile("_OUTPUT");
+ current = stdout;
+ }
else if (lua_tag(f) == lua_tagio)
- lua_outfile = lua_getuserdata(f);
+ current = lua_getuserdata(f);
else {
char *s = luaL_check_string(1);
- FILE *fp = (*s == '|') ? popen(s+1,"w") : fopen(s,"w");
- if (fp)
- lua_outfile = fp;
- else {
+ current = (*s == '|') ? popen(s+1,"w") : fopen(s,"w");
+ if (current == NULL) {
pushresult(0);
return;
}
}
- lua_pushusertag(lua_outfile, lua_tagio);
+ setreturn(current, "_OUTPUT");
}
@@ -99,10 +118,8 @@ static void io_appendto (void)
{
char *s = luaL_check_string(1);
FILE *fp = fopen (s, "a");
- if (fp != NULL) {
- lua_outfile = fp;
- lua_pushusertag(lua_outfile, lua_tagio);
- }
+ if (fp != NULL)
+ setreturn(fp, "_OUTPUT");
else
pushresult(0);
}
@@ -112,6 +129,7 @@ static void io_appendto (void)
static void io_read (void)
{
+ FILE *f = getfile("_INPUT");
char *buff;
char *p = luaL_opt_string(1, "[^\n]*{\n}");
int inskip = 0; /* to control {skips} */
@@ -131,7 +149,7 @@ static void io_read (void)
else {
char *ep = luaL_item_end(p); /* get what is next */
int m; /* match result */
- if (c == NEED_OTHER) c = getc(lua_infile);
+ if (c == NEED_OTHER) c = getc(f);
m = (c == EOF) ? 0 : luaL_singlematch((char)c, p);
if (m) {
if (inskip == 0) luaI_addchar(c);
@@ -152,7 +170,7 @@ static void io_read (void)
}
} break_while:
if (c >= 0) /* not EOF nor NEED_OTHER? */
- ungetc(c, lua_infile);
+ ungetc(c, f);
buff = luaI_addchar(0);
if (*buff != 0 || *p == 0) /* read something or did not fail? */
lua_pushstring(buff);
@@ -161,11 +179,12 @@ static void io_read (void)
static void io_write (void)
{
+ FILE *f = getfile("_OUTPUT");
int arg = 1;
int status = 1;
char *s;
while ((s = luaL_opt_string(arg++, NULL)) != NULL)
- status = status && (fputs(s, lua_outfile) != EOF);
+ status = status && (fputs(s, f) != EOF);
pushresult(status);
}
@@ -300,7 +319,11 @@ static struct luaL_reg iolib[] = {
void iolib_open (void)
{
lua_tagio = lua_newtag();
- lua_infile=stdin; lua_outfile=stdout;
+ setfile(stdin, "_INPUT");
+ setfile(stdout, "_OUTPUT");
+ setfile(stdin, "_STDIN");
+ setfile(stdout, "_STDOUT");
+ setfile(stderr, "_STDERR");
luaL_openlib(iolib, (sizeof(iolib)/sizeof(iolib[0])));
lua_pushcfunction(errorfb);
lua_seterrormethod();
diff --git a/manual.tex b/manual.tex
index 210721b2..1bab89c1 100644
--- a/manual.tex
+++ b/manual.tex
@@ -1,4 +1,4 @@
-% $Id: manual.tex,v 2.4 1997/06/19 18:49:40 roberto Exp roberto $
+% $Id: manual.tex,v 2.5 1997/06/20 19:28:16 roberto Exp roberto $
\documentstyle[fullpage,11pt,bnf]{article}
@@ -38,7 +38,7 @@ Waldemar Celes
\tecgraf\ --- Computer Science Department --- PUC-Rio
}
-\date{\small \verb$Date: 1997/06/19 18:49:40 $}
+\date{\small \verb$Date: 1997/06/20 19:28:16 $}
\maketitle
@@ -1034,7 +1034,7 @@ This method cannot be set for tables with default tag.
function settable_event (table, index, value)
local tm = gettagmethod(tag(table), "settable")
if tm then
- return tm(table, index, value)
+ tm(table, index, value)
elseif type(table) ~= "table" then
error("indexed expression not a table")
else
@@ -1598,11 +1598,10 @@ If \verb|retmode| is absent,
all results from \verb|func| are just returned by the call.
If \verb|retmode| is equal to \verb|"pack"|,
the results are {\em packed\/} in a single table.\index{packed results}
-That is, \verb|call| returns just one table.
-At index \verb|n|, the table has the total number of results
+That is, \verb|call| returns just one table;
+at index \verb|n|, the table has the total number of results
from the call;
the first result is at index 1, etc.
-
For instance, the following calls produce the following results:
\begin{verbatim}
a = call(sin, {5}) --> a = 0.0871557 = sin(5)
@@ -1666,7 +1665,9 @@ semantically, there is no difference between a
field not present in a table or a field with value \nil.
Therefore, the function only considers fields with non \nil\ values.
The order in which the indices are enumerated is not specified,
-{\em not even for numeric indices}.
+{\em not even for numeric indices}
+(to traverse a table in numeric order,
+use a counter).
If the table is modified in any way during a traversal,
the semantics of \verb|next| is undefined.
@@ -1904,7 +1905,7 @@ stands for the value of the n-th captured substring.
If \verb|repl| is a function, then this function is called every time a
match occurs, with the following arguments:
-If \verb|table| is present, the the first argument is this table
+If \verb|table| is present, then the first argument is this table
and the second one is a match counter (1 for the first call).
Independently of these two optional arguments,
all captured substrings are passed as arguments,
@@ -2072,10 +2073,21 @@ range \Math{[0,1)}.
\subsection{I/O Facilities} \label{libio}
-All input and output operations in Lua are done over two {\em current\/} files:
-one for reading and one for writing.
-Initially, the current input file is \verb|stdin|,
-and the current output file is \verb|stdout|.
+All input and output operations in Lua are done over two
+\Def{file handles}, one for reading and one for writing.
+These handles are stored in two Lua global variables,
+called \verb|_INPUT| and \verb|_OUTPUT|.
+The global variables
+\verb|_STDIN|, \verb|_STDOUT| and \verb|_STDERR|
+are initialized with file descriptors for
+\verb|stdin|, \verb|stdout| and \verb|stderr|.
+Initially, \verb|_INPUT=_STDIN| and \verb|_OUTPUT=_STDOUT|.
+\Deffunc{_INPUT}\Deffunc{_OUTPUT}
+\Deffunc{_STDIN}\Deffunc{_STDOUT}\Deffunc{_STDERR}
+
+A file handle is a userdata containing the file stream \verb|FILE*|,
+and with a distinctive tag created by the I/O library.
+
Unless otherwise stated,
all I/O functions return \nil\ on failure and
@@ -2083,18 +2095,16 @@ some value different from \nil\ on success.
\subsubsection*{\ff {\tt readfrom (filename)}}\Deffunc{readfrom}
-This function may be called in three ways.
-When called with a file name,
-it opens the named file,
-sets it as the {\em current\/} input file,
-and returns a {\em handle\/} to the file
-(this handle is a userdata containing the file stream \verb|FILE*|).
+This function may be called in two ways.
+When called with a file name, it opens the named file,
+sets its handle as the value of \verb|_INPUT|,
+and returns this value.
It does not close the current input file.
-When called with a file handle returned by a previous call,
-it restores the file as the current input.
+%When called with a file handle returned by a previous call,
+%it simply assigns it to \verb|_INPUT|.
When called without parameters,
-it closes the current input file,
-and restores \verb|stdin| as the current input file.
+it closes the \verb|_INPUT| file,
+and restores \verb|stdin| as the value of \verb|_INPUT|.
If this function fails, it returns \nil,
plus a string describing the error.
@@ -2105,28 +2115,26 @@ plus a string describing the error.
then a \Index{piped input} is open, via function \IndexVerb{popen}.
Not all systems implement pipes.
Moreover,
-the number of files that can be open at the same time is usually limited and
-depends on the system.
+the number of files that can be open at the same time is
+usually limited and depends on the system.
\end{quotation}
\subsubsection*{\ff {\tt writeto (filename)}}\Deffunc{writeto}
-This function may be called in three ways.
+This function may be called in two ways.
When called with a file name,
it opens the named file,
-sets it as the {\em current\/} output file,
-and returns a {\em handle\/} to the file
-(this handle is a user data containing the file stream \verb|FILE*|).
+sets its handle as the value of \verb|_OUTPUT|,
+and returns this value.
It does not close the current output file.
Notice that, if the file already exists,
then it will be {\em completely erased\/} with this operation.
-When called with a file handle returned by a previous call,
-it restores the file as the current output.
+%When called with a file handle returned by a previous call,
+%it restores the file as the current output.
When called without parameters,
-this function closes the current output file,
-and restores \verb|stdout| as the current output file.
+this function closes the \verb|_OUTPUT| file,
+and restores \verb|stdout| as the value of \verb|_OUTPUT|.
\index{closing a file}
-%%LHF: nao tem como escrever em stderr, tem?
If this function fails, it returns \nil,
plus a string describing the error.
@@ -2137,16 +2145,14 @@ plus a string describing the error.
then a \Index{piped output} is open, via function \IndexVerb{popen}.
Not all systems implement pipes.
Moreover,
-the number of files that can be open at the same time is usually limited and
-depends on the system.
+the number of files that can be open at the same time is
+usually limited and depends on the system.
\end{quotation}
\subsubsection*{\ff {\tt appendto (filename)}}\Deffunc{appendto}
This function opens a file named \verb|filename| and sets it as the
-{\em current\/} output file.
-It returns the file handle,
-or \nil\ in case of error.
+value of \verb|_OUTPUT|.
Unlike the \verb|writeto| operation,
this function does not erase any previous content of the file.
If this function fails, it returns \nil,
@@ -2174,7 +2180,7 @@ The file must be explicitly removed when no longer needed.
\subsubsection*{\ff {\tt read ([readpattern])}}\Deffunc{read}
-This function reads the current input
+This function reads the file \verb|_INPUT|
according to a read pattern, that specifies how much to read;
characters are read from the current input file until
the read pattern fails or ends.
@@ -2196,7 +2202,7 @@ from the input if it belongs to the class;
it never fails.
A character class followed by \verb|*| reads until a character that
does not belong to the class, or end of file;
-since it can match a sequence of zero characteres, it never fails.%
+since it can match a sequence of zero characters, it never fails.%
\footnote{
Notice that the behavior of read patterns is different from
the regular pattern matching behavior,
@@ -2220,6 +2226,7 @@ Following are some examples of read patterns and their meanings:
This is the default pattern.
\item \verb|"{%s*}%S%S*"| returns the next word
(maximal sequence of non white-space characters),
+skipping spaces if necessary,
or \nil\ on end of file.
\item \verb|"{%s*}[+-]?%d%d*"| returns the next integer
or \nil\ if the next characters do not conform to an integer format.
@@ -2228,10 +2235,10 @@ or \nil\ if the next characters do not conform to an integer format.
\subsubsection*{\ff {\tt write (value1, ...)}}\Deffunc{write}
This function writes the value of each of its arguments to the
-current output file.
+file \verb|_OUTPUT|.
The arguments must be strings or numbers.
To write other values,
-use \verb|tostring| before \verb|write|.
+use \verb|tostring| or \verb|format| before \verb|write|.
If this function fails, it returns \nil,
plus a string describing the error.