commit cc117253c83ec32d226a8f2226d5ca144804f873
parent 8e226e6a09390a80fde98f192833fc85a5537376
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Fri, 21 Aug 1998 14:43:23 -0300
new implementation for error handling: on error, function _ERRORMESSAGE
is called, which in turn calls _ALERT to write a message to stderr.
Diffstat:
M | lapi.c | | | 17 | ++++++++--------- |
M | lbuiltin.c | | | 19 | +++++++++++++++++-- |
M | ldo.c | | | 33 | +++++++++++---------------------- |
M | liolib.c | | | 87 | ++++++++++++++++++++++++++++++++++++++++--------------------------------------- |
M | lstate.h | | | 3 | +-- |
M | ltm.c | | | 4 | +--- |
M | lua.h | | | 7 | ++++--- |
M | manual.tex | | | 99 | ++++++++++++++++++++++++++++++++++++++----------------------------------------- |
8 files changed, 133 insertions(+), 136 deletions(-)
diff --git a/lapi.c b/lapi.c
@@ -1,5 +1,5 @@
/*
-** $Id: lapi.c,v 1.25 1998/06/05 22:17:44 roberto Exp roberto $
+** $Id: lapi.c,v 1.26 1998/07/12 16:16:02 roberto Exp roberto $
** Lua API
** See Copyright Notice in lua.h
*/
@@ -29,9 +29,8 @@ char lua_ident[] = "$Lua: " LUA_VERSION " " LUA_COPYRIGHT " $\n"
-TObject *luaA_Address (lua_Object o)
-{
- return Address(o);
+TObject *luaA_Address (lua_Object o) {
+ return (o != LUA_NOOBJECT) ? Address(o) : NULL;
}
@@ -150,12 +149,12 @@ lua_Object lua_settagmethod (int tag, char *event)
}
-lua_Object lua_seterrormethod (void)
-{
- TObject temp = L->errorim;
+lua_Object lua_seterrormethod (void) {
+ lua_Object temp;
checkCparams(1);
- L->errorim = *(--L->stack.top);
- return put_luaObject(&temp);
+ temp = lua_getglobal("_ERRORMESSAGE");
+ lua_setglobal("_ERRORMESSAGE");
+ return temp;
}
diff --git a/lbuiltin.c b/lbuiltin.c
@@ -1,5 +1,5 @@
/*
-** $Id: lbuiltin.c,v 1.32 1998/06/29 18:24:06 roberto Exp roberto $
+** $Id: lbuiltin.c,v 1.33 1998/07/12 16:16:43 roberto Exp roberto $
** Built-in functions
** See Copyright Notice in lua.h
*/
@@ -192,6 +192,19 @@ static void luaI_print (void) {
}
+static void luaB_message (void) {
+ fputs(luaL_check_string(1), stderr);
+}
+
+
+static void error_message (void) {
+ char buff[200];
+ sprintf(buff, "lua error: %.180s\n", luaL_check_string(1));
+ lua_pushstring(buff);
+ lua_call("_ALERT");
+}
+
+
static void luaI_type (void)
{
lua_Object o = luaL_nonnullarg(1);
@@ -568,6 +581,7 @@ static struct luaL_reg int_funcs[] = {
{"copytagmethods", copytagmethods},
{"dostring", internaldostring},
{"error", luaI_error},
+ {"_ERRORMESSAGE", error_message},
{"foreach", foreach},
{"foreachvar", foreachvar},
{"getglobal", getglobal},
@@ -588,7 +602,8 @@ static struct luaL_reg int_funcs[] = {
{"tonumber", luaB_tonumber},
{"tostring", to_string},
{"tag", luatag},
- {"type", luaI_type}
+ {"type", luaI_type},
+ {"_ALERT", luaB_message}
};
diff --git a/ldo.c b/ldo.c
@@ -1,5 +1,5 @@
/*
-** $Id: ldo.c,v 1.27 1998/06/19 18:47:06 roberto Exp roberto $
+** $Id: ldo.c,v 1.28 1998/07/12 16:14:34 roberto Exp roberto $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@@ -17,6 +17,7 @@
#include "lobject.h"
#include "lparser.h"
#include "lstate.h"
+#include "lstring.h"
#include "ltm.h"
#include "lua.h"
#include "luadebug.h"
@@ -32,27 +33,13 @@
-/*
-** Error messages
-*/
-
-static void stderrorim (void)
-{
- fprintf(stderr, "lua error: %s\n", lua_getstring(lua_getparam(1)));
-}
-
-
-
#define STACK_UNIT 128
-void luaD_init (void)
-{
+void luaD_init (void) {
L->stack.stack = luaM_newvector(STACK_UNIT, TObject);
L->stack.top = L->stack.stack;
L->stack.last = L->stack.stack+(STACK_UNIT-1);
- ttype(&L->errorim) = LUA_T_CPROTO;
- fvalue(&L->errorim) = stderrorim;
}
@@ -246,12 +233,13 @@ void luaD_travstack (int (*fn)(TObject *))
-static void message (char *s)
-{
- TObject im = L->errorim;
- if (ttype(&im) != LUA_T_NIL) {
+static void message (char *s) {
+ TObject *em = &(luaS_new("_ERRORMESSAGE")->u.s.globalval);
+ if (ttype(em) != LUA_T_NIL) {
+ *L->stack.top = *em;
+ incr_top;
lua_pushstring(s);
- luaD_callTM(&im, 1, 0);
+ luaD_calln(1, 0);
}
}
@@ -264,7 +252,8 @@ void lua_error (char *s)
if (L->errorJmp)
longjmp(*((jmp_buf *)L->errorJmp), 1);
else {
- fprintf (stderr, "lua: exit(1). Unable to recover\n");
+ lua_pushstring("lua: exit(1). Unable to recover.\n");
+ lua_call("_ALERT");
exit(1);
}
}
diff --git a/liolib.c b/liolib.c
@@ -1,5 +1,5 @@
/*
-** $Id: liolib.c,v 1.20 1998/06/05 22:17:44 roberto Exp roberto $
+** $Id: liolib.c,v 1.21 1998/06/18 17:04:28 roberto Exp roberto $
** Standard I/O (and system) library
** See Copyright Notice in lua.h
*/
@@ -353,71 +353,75 @@ static void io_debug (void)
}
-static void lua_printstack (FILE *f)
-{
+#define MESSAGESIZE 150
+#define MAXMESSAGE (MESSAGESIZE*10)
+
+static void errorfb (void) {
+ char buff[MAXMESSAGE];
int level = 1; /* skip level 0 (it's this function) */
lua_Object func;
+ sprintf(buff, "lua: %.200s\n", lua_getstring(lua_getparam(1)));
while ((func = lua_stackedfunction(level++)) != LUA_NOOBJECT) {
char *name;
int currentline;
- char *filename;
+ char *chunkname;
int linedefined;
- lua_funcinfo(func, &filename, &linedefined);
- fprintf(f, (level==2) ? "Active Stack:\n\t" : "\t");
+ lua_funcinfo(func, &chunkname, &linedefined);
+ strcat(buff, (level==2) ? "Active Stack:\n\t" : "\t");
+ if (strlen(buff) > MAXMESSAGE-MESSAGESIZE) {
+ strcat(buff, "...\n");
+ break; /* buffer is full */
+ }
switch (*lua_getobjname(func, &name)) {
case 'g':
- fprintf(f, "function %s", name);
+ sprintf(buff+strlen(buff), "function %.50s", name);
break;
case 't':
- fprintf(f, "`%s' tag method", name);
+ sprintf(buff+strlen(buff), "`%.50s' tag method", name);
break;
default: {
if (linedefined == 0)
- fprintf(f, "main of %s", filename);
+ sprintf(buff+strlen(buff), "main of %.50s", chunkname);
else if (linedefined < 0)
- fprintf(f, "%s", filename);
+ sprintf(buff+strlen(buff), "%.50s", chunkname);
else
- fprintf(f, "function (%s:%d)", filename, linedefined);
- filename = NULL;
+ sprintf(buff+strlen(buff), "function (%.50s:%d)",
+ chunkname, linedefined);
+ chunkname = NULL;
}
}
if ((currentline = lua_currentline(func)) > 0)
- fprintf(f, " at line %d", currentline);
- if (filename)
- fprintf(f, " [in file %s]", filename);
- fprintf(f, "\n");
+ sprintf(buff+strlen(buff), " at line %d", currentline);
+ if (chunkname)
+ sprintf(buff+strlen(buff), " [in chunk %.50s]", chunkname);
+ strcat(buff, "\n");
}
-}
-
-
-static void errorfb (void)
-{
- fprintf(stderr, "lua: %s\n", lua_getstring(lua_getparam(1)));
- lua_printstack(stderr);
+ lua_pushstring(buff);
+ lua_call("_ALERT");
}
static struct luaL_reg iolib[] = {
-{"setlocale", setloc},
-{"execute", io_execute},
-{"remove", io_remove},
-{"rename", io_rename},
-{"tmpname", io_tmpname},
-{"getenv", io_getenv},
-{"date", io_date},
-{"clock", io_clock},
-{"exit", io_exit},
-{"debug", io_debug},
-{"print_stack", errorfb}
+ {"setlocale", setloc},
+ {"execute", io_execute},
+ {"remove", io_remove},
+ {"rename", io_rename},
+ {"tmpname", io_tmpname},
+ {"getenv", io_getenv},
+ {"date", io_date},
+ {"clock", io_clock},
+ {"exit", io_exit},
+ {"debug", io_debug},
+ {"_ERRORMESSAGE", errorfb}
};
static struct luaL_reg iolibtag[] = {
-{"readfrom", io_readfrom},
-{"writeto", io_writeto},
-{"appendto", io_appendto},
-{"read", io_read},
-{"write", io_write}
+ {"readfrom", io_readfrom},
+ {"writeto", io_writeto},
+ {"appendto", io_appendto},
+ {"read", io_read},
+ {"write", io_write}
};
static void openwithtags (void)
@@ -439,10 +443,7 @@ static void openwithtags (void)
setfile(stderr, "_STDERR", iotag);
}
-void lua_iolibopen (void)
-{
+void lua_iolibopen (void) {
luaL_openlib(iolib, (sizeof(iolib)/sizeof(iolib[0])));
openwithtags();
- lua_pushcfunction(errorfb);
- lua_seterrormethod();
}
diff --git a/lstate.h b/lstate.h
@@ -1,5 +1,5 @@
/*
-** $Id: lstate.h,v 1.10 1998/06/19 16:14:09 roberto Exp roberto $
+** $Id: lstate.h,v 1.11 1998/06/24 13:33:00 roberto Exp roberto $
** Global State
** See Copyright Notice in lua.h
*/
@@ -61,7 +61,6 @@ struct lua_State {
struct C_Lua_Stack Cblocks[MAX_C_BLOCKS];
int numCblocks; /* number of nested Cblocks */
/* global state */
- TObject errorim; /* error tag method */
GCnode rootproto; /* list of all prototypes */
GCnode rootcl; /* list of all closures */
GCnode roottable; /* list of all tables */
diff --git a/ltm.c b/ltm.c
@@ -1,5 +1,5 @@
/*
-** $Id: ltm.c,v 1.15 1998/03/11 13:59:50 roberto Exp roberto $
+** $Id: ltm.c,v 1.16 1998/06/18 16:57:03 roberto Exp roberto $
** Tag methods
** See Copyright Notice in lua.h
*/
@@ -158,8 +158,6 @@ void luaT_settagmethod (int t, char *event, TObject *func)
char *luaT_travtagmethods (int (*fn)(TObject *))
{
int e;
- if (fn(&L->errorim))
- return "error";
for (e=IM_GETTABLE; e<=IM_FUNCTION; e++) { /* ORDER IM */
int t;
for (t=0; t>=L->last_tag; t--)
diff --git a/lua.h b/lua.h
@@ -1,5 +1,5 @@
/*
-** $Id: lua.h,v 1.22 1998/06/15 21:34:14 roberto Exp roberto $
+** $Id: lua.h,v 1.23 1998/06/18 16:51:53 roberto Exp roberto $
** Lua - An Extensible Extension Language
** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil
** e-mail: lua@tecgraf.puc-rio.br
@@ -11,7 +11,7 @@
#ifndef lua_h
#define lua_h
-#define LUA_VERSION "Lua 3.1"
+#define LUA_VERSION "Lua 3.2 (alpha)"
#define LUA_COPYRIGHT "Copyright (C) 1994-1998 TeCGraf, PUC-Rio"
#define LUA_AUTHORS "W. Celes, R. Ierusalimschy & L. H. de Figueiredo"
@@ -32,7 +32,6 @@ lua_State *lua_setstate (lua_State *st);
lua_Object lua_settagmethod (int tag, char *event); /* In: new method */
lua_Object lua_gettagmethod (int tag, char *event);
-lua_Object lua_seterrormethod (void); /* In: new method */
int lua_newtag (void);
int lua_copytagmethods (int tagto, int tagfrom);
@@ -125,6 +124,8 @@ int (lua_clonetag) (int t);
#define lua_clonetag(t) lua_copytagmethods(lua_newtag(), (t))
+lua_Object lua_seterrormethod (void); /* In: new method */
+
/* ==========================================================================
** for compatibility with old versions. Avoid using these macros/functions
** If your program does need any of these, define LUA_COMPAT2_5
diff --git a/manual.tex b/manual.tex
@@ -1,8 +1,10 @@
-% $Id: manual.tex,v 1.16 1998/06/19 18:47:06 roberto Exp roberto $
+% $Id: manual.tex,v 1.17 1998/06/29 18:09:28 roberto Exp roberto $
\documentclass[11pt]{article}
\usepackage{fullpage,bnf}
+\catcode`\_=12
+
\newcommand{\See}[1]{Section~\ref{#1}}
\newcommand{\see}[1]{(see \See{#1})}
\newcommand{\M}[1]{\emph{#1}}
@@ -19,7 +21,7 @@
\newcommand{\ff}{$\bullet$\ }
-\newcommand{\Version}{3.1}
+\newcommand{\Version}{3.2 (alpha)}
\makeindex
@@ -39,7 +41,7 @@ Waldemar Celes
\tecgraf\ --- Computer Science Department --- PUC-Rio
}
-%\date{\small \verb$Date: 1998/06/19 18:47:06 $}
+%\date{\small \verb$Date: 1998/06/29 18:09:28 $}
\maketitle
@@ -810,7 +812,7 @@ If the function is called in a place that can hold many values
(syntactically denoted by the non-terminal \M{exp}),
then no adjustment is made.
Note that the only place that can hold many values
-is the last expression (or the only one) in an assignment
+is the last (or the only) expression in an assignment
or in a return statement; see examples below.
\begin{verbatim}
f(); -- adjusted to 0
@@ -1263,22 +1265,20 @@ Because Lua is an extension language,
all Lua actions start from C code in the host program
calling a function from the Lua library.
Whenever an error occurs during Lua compilation or execution,
-the \Def{error method} is called,
+function \verb|_ERRORMESSAGE| is called \Deffunc{_ERRORMESSAGE}
+(provided it is different from \nil),
and then the corresponding function from the library
(\verb|lua_dofile|, \verb|lua_dostring|,
\verb|lua_dobuffer|, or \verb|lua_callfunction|)
is terminated, returning an error condition.
-The only argument to the error method is a string
+The only argument to \verb|_ERRORMESSAGE| is a string
describing the error.
-The default method prints this message to \verb|stderr|.
-If needed, it is possible to change the error method with the
-function \verb|seterrormethod|,
-which gets the new error handler as its only parameter
-\see{pdf-seterrormethod}.
-The standard I/O library uses this facility to redefine the error method,
-using the debug facilities \see{debugI},
-in order to print some extra information,
+The default definition for this function calls \verb|_ALERT|,
+which prints the message to \verb|stderr| \see{alert}.
+The standard I/O library redefines \verb|_ERRORMESSAGE|,
+and uses the debug facilities \see{debugI}
+to print some extra information,
such as the call stack.
To provide more information about errors,
@@ -1347,11 +1347,11 @@ For that, you must set \verb|lua_state| back to \verb|NULL| before
calling \verb|lua_open|.
An easy way to do that is defining an auxiliary function:
\begin{verbatim}
-lua_State *lua_newstate (void) {
- lua_State *old = lua_setstate(NULL);
- lua_open();
- return lua_setstate(old);
-}
+ lua_State *lua_newstate (void) {
+ lua_State *old = lua_setstate(NULL);
+ lua_open();
+ return lua_setstate(old);
+ }
\end{verbatim}
This function creates a new state without changing the current state
of the interpreter.
@@ -1373,14 +1373,14 @@ If \verb|lua_state| is already \verb|NULL|,
\verb|lua_close| has no effect.
If you are using multiple states,
-you may find useful the following function,
+you may find useful to define the following function,
which releases a given state:
\begin{verbatim}
-void lua_freestate (lua_State *st) {
- lua_State *old = lua_setstate(st);
- lua_close();
- if (old != st) lua_setstate(old);
-}
+ void lua_freestate (lua_State *st) {
+ lua_State *old = lua_setstate(st);
+ lua_close();
+ if (old != st) lua_setstate(old);
+ }
\end{verbatim}
\subsection{Exchanging Values between C and Lua} \label{valuesCLua}
@@ -1736,18 +1736,10 @@ If the C function has been called from Lua,
then the corresponding Lua execution terminates,
as if an error had occurred inside Lua code.
Otherwise, the whole program terminates with a call to \verb|exit(1)|.
-The \verb|message| is passed to the error handler method.
+The \verb|message| is passed to the error handler function,
+\verb|_ERRORMESSAGE|.
If \verb|message| is \verb|NULL|,
-the error handler method is not called.
-
-The error handler method \see{error} can be
-changed with: \Deffunc{lua_seterrormethod}
-\begin{verbatim}
-lua_Object lua_seterrormethod (void);
-\end{verbatim}
-This function sets the object at the top of C2lua
-as the new error method,
-and returns the old error method value.
+\verb|_ERRORMESSAGE| is not called.
Tag methods can be changed with: \Deffunc{lua_settagmethod}
\begin{verbatim}
@@ -1885,7 +1877,7 @@ and \verb|lua_iolibopen|, declared in \verb|lualib.h|.
\subsection{Predefined Functions} \label{predefined}
-\subsubsection*{\ff \T{call (func, arg [, mode [, errmethod]])}}\Deffunc{call}
+\subsubsection*{\ff \T{call (func, arg [, mode [, errhandler]])}}\Deffunc{call}
\label{pdf-call}
This function calls function \verb|func| with
the arguments given by the table \verb|arg|.
@@ -1917,14 +1909,15 @@ if an error occurs during the function call,
the error is propagated.
If the string \verb|mode| contains \verb|"x"|,
then the call is \emph{protected}.\index{protected calls}
-In this mode, function \verb|call| does not generate an error,
+In this mode, function \verb|call| does not propagate an error,
whatever happens during the call.
Instead, it returns \nil\ to signal the error
-(besides calling the appropriated error method).
+(besides calling the appropriated error handler).
-If provided, \verb|errmethod| is temporarily set as the error method,
-while \verb|func| runs.
-As a particular case, if \verb|errmethod| is \nil,
+If provided,
+\verb|errhandler| is temporarily set as the error function
+\verb|_ERRORMESSAGE|, while \verb|func| runs.
+As a particular example, if \verb|errhandler| is \nil,
no error messages will be issued during the execution of the called function.
\subsubsection*{\ff \T{collectgarbage ([limit])}}\Deffunc{collectgarbage}
@@ -2055,9 +2048,16 @@ This function receives any number of arguments,
and prints their values using the strings returned by \verb|tostring|.
This function is not intended for formatted output,
but only as a quick way to show a value,
-for instance for error messages or debugging.
+for instance for debugging.
See \See{libio} for functions for formatted output.
+\subsubsection*{\ff \T{_ALERT (message)}}\Deffunc{alert}\label{alert}
+This function prints its only string argument to \IndexVerb{stderr}.
+All error messages in Lua are printed through this function.
+Therefore, a program may redefine it
+to change the way such messages are shown
+(for instance, for systems without \verb|stderr|).
+
\subsubsection*{\ff \T{tonumber (e [, base])}}\Deffunc{tonumber}
This function receives one argument,
and tries to convert it to a number.
@@ -2164,13 +2164,6 @@ Its full semantics is explained in \See{tag-method}.
The string \verb|name| does not need to be a
syntactically valid variable name.
-\subsubsection*{\ff \T{seterrormethod (newmethod)}}
-\label{pdf-seterrormethod}
-Sets the error handler \see{error}.
-\verb|newmethod| must be a function or \nil,
-in which case the error handler does nothing.
-Returns the old error handler.
-
\subsubsection*{\ff \T{settagmethod (tag, event, newmethod)}}
\Deffunc{settagmethod}
This function sets a new tag method to the given pair \M{(tag, event)}.
@@ -2930,7 +2923,7 @@ so any existing program that opens at least one standard
library before calling Lua does not need to be modified.
\item Function \verb|dostring| no longer accepts an optional second argument,
-with a temporary error method.
+with a temporary error handler.
This facility is now provided by function \verb|call|.
\item Function \verb|gsub| no longer accepts an optional fourth argument
@@ -2951,8 +2944,10 @@ programs should use an explicit assignment instead, such as
\end{itemize}
+% restore underscore to usual meaning
+\catcode`\_=8
+
\newcommand{\indexentry}[2]{\item {#1} #2}
-%\catcode`\_=12
\begin{theindex}
\input{manual.id}
\end{theindex}