new function lua_vpushstr' to replace uses of sprintf'

This commit is contained in:
Roberto Ierusalimschy 2002-05-07 14:36:56 -03:00
parent 71144e3ff0
commit dea6b6da94
15 changed files with 195 additions and 157 deletions

11
lapi.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: lapi.c,v 1.188 2002/05/06 15:51:41 roberto Exp roberto $ ** $Id: lapi.c,v 1.189 2002/05/06 19:05:10 roberto Exp roberto $
** Lua API ** Lua API
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -354,6 +354,13 @@ LUA_API void lua_pushstring (lua_State *L, const char *s) {
} }
LUA_API void lua_vpushstr (lua_State *L, const char *fmt, va_list argp) {
lua_lock(L);
luaO_vpushstr(L, fmt, argp);
lua_unlock(L);
}
LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
Closure *cl; Closure *cl;
lua_lock(L); lua_lock(L);
@ -514,7 +521,7 @@ LUA_API void lua_setmetatable (lua_State *L, int objindex) {
uvalue(obj)->uv.metatable = hvalue(mt); uvalue(obj)->uv.metatable = hvalue(mt);
break; break;
default: default:
luaO_verror(L, "cannot change the meta table of a %.20s", luaO_verror(L, "cannot change the meta table of a %s",
luaT_typenames[ttype(obj)]); luaT_typenames[ttype(obj)]);
} }
lua_unlock(L); lua_unlock(L);

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lauxlib.c,v 1.67 2002/05/01 20:40:42 roberto Exp roberto $ ** $Id: lauxlib.c,v 1.68 2002/05/06 19:05:10 roberto Exp roberto $
** Auxiliary functions for building Lua libraries ** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -142,38 +142,10 @@ LUALIB_API void luaL_opennamedlib (lua_State *L, const char *libname,
} }
static void vstr (lua_State *L, const char *fmt, va_list argp) {
luaL_Buffer b;
luaL_buffinit(L, &b);
for (;;) {
const char *e = strchr(fmt, '%');
if (e == NULL) break;
luaL_addlstring(&b, fmt, e-fmt);
switch (*(e+1)) {
case 's':
luaL_addstring(&b, va_arg(argp, char *));
break;
case 'd':
lua_pushnumber(L, va_arg(argp, int));
luaL_addvalue (&b);
break;
case '%':
luaL_putchar(&b, '%');
break;
default:
lua_error(L, "invalid format option");
}
fmt = e+2;
}
luaL_addstring(&b, fmt);
luaL_pushresult(&b);
}
LUALIB_API void luaL_vstr (lua_State *L, const char *fmt, ...) { LUALIB_API void luaL_vstr (lua_State *L, const char *fmt, ...) {
va_list argp; va_list argp;
va_start(argp, fmt); va_start(argp, fmt);
vstr(L, fmt, argp); lua_vpushstr(L, fmt, argp);
va_end(argp); va_end(argp);
} }
@ -181,7 +153,7 @@ LUALIB_API void luaL_vstr (lua_State *L, const char *fmt, ...) {
LUALIB_API int luaL_verror (lua_State *L, const char *fmt, ...) { LUALIB_API int luaL_verror (lua_State *L, const char *fmt, ...) {
va_list argp; va_list argp;
va_start(argp, fmt); va_start(argp, fmt);
vstr(L, fmt, argp); lua_vpushstr(L, fmt, argp);
va_end(argp); va_end(argp);
return lua_errorobj(L); return lua_errorobj(L);
} }

11
lcode.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: lcode.c,v 1.97 2002/04/24 20:07:46 roberto Exp roberto $ ** $Id: lcode.c,v 1.98 2002/05/06 15:51:41 roberto Exp roberto $
** Code generator for Lua ** Code generator for Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -23,11 +23,6 @@
#define hasjumps(e) ((e)->t != (e)->f) #define hasjumps(e) ((e)->t != (e)->f)
void luaK_error (LexState *ls, const char *msg) {
luaX_error(ls, msg, ls->t.token);
}
void luaK_nil (FuncState *fs, int from, int n) { void luaK_nil (FuncState *fs, int from, int n) {
Instruction *previous; Instruction *previous;
if (fs->pc > fs->lasttarget && /* no jumps to current position? */ if (fs->pc > fs->lasttarget && /* no jumps to current position? */
@ -67,7 +62,7 @@ static void luaK_fixjump (FuncState *fs, int pc, int dest) {
else { /* jump is relative to position following jump instruction */ else { /* jump is relative to position following jump instruction */
int offset = dest-(pc+1); int offset = dest-(pc+1);
if (abs(offset) > MAXARG_sBx) if (abs(offset) > MAXARG_sBx)
luaK_error(fs->ls, "control structure too long"); luaX_syntaxerror(fs->ls, "control structure too long");
SETARG_sBx(*jmp, offset); SETARG_sBx(*jmp, offset);
} }
} }
@ -182,7 +177,7 @@ static void luaK_checkstack (FuncState *fs, int n) {
int newstack = fs->freereg + n; int newstack = fs->freereg + n;
if (newstack > fs->f->maxstacksize) { if (newstack > fs->f->maxstacksize) {
if (newstack >= MAXSTACK) if (newstack >= MAXSTACK)
luaK_error(fs->ls, "function or expression too complex"); luaX_syntaxerror(fs->ls, "function or expression too complex");
fs->f->maxstacksize = cast(lu_byte, newstack); fs->f->maxstacksize = cast(lu_byte, newstack);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lcode.h,v 1.31 2002/04/09 18:49:30 roberto Exp roberto $ ** $Id: lcode.h,v 1.32 2002/04/24 20:07:46 roberto Exp roberto $
** Code generator for Lua ** Code generator for Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -41,7 +41,6 @@ typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_NOUNOPR } UnOpr;
#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) #define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)
void luaK_error (LexState *ls, const char *msg);
int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);
void luaK_nil (FuncState *fs, int from, int n); void luaK_nil (FuncState *fs, int from, int n);

View File

@ -1,5 +1,5 @@
/* /*
** $Id: ldblib.c,v 1.49 2002/05/01 20:40:42 roberto Exp roberto $ ** $Id: ldblib.c,v 1.50 2002/05/06 19:05:10 roberto Exp roberto $
** Interface from Lua to its debug API ** Interface from Lua to its debug API
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -34,7 +34,6 @@ static void settabsi (lua_State *L, const char *i, int v) {
static int getinfo (lua_State *L) { static int getinfo (lua_State *L) {
lua_Debug ar; lua_Debug ar;
const char *options = luaL_opt_string(L, 2, "flnSu"); const char *options = luaL_opt_string(L, 2, "flnSu");
char buff[20];
if (lua_isnumber(L, 1)) { if (lua_isnumber(L, 1)) {
if (!lua_getstack(L, (int)(lua_tonumber(L, 1)), &ar)) { if (!lua_getstack(L, (int)(lua_tonumber(L, 1)), &ar)) {
lua_pushnil(L); /* level out of range */ lua_pushnil(L); /* level out of range */
@ -42,9 +41,9 @@ static int getinfo (lua_State *L) {
} }
} }
else if (lua_isfunction(L, 1)) { else if (lua_isfunction(L, 1)) {
luaL_vstr(L, ">%s", options);
options = lua_tostring(L, -1);
lua_pushvalue(L, 1); lua_pushvalue(L, 1);
sprintf(buff, ">%.10s", options);
options = buff;
} }
else else
return luaL_argerror(L, 1, "function or level expected"); return luaL_argerror(L, 1, "function or level expected");
@ -170,7 +169,7 @@ static int setlinehook (lua_State *L) {
static int debug (lua_State *L) { static int debug (lua_State *L) {
for (;;) { for (;;) {
char buffer[250]; char buffer[250];
fprintf(stderr, "lua_debug> "); fputs("lua_debug> ", stderr);
if (fgets(buffer, sizeof(buffer), stdin) == 0 || if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
strcmp(buffer, "cont\n") == 0) strcmp(buffer, "cont\n") == 0)
return 0; return 0;

View File

@ -1,5 +1,5 @@
/* /*
** $Id: ldebug.c,v 1.110 2002/04/24 20:07:46 roberto Exp roberto $ ** $Id: ldebug.c,v 1.111 2002/05/02 13:06:20 roberto Exp roberto $
** Debug Interface ** Debug Interface
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -487,10 +487,10 @@ void luaG_typeerror (lua_State *L, const TObject *o, const char *op) {
if (isinstack(L->ci, o)) if (isinstack(L->ci, o))
kind = getobjname(L, L->ci, o - L->ci->base, &name); kind = getobjname(L, L->ci, o - L->ci->base, &name);
if (kind) if (kind)
luaO_verror(L, "attempt to %.30s %.20s `%.40s' (a %.10s value)", luaO_verror(L, "attempt to %s %s `%s' (a %s value)",
op, kind, name, t); op, kind, name, t);
else else
luaO_verror(L, "attempt to %.30s a %.10s value", op, t); luaO_verror(L, "attempt to %s a %s value", op, t);
} }
@ -513,8 +513,8 @@ void luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2) {
const char *t1 = luaT_typenames[ttype(p1)]; const char *t1 = luaT_typenames[ttype(p1)];
const char *t2 = luaT_typenames[ttype(p2)]; const char *t2 = luaT_typenames[ttype(p2)];
if (t1[2] == t2[2]) if (t1[2] == t2[2])
luaO_verror(L, "attempt to compare two %.10s values", t1); luaO_verror(L, "attempt to compare two %s values", t1);
else else
luaO_verror(L, "attempt to compare %.10s with %.10s", t1, t2); luaO_verror(L, "attempt to compare %s with %s", t1, t2);
} }

10
ldo.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: ldo.c,v 1.172 2002/04/22 14:40:50 roberto Exp roberto $ ** $Id: ldo.c,v 1.173 2002/05/01 20:40:42 roberto Exp roberto $
** Stack and Call structure of Lua ** Stack and Call structure of Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -436,8 +436,7 @@ int luaD_protectedparser (lua_State *L, ZIO *z, int bin) {
} }
else { else {
setobj(L->top++, &p.err); setobj(L->top++, &p.err);
if (status == LUA_ERRRUN) /* an error occurred: correct error code */ lua_assert(status != LUA_ERRRUN);
status = LUA_ERRSYNTAX;
} }
lua_unlock(L); lua_unlock(L);
return status; return status;
@ -459,9 +458,8 @@ static void message (lua_State *L, const TObject *msg, int nofunc) {
} }
else { /* call error function */ else { /* call error function */
setobj(L->top, m); setobj(L->top, m);
incr_top(L); setobj(L->top + 1, msg);
setobj(L->top, msg); L->top += 2;
incr_top(L);
luaD_call(L, L->top - 2, 1); luaD_call(L, L->top - 2, 1);
setobj(m, L->top - 1); setobj(m, L->top - 1);
} }

91
llex.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: llex.c,v 1.98 2002/03/08 19:07:01 roberto Exp roberto $ ** $Id: llex.c,v 1.99 2002/03/08 19:25:24 roberto Exp roberto $
** Lexical Analyzer ** Lexical Analyzer
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -11,6 +11,7 @@
#include "lua.h" #include "lua.h"
#include "ldo.h"
#include "llex.h" #include "llex.h"
#include "lobject.h" #include "lobject.h"
#include "lparser.h" #include "lparser.h"
@ -29,9 +30,9 @@ static const char *const token2string [] = {
"and", "break", "do", "else", "elseif", "and", "break", "do", "else", "elseif",
"end", "false", "for", "function", "global", "if", "end", "false", "for", "function", "global", "if",
"in", "local", "nil", "not", "or", "repeat", "in", "local", "nil", "not", "or", "repeat",
"return", "then", "true", "until", "while", "", "return", "then", "true", "until", "while", "*name",
"..", "...", "==", ">=", "<=", "~=", "..", "...", "==", ">=", "<=", "~=",
"", "", "<eof>" "*number", "*string", "<eof>"
}; };
@ -50,53 +51,57 @@ void luaX_init (lua_State *L) {
void luaX_checklimit (LexState *ls, int val, int limit, const char *msg) { void luaX_checklimit (LexState *ls, int val, int limit, const char *msg) {
if (val > limit) { if (val > limit) {
char buff[90]; msg = luaO_pushstr(ls->L, "too many %s (limit=%d)", msg, limit);
sprintf(buff, "too many %.40s (limit=%d)", msg, limit); luaX_syntaxerror(ls, msg);
luaX_error(ls, buff, ls->t.token);
} }
} }
static void luaX_syntaxerror (LexState *ls, const char *s, static void luaX_error (LexState *ls, const char *s, const char *token) {
const char *token) { lua_State *L = ls->L;
char buff[MAXSRC]; char buff[MAXSRC];
luaO_chunkid(buff, getstr(ls->source), MAXSRC); luaO_chunkid(buff, getstr(ls->source), MAXSRC);
luaO_verror(ls->L, luaO_pushstr(L, "%s;\n last token read: `%s' at line %d in %s",
"%.99s;\n last token read: `%.30s' at line %d in %.80s", s, token, ls->linenumber, buff);
s, token, ls->linenumber, buff); luaD_errorobj(L, L->top - 1, LUA_ERRSYNTAX);
} }
void luaX_token2str (int token, char *s) { void luaX_syntaxerror (LexState *ls, const char *msg) {
const char *lasttoken;
switch (ls->t.token) {
case TK_NAME:
lasttoken = luaO_pushstr(ls->L, "%s", getstr(ls->t.seminfo.ts));
break;
case TK_STRING:
lasttoken = luaO_pushstr(ls->L, "\"%s\"", getstr(ls->t.seminfo.ts));
break;
case TK_NUMBER:
lasttoken = luaO_pushstr(ls->L, "%f", ls->t.seminfo.r);
break;
default:
lasttoken = luaX_token2str(ls, ls->t.token);
break;
}
luaX_error(ls, msg, lasttoken);
}
const char *luaX_token2str (LexState *ls, int token) {
if (token < FIRST_RESERVED) { if (token < FIRST_RESERVED) {
lua_assert(token == (char)token); lua_assert(token == (char)token);
s[0] = (char)token; return luaO_pushstr(ls->L, "%c", token);
s[1] = '\0';
} }
else else
strcpy(s, token2string[token-FIRST_RESERVED]); return token2string[token-FIRST_RESERVED];
} }
static char *token2str_all (LexState *ls, int token, char *s) { static void luaX_lexerror (LexState *ls, const char *s, int token) {
luaX_token2str(token, s); if (token == TK_EOS)
if (s[0] == '\0') luaX_error(ls, s, luaX_token2str(ls, token));
return cast(char *, G(ls->L)->Mbuffer);
else else
return s; luaX_error(ls, s, cast(char *, G(ls->L)->Mbuffer));
}
void luaX_error (LexState *ls, const char *s, int token) {
char buff[TOKEN_LEN];
luaX_syntaxerror(ls, s, token2str_all(ls, token, buff));
}
static void luaX_invalidchar (LexState *ls, int c) {
char buff[8];
sprintf(buff, "0x%02X", (unsigned char)c);
luaX_syntaxerror(ls, "invalid control char", buff);
} }
@ -171,7 +176,7 @@ static void read_number (LexState *LS, int comma, SemInfo *seminfo) {
if (LS->current == '.') { if (LS->current == '.') {
save_and_next(L, LS, l); save_and_next(L, LS, l);
save(L, '\0', l); save(L, '\0', l);
luaX_error(LS, luaX_lexerror(LS,
"ambiguous syntax (decimal point x string concatenation)", "ambiguous syntax (decimal point x string concatenation)",
TK_NUMBER); TK_NUMBER);
} }
@ -191,7 +196,7 @@ static void read_number (LexState *LS, int comma, SemInfo *seminfo) {
} }
save(L, '\0', l); save(L, '\0', l);
if (!luaO_str2d(cast(char *, G(L)->Mbuffer), &seminfo->r)) if (!luaO_str2d(cast(char *, G(L)->Mbuffer), &seminfo->r))
luaX_error(LS, "malformed number", TK_NUMBER); luaX_lexerror(LS, "malformed number", TK_NUMBER);
} }
@ -209,7 +214,7 @@ static void read_long_string (LexState *LS, SemInfo *seminfo) {
switch (LS->current) { switch (LS->current) {
case EOZ: case EOZ:
save(L, '\0', l); save(L, '\0', l);
luaX_error(LS, (seminfo) ? "unfinished long string" : luaX_lexerror(LS, (seminfo) ? "unfinished long string" :
"unfinished long comment", TK_EOS); "unfinished long comment", TK_EOS);
break; /* to avoid warnings */ break; /* to avoid warnings */
case '[': case '[':
@ -251,10 +256,13 @@ static void read_string (LexState *LS, int del, SemInfo *seminfo) {
while (LS->current != del) { while (LS->current != del) {
checkbuffer(L, l); checkbuffer(L, l);
switch (LS->current) { switch (LS->current) {
case EOZ: case '\n': case EOZ:
save(L, '\0', l); save(L, '\0', l);
luaX_error(LS, "unfinished string", luaX_lexerror(LS, "unfinished string", TK_EOS);
(LS->current == EOZ) ? TK_EOS : TK_STRING); break; /* to avoid warnings */
case '\n':
save(L, '\0', l);
luaX_lexerror(LS, "unfinished string", TK_STRING);
break; /* to avoid warnings */ break; /* to avoid warnings */
case '\\': case '\\':
next(LS); /* do not save the `\' */ next(LS); /* do not save the `\' */
@ -279,7 +287,7 @@ static void read_string (LexState *LS, int del, SemInfo *seminfo) {
} while (++i<3 && isdigit(LS->current)); } while (++i<3 && isdigit(LS->current));
if (c > UCHAR_MAX) { if (c > UCHAR_MAX) {
save(L, '\0', l); save(L, '\0', l);
luaX_error(LS, "escape sequence too large", TK_STRING); luaX_lexerror(LS, "escape sequence too large", TK_STRING);
} }
save(L, c, l); save(L, c, l);
} }
@ -389,7 +397,8 @@ int luaX_lex (LexState *LS, SemInfo *seminfo) {
else { else {
int c = LS->current; int c = LS->current;
if (iscntrl(c)) if (iscntrl(c))
luaX_invalidchar(LS, c); luaX_error(LS, "invalid control char",
luaO_pushstr(LS->L, "char(%d)", c));
next(LS); next(LS);
return c; /* single-char tokens (+ - / ...) */ return c; /* single-char tokens (+ - / ...) */
} }

6
llex.h
View File

@ -1,5 +1,5 @@
/* /*
** $Id: llex.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ ** $Id: llex.h,v 1.42 2002/02/08 22:42:41 roberto Exp roberto $
** Lexical Analyzer ** Lexical Analyzer
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -65,8 +65,8 @@ void luaX_init (lua_State *L);
void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source); void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source);
int luaX_lex (LexState *LS, SemInfo *seminfo); int luaX_lex (LexState *LS, SemInfo *seminfo);
void luaX_checklimit (LexState *ls, int val, int limit, const char *msg); void luaX_checklimit (LexState *ls, int val, int limit, const char *msg);
void luaX_error (LexState *ls, const char *s, int token); void luaX_syntaxerror (LexState *ls, const char *s);
void luaX_token2str (int token, char *s); const char *luaX_token2str (LexState *ls, int token);
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lobject.c,v 1.77 2002/04/22 14:40:23 roberto Exp roberto $ ** $Id: lobject.c,v 1.78 2002/05/06 15:51:41 roberto Exp roberto $
** Some generic functions over Lua objects ** Some generic functions over Lua objects
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -16,6 +16,8 @@
#include "lmem.h" #include "lmem.h"
#include "lobject.h" #include "lobject.h"
#include "lstate.h" #include "lstate.h"
#include "lstring.h"
#include "lvm.h"
@ -89,17 +91,72 @@ int luaO_str2d (const char *s, lua_Number *result) {
} }
/* maximum length of a string format for `luaO_verror' */
#define MAX_VERROR 280
/* this function needs to handle only '%d' and '%.XXs' formats */ static void pushstr (lua_State *L, const char *str) {
void luaO_verror (lua_State *L, const char *fmt, ...) { setsvalue(L->top, luaS_new(L, str));
incr_top(L);
}
/* this function handles only `%d', `%c', %f, and `%s' formats */
const char *luaO_vpushstr (lua_State *L, const char *fmt, va_list argp) {
int n = 0;
for (;;) {
const char *e = strchr(fmt, '%');
if (e == NULL) break;
setsvalue(L->top, luaS_newlstr(L, fmt, e-fmt));
incr_top(L);
switch (*(e+1)) {
case 's':
pushstr(L, va_arg(argp, char *));
break;
case 'c': {
char buff[2];
buff[0] = va_arg(argp, int);
buff[1] = '\0';
pushstr(L, buff);
break;
}
case 'd':
setnvalue(L->top, va_arg(argp, int));
incr_top(L);
break;
case 'f':
setnvalue(L->top, va_arg(argp, lua_Number));
incr_top(L);
break;
case '%':
pushstr(L, "%");
break;
default: lua_assert(0);
}
n += 2;
fmt = e+2;
}
pushstr(L, fmt);
luaV_strconc(L, n+1, L->top - L->ci->base - 1);
L->top -= n;
return svalue(L->top - 1);
}
const char *luaO_pushstr (lua_State *L, const char *fmt, ...) {
const char *msg;
va_list argp; va_list argp;
char buff[MAX_VERROR]; /* to hold formatted message */
va_start(argp, fmt); va_start(argp, fmt);
vsprintf(buff, fmt, argp); msg = luaO_vpushstr(L, fmt, argp);
va_end(argp); va_end(argp);
luaD_runerror(L, buff); return msg;
}
void luaO_verror (lua_State *L, const char *fmt, ...) {
const char *msg;
va_list argp;
va_start(argp, fmt);
msg = luaO_vpushstr(L, fmt, argp);
va_end(argp);
luaD_runerror(L, msg);
} }
@ -108,31 +165,32 @@ void luaO_chunkid (char *out, const char *source, int bufflen) {
strncpy(out, source+1, bufflen); /* remove first char */ strncpy(out, source+1, bufflen); /* remove first char */
out[bufflen-1] = '\0'; /* ensures null termination */ out[bufflen-1] = '\0'; /* ensures null termination */
} }
else { else { /* out = "file `source'", or "file `...source'" */
if (*source == '@') { if (*source == '@') {
int l; int l;
source++; /* skip the `@' */ source++; /* skip the `@' */
bufflen -= sizeof("file `...%s'"); bufflen -= sizeof(" file `...' ");
l = strlen(source); l = strlen(source);
strcpy(out, "file `");
if (l>bufflen) { if (l>bufflen) {
source += (l-bufflen); /* get last part of file name */ source += (l-bufflen); /* get last part of file name */
sprintf(out, "file `...%.99s'", source); strcat(out, "...");
} }
else strcat(out, source);
sprintf(out, "file `%.99s'", source); strcat(out, "'");
} }
else { else {
int len = strcspn(source, "\n"); /* stop at first newline */ int len = strcspn(source, "\n"); /* stop at first newline */
bufflen -= sizeof("string \"%.*s...\""); bufflen -= sizeof(" string \"...\" ");
if (len > bufflen) len = bufflen; if (len > bufflen) len = bufflen;
strcpy(out, "string \"");
if (source[len] != '\0') { /* must truncate? */ if (source[len] != '\0') { /* must truncate? */
strcpy(out, "string \""); strncat(out, source, len);
out += strlen(out); strcat(out, "...");
strncpy(out, source, len);
strcpy(out+len, "...\"");
} }
else else
sprintf(out, "string \"%.99s\"", source); strcat(out, source);
strcat(out, "\"");
} }
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lobject.h,v 1.129 2002/04/05 18:54:31 roberto Exp roberto $ ** $Id: lobject.h,v 1.130 2002/05/06 15:51:41 roberto Exp roberto $
** Type definitions for Lua objects ** Type definitions for Lua objects
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -250,6 +250,8 @@ void *luaO_openspaceaux (lua_State *L, size_t n);
int luaO_equalObj (const TObject *t1, const TObject *t2); int luaO_equalObj (const TObject *t1, const TObject *t2);
int luaO_str2d (const char *s, lua_Number *result); int luaO_str2d (const char *s, lua_Number *result);
const char *luaO_vpushstr (lua_State *L, const char *fmt, va_list argp);
const char *luaO_pushstr (lua_State *L, const char *fmt, ...);
void luaO_verror (lua_State *L, const char *fmt, ...); void luaO_verror (lua_State *L, const char *fmt, ...);
void luaO_chunkid (char *out, const char *source, int len); void luaO_chunkid (char *out, const char *source, int len);

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lparser.c,v 1.177 2002/04/22 14:38:52 roberto Exp roberto $ ** $Id: lparser.c,v 1.178 2002/04/24 20:07:46 roberto Exp roberto $
** Lua Parser ** Lua Parser
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -66,10 +66,8 @@ static void lookahead (LexState *ls) {
static void error_expected (LexState *ls, int token) { static void error_expected (LexState *ls, int token) {
char buff[30], t[TOKEN_LEN]; luaX_syntaxerror(ls,
luaX_token2str(token, t); luaO_pushstr(ls->L, "`%s' expected", luaX_token2str(ls, token)));
sprintf(buff, "`%.10s' expected", t);
luaK_error(ls, buff);
} }
@ -80,7 +78,7 @@ static void check (LexState *ls, int c) {
} }
#define check_condition(ls,c,msg) { if (!(c)) luaK_error(ls, msg); } #define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); }
static int optional (LexState *ls, int c) { static int optional (LexState *ls, int c) {
@ -97,13 +95,9 @@ static void check_match (LexState *ls, int what, int who, int where) {
if (where == ls->linenumber) if (where == ls->linenumber)
error_expected(ls, what); error_expected(ls, what);
else { else {
char buff[70]; luaX_syntaxerror(ls, luaO_pushstr(ls->L,
char t_what[TOKEN_LEN], t_who[TOKEN_LEN]; "`%s' expected (to close `%s' at line %d)",
luaX_token2str(what, t_what); luaX_token2str(ls, what), luaX_token2str(ls, who), where));
luaX_token2str(who, t_who);
sprintf(buff, "`%.10s' expected (to close `%.10s' at line %d)",
t_what, t_who, where);
luaK_error(ls, buff);
} }
} }
next(ls); next(ls);
@ -256,7 +250,7 @@ static int singlevar_aux (FuncState *fs, TString *n, expdesc *var, int nd) {
if (var->k == VGLOBAL) { if (var->k == VGLOBAL) {
if (k == VNIL && nd && fs->defaultglob != NO_REG) { if (k == VNIL && nd && fs->defaultglob != NO_REG) {
if (fs->defaultglob == NO_REG1) if (fs->defaultglob == NO_REG1)
luaK_error(fs->ls, "undeclared global"); luaX_syntaxerror(fs->ls, "undeclared global");
init_exp(var, VLOCAL, fs->defaultglob); init_exp(var, VLOCAL, fs->defaultglob);
k = VGLOBAL; /* now there is a declaration */ k = VGLOBAL; /* now there is a declaration */
} }
@ -479,7 +473,7 @@ static void funcargs (LexState *ls, expdesc *f) {
switch (ls->t.token) { switch (ls->t.token) {
case '(': { /* funcargs -> `(' [ explist1 ] `)' */ case '(': { /* funcargs -> `(' [ explist1 ] `)' */
if (line != ls->lastline) if (line != ls->lastline)
luaK_error(ls, "ambiguous syntax (function call x new statement)"); luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)");
next(ls); next(ls);
if (ls->t.token == ')') /* arg list is empty? */ if (ls->t.token == ')') /* arg list is empty? */
args.k = VVOID; args.k = VVOID;
@ -500,7 +494,7 @@ static void funcargs (LexState *ls, expdesc *f) {
break; break;
} }
default: { default: {
luaK_error(ls, "function arguments expected"); luaX_syntaxerror(ls, "function arguments expected");
return; return;
} }
} }
@ -657,9 +651,10 @@ static void prefixexp (LexState *ls, expdesc *v) {
/* prefixexp -> NAME | '(' expr ')' */ /* prefixexp -> NAME | '(' expr ')' */
switch (ls->t.token) { switch (ls->t.token) {
case '(': { case '(': {
int line = ls->linenumber;
next(ls); next(ls);
expr(ls, v); expr(ls, v);
check(ls, ')'); check_match(ls, ')', '(', line);
luaK_dischargevars(ls->fs, v); luaK_dischargevars(ls->fs, v);
return; return;
} }
@ -676,7 +671,7 @@ static void prefixexp (LexState *ls, expdesc *v) {
return; return;
} }
default: { default: {
luaK_error(ls, "unexpected symbol"); luaX_syntaxerror(ls, "unexpected symbol");
return; return;
} }
} }
@ -1070,7 +1065,7 @@ static void forstat (LexState *ls, int line) {
switch (ls->t.token) { switch (ls->t.token) {
case '=': fornum(ls, varname, line); break; case '=': fornum(ls, varname, line); break;
case ',': case TK_IN: forlist(ls, varname); break; case ',': case TK_IN: forlist(ls, varname); break;
default: luaK_error(ls, "`=' or `in' expected"); default: luaX_syntaxerror(ls, "`=' or `in' expected");
} }
check_match(ls, TK_END, TK_FOR, line); check_match(ls, TK_END, TK_FOR, line);
leaveblock(fs); leaveblock(fs);
@ -1245,7 +1240,7 @@ static void breakstat (LexState *ls) {
bl = bl->previous; bl = bl->previous;
} }
if (!bl) if (!bl)
luaK_error(ls, "no loop to break"); luaX_syntaxerror(ls, "no loop to break");
if (upval) if (upval)
luaK_codeABC(fs, OP_CLOSE, bl->nactloc, 0, 0); luaK_codeABC(fs, OP_CLOSE, bl->nactloc, 0, 0);
luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
@ -1314,7 +1309,7 @@ static void parlist (LexState *ls) {
switch (ls->t.token) { switch (ls->t.token) {
case TK_DOTS: dots = 1; break; case TK_DOTS: dots = 1; break;
case TK_NAME: new_localvar(ls, str_checkname(ls), nparams++); break; case TK_NAME: new_localvar(ls, str_checkname(ls), nparams++); break;
default: luaK_error(ls, "<name> or `...' expected"); default: luaX_syntaxerror(ls, "<name> or `...' expected");
} }
next(ls); next(ls);
} while (!dots && optional(ls, ',')); } while (!dots && optional(ls, ','));

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lstate.c,v 1.91 2002/04/23 15:04:39 roberto Exp roberto $ ** $Id: lstate.c,v 1.92 2002/05/01 20:40:42 roberto Exp roberto $
** Global State ** Global State
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -30,7 +30,7 @@ static void close_state (lua_State *L);
** call `lua_setpanicf' ** call `lua_setpanicf'
*/ */
static int default_panic (lua_State *L) { static int default_panic (lua_State *L) {
fprintf(stderr, "unable to recover; exiting\n"); fputs("unable to recover; exiting\n", stderr);
return 0; return 0;
} }

6
lua.h
View File

@ -1,5 +1,5 @@
/* /*
** $Id: lua.h,v 1.130 2002/05/01 20:48:12 roberto Exp roberto $ ** $Id: lua.h,v 1.131 2002/05/06 19:05:10 roberto Exp roberto $
** Lua - An Extensible Extension Language ** Lua - An Extensible Extension Language
** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil ** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil
** e-mail: info@lua.org ** e-mail: info@lua.org
@ -12,6 +12,9 @@
#define lua_h #define lua_h
/* definition of `va_list' */
#include <stdarg.h>
/* definition of `size_t' */ /* definition of `size_t' */
#include <stddef.h> #include <stddef.h>
@ -141,6 +144,7 @@ LUA_API void lua_pushnil (lua_State *L);
LUA_API void lua_pushnumber (lua_State *L, lua_Number n); LUA_API void lua_pushnumber (lua_State *L, lua_Number n);
LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len); LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len);
LUA_API void lua_pushstring (lua_State *L, const char *s); LUA_API void lua_pushstring (lua_State *L, const char *s);
LUA_API void lua_vpushstr (lua_State *L, const char *fmt, va_list argp);
LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n); LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);
LUA_API void lua_pushboolean (lua_State *L, int b); LUA_API void lua_pushboolean (lua_State *L, int b);
LUA_API void lua_pushudataval (lua_State *L, void *p); LUA_API void lua_pushudataval (lua_State *L, void *p);

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lundump.c,v 1.44 2001/11/28 20:13:13 roberto Exp roberto $ ** $Id: lundump.c,v 1.45 2002/03/25 17:47:14 roberto Exp roberto $
** load pre-compiled Lua chunks ** load pre-compiled Lua chunks
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -27,7 +27,7 @@ static const char* ZNAME (ZIO* Z)
static void unexpectedEOZ (lua_State* L, ZIO* Z) static void unexpectedEOZ (lua_State* L, ZIO* Z)
{ {
luaO_verror(L,"unexpected end of file in `%.99s'",ZNAME(Z)); luaO_verror(L,"unexpected end of file in `%s'",ZNAME(Z));
} }
static int ezgetc (lua_State* L, ZIO* Z) static int ezgetc (lua_State* L, ZIO* Z)
@ -157,7 +157,7 @@ static void LoadConstants (lua_State* L, Proto* f, ZIO* Z, int swap)
tsvalue(o)=LoadString(L,Z,swap); tsvalue(o)=LoadString(L,Z,swap);
break; break;
default: default:
luaO_verror(L,"bad constant type (%d) in `%.99s'",ttype(o),ZNAME(Z)); luaO_verror(L,"bad constant type (%d) in `%s'",ttype(o),ZNAME(Z));
break; break;
} }
} }
@ -181,7 +181,7 @@ static Proto* LoadFunction (lua_State* L, TString* p, ZIO* Z, int swap)
LoadConstants(L,f,Z,swap); LoadConstants(L,f,Z,swap);
LoadCode(L,f,Z,swap); LoadCode(L,f,Z,swap);
#ifndef TRUST_BINARIES #ifndef TRUST_BINARIES
if (!luaG_checkcode(f)) luaO_verror(L,"bad code in `%.99s'",ZNAME(Z)); if (!luaG_checkcode(f)) luaO_verror(L,"bad code in `%s'",ZNAME(Z));
#endif #endif
return f; return f;
} }
@ -191,14 +191,14 @@ static void LoadSignature (lua_State* L, ZIO* Z)
const char* s=LUA_SIGNATURE; const char* s=LUA_SIGNATURE;
while (*s!=0 && ezgetc(L,Z)==*s) while (*s!=0 && ezgetc(L,Z)==*s)
++s; ++s;
if (*s!=0) luaO_verror(L,"bad signature in `%.99s'",ZNAME(Z)); if (*s!=0) luaO_verror(L,"bad signature in `%s'",ZNAME(Z));
} }
static void TestSize (lua_State* L, int s, const char* what, ZIO* Z) static void TestSize (lua_State* L, int s, const char* what, ZIO* Z)
{ {
int r=LoadByte(L,Z); int r=LoadByte(L,Z);
if (r!=s) if (r!=s)
luaO_verror(L,"virtual machine mismatch in `%.99s':\n" luaO_verror(L,"virtual machine mismatch in `%s':\n"
" size of %.20s is %d but read %d",ZNAME(Z),what,s,r); " size of %.20s is %d but read %d",ZNAME(Z),what,s,r);
} }
@ -212,11 +212,11 @@ static int LoadHeader (lua_State* L, ZIO* Z)
LoadSignature(L,Z); LoadSignature(L,Z);
version=LoadByte(L,Z); version=LoadByte(L,Z);
if (version>VERSION) if (version>VERSION)
luaO_verror(L,"`%.99s' too new:\n" luaO_verror(L,"`%s' too new:\n"
" read version %d.%d; expected at most %d.%d", " read version %d.%d; expected at most %d.%d",
ZNAME(Z),V(version),V(VERSION)); ZNAME(Z),V(version),V(VERSION));
if (version<VERSION0) /* check last major change */ if (version<VERSION0) /* check last major change */
luaO_verror(L,"`%.99s' too old:\n" luaO_verror(L,"`%s' too old:\n"
" read version %d.%d; expected at least %d.%d", " read version %d.%d; expected at least %d.%d",
ZNAME(Z),V(version),V(VERSION)); ZNAME(Z),V(version),V(VERSION));
swap=(luaU_endianness()!=LoadByte(L,Z)); /* need to swap bytes? */ swap=(luaU_endianness()!=LoadByte(L,Z)); /* need to swap bytes? */
@ -230,7 +230,7 @@ static int LoadHeader (lua_State* L, ZIO* Z)
TESTSIZE(sizeof(lua_Number), "number"); TESTSIZE(sizeof(lua_Number), "number");
x=LoadNumber(L,Z,swap); x=LoadNumber(L,Z,swap);
if ((long)x!=(long)tx) /* disregard errors in last bits of fraction */ if ((long)x!=(long)tx) /* disregard errors in last bits of fraction */
luaO_verror(L,"unknown number format in `%.99s':\n" luaO_verror(L,"unknown number format in `%s':\n"
" read " LUA_NUMBER_FMT "; expected " LUA_NUMBER_FMT, " read " LUA_NUMBER_FMT "; expected " LUA_NUMBER_FMT,
ZNAME(Z),x,tx); ZNAME(Z),x,tx);
return swap; return swap;
@ -248,7 +248,7 @@ Proto* luaU_undump (lua_State* L, ZIO* Z)
{ {
Proto* f=LoadChunk(L,Z); Proto* f=LoadChunk(L,Z);
if (zgetc(Z)!=EOZ) if (zgetc(Z)!=EOZ)
luaO_verror(L,"`%.99s' apparently contains more than one chunk",ZNAME(Z)); luaO_verror(L,"`%s' apparently contains more than one chunk",ZNAME(Z));
return f; return f;
} }