summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-06-24 19:38:20 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-06-24 19:38:20 +0000
commit29e85c811ddbf45cc8cb830012abefce8a92009a (patch)
tree0a1ef24f6ffc42389b48dd1f5a665ee9159b1561 /crawl-ref/source
parent7a6a09598a661b45bb3d96f48281ea7520370590 (diff)
downloadcrawl-ref-29e85c811ddbf45cc8cb830012abefce8a92009a.tar.gz
crawl-ref-29e85c811ddbf45cc8cb830012abefce8a92009a.zip
Hackily rewrite Lua chunk errors to reflect line numbers from the original
.des file so that level-designers can find the lines that are causing the problem. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1641 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/clua.cc38
-rw-r--r--crawl-ref/source/dat/clua/dungeon.lua4
-rw-r--r--crawl-ref/source/luadgn.cc71
-rw-r--r--crawl-ref/source/luadgn.h8
-rw-r--r--crawl-ref/source/mapdef.cc27
-rw-r--r--crawl-ref/source/mapdef.h3
-rw-r--r--crawl-ref/source/util/levcomp.ypp7
7 files changed, 131 insertions, 27 deletions
diff --git a/crawl-ref/source/clua.cc b/crawl-ref/source/clua.cc
index 6f891072df..7e2c43a98a 100644
--- a/crawl-ref/source/clua.cc
+++ b/crawl-ref/source/clua.cc
@@ -1815,6 +1815,41 @@ static int crawl_split(lua_State *ls)
return (1);
}
+LUARET1(crawl_game_started, boolean, crawl_state.need_save)
+
+static int crawl_err_trace(lua_State *ls)
+{
+ const int nargs = lua_gettop(ls);
+ const int err = lua_pcall(ls, nargs - 1, LUA_MULTRET, 0);
+
+ if (err)
+ {
+ // This code from lua.c:traceback() (mostly)
+ const char *errs = lua_tostring(ls, 1);
+ std::string errstr = errs? errs : "";
+ lua_getfield(ls, LUA_GLOBALSINDEX, "debug");
+ if (!lua_istable(ls, -1))
+ {
+ lua_pop(ls, 1);
+ return lua_error(ls);
+ }
+ lua_getfield(ls, -1, "traceback");
+ if (!lua_isfunction(ls, -1))
+ {
+ lua_pop(ls, 2);
+ return lua_error(ls);
+ }
+ lua_pushvalue(ls, 1);
+ lua_pushinteger(ls, 2); // Skip crawl_err_trace and traceback.
+ lua_call(ls, 2, 1);
+
+ // What's on top should be the error.
+ lua_error(ls);
+ }
+
+ return (lua_gettop(ls));
+}
+
static const struct luaL_reg crawl_lib[] =
{
{ "mpr", crawl_mpr },
@@ -1837,6 +1872,9 @@ static const struct luaL_reg crawl_lib[] =
{ "message_filter", crawl_message_filter },
{ "trim", crawl_trim },
{ "split", crawl_split },
+ { "game_started", crawl_game_started },
+ { "err_trace", crawl_err_trace },
+
{ NULL, NULL },
};
diff --git a/crawl-ref/source/dat/clua/dungeon.lua b/crawl-ref/source/dat/clua/dungeon.lua
index c25e06c4df..28084beaa8 100644
--- a/crawl-ref/source/dat/clua/dungeon.lua
+++ b/crawl-ref/source/dat/clua/dungeon.lua
@@ -11,7 +11,7 @@ function dgn_map_meta_wrap(obj, tab)
local meta = { }
for fn, val in pairs(tab) do
meta[fn] = function (...)
- return val(obj, ...)
+ return crawl.err_trace(val, obj, ...)
end
end
meta.wrapped_instance = obj
@@ -38,4 +38,4 @@ function dgn_run_map(prelude, main)
-- calls.
return env
end
-end \ No newline at end of file
+end
diff --git a/crawl-ref/source/luadgn.cc b/crawl-ref/source/luadgn.cc
index 2381dcfa97..f0dbee15bc 100644
--- a/crawl-ref/source/luadgn.cc
+++ b/crawl-ref/source/luadgn.cc
@@ -38,8 +38,8 @@ static int dlua_stringtable(lua_State *ls, const std::vector<std::string> &s)
///////////////////////////////////////////////////////////////////////////
// dlua_chunk
-dlua_chunk::dlua_chunk()
- : file(), chunk(), first(-1), last(-1), error()
+dlua_chunk::dlua_chunk(const std::string &_context)
+ : file(), chunk(), context(_context), first(-1), last(-1), error()
{
clear();
}
@@ -63,7 +63,8 @@ void dlua_chunk::add(int line, const std::string &s)
first = line;
if (line != last && last != -1)
- chunk += "\n";
+ while (last++ < line)
+ chunk += '\n';
chunk += " ";
chunk += s;
@@ -86,7 +87,7 @@ int dlua_chunk::load(CLua *interp)
if (trimmed_string(chunk).empty())
return (-1000);
return check_op(interp,
- interp->loadstring(chunk.c_str(), "dlua_chunk"));
+ interp->loadstring(chunk.c_str(), context.c_str()));
}
int dlua_chunk::load_call(CLua *interp, const char *fn)
@@ -110,6 +111,67 @@ bool dlua_chunk::empty() const
return trimmed_string(chunk).empty();
}
+bool dlua_chunk::rewrite_chunk_errors(std::string &s) const
+{
+ if (s.find(context) == std::string::npos)
+ return (false);
+
+ // Our chunk is mentioned, go back through and rewrite lines.
+ std::vector<std::string> lines = split_string("\n", s);
+ std::string newmsg = lines[0];
+ bool wrote_prefix = false;
+ for (int i = 2, size = lines.size() - 1; i < size; ++i)
+ {
+ const std::string &st = lines[i];
+ if (st.find(context) != std::string::npos)
+ {
+ if (!wrote_prefix)
+ {
+ newmsg = get_chunk_prefix(st) + ": " + newmsg;
+ wrote_prefix = true;
+ }
+ else
+ newmsg += "\n" + rewrite_chunk_prefix(st);
+ }
+ }
+ s = newmsg;
+ return (true);
+}
+
+std::string dlua_chunk::rewrite_chunk_prefix(const std::string &line) const
+{
+ std::string s = line;
+ const std::string contextm = "[string \"" + context + "\"]:";
+ const std::string::size_type ps = s.find(contextm);
+ if (ps == std::string::npos)
+ return (s);
+
+ std::string::size_type pe = s.find(':', ps + contextm.length());
+ if (pe != std::string::npos)
+ {
+ const std::string::size_type lns = ps + contextm.length();
+ const std::string line_num = s.substr(lns, pe - lns);
+ const int lnum = atoi(line_num.c_str());
+ s = s.substr(0, lns) + make_stringf("%d", lnum + first - 1)
+ + s.substr(pe);
+ }
+
+ return s.substr(0, ps) + (file.empty()? context : file) + ":"
+ + s.substr(ps + contextm.length());
+}
+
+std::string dlua_chunk::get_chunk_prefix(const std::string &sorig) const
+{
+ std::string s = rewrite_chunk_prefix(sorig);
+ const std::string::size_type cpos = s.find(':');
+ if (cpos == std::string::npos)
+ return (s);
+ const std::string::size_type cnpos = s.find(':', cpos + 1);
+ if (cnpos == std::string::npos)
+ return (s);
+ return s.substr(0, cnpos);
+}
+
///////////////////////////////////////////////////////////////////////////
// Lua dungeon bindings (in the dgn table).
@@ -510,6 +572,7 @@ static const struct luaL_reg dgn_lib[] =
void init_dungeon_lua()
{
dlua.execfile("clua/dungeon.lua");
+ luaopen_debug(dlua);
luaL_newmetatable(dlua, MAP_METATABLE);
lua_pop(dlua, 1);
luaL_openlib(dlua, "dgn", dgn_lib, 0);
diff --git a/crawl-ref/source/luadgn.h b/crawl-ref/source/luadgn.h
index 199939dad2..f8b272f544 100644
--- a/crawl-ref/source/luadgn.h
+++ b/crawl-ref/source/luadgn.h
@@ -18,16 +18,19 @@ class dlua_chunk
private:
std::string file;
std::string chunk;
+ std::string context;
int first, last; // First and last lines of the original source.
private:
int check_op(CLua *, int);
+ std::string rewrite_chunk_prefix(const std::string &line) const;
+ std::string get_chunk_prefix(const std::string &s) const;
public:
std::string error;
public:
- dlua_chunk();
+ dlua_chunk(const std::string &_context = "dlua_chunk");
void clear();
void add(int line, const std::string &line);
void set_chunk(const std::string &s);
@@ -38,7 +41,8 @@ public:
const std::string &lua_string() const { return chunk; }
std::string orig_error() const;
-
+ bool rewrite_chunk_errors(std::string &err) const;
+
bool empty() const;
};
diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc
index 8a4c40ff39..5323c421a0 100644
--- a/crawl-ref/source/mapdef.cc
+++ b/crawl-ref/source/mapdef.cc
@@ -813,7 +813,7 @@ std::vector<std::string> map_lines::get_subst_strings() const
map_def::map_def()
: name(), tags(), place(), depths(), orient(), chance(),
- map(), mons(), items(), keyspecs(), prelude(), main(),
+ map(), mons(), items(), keyspecs(), prelude("dlprelude"), main("dlmain"),
index_only(false), cache_offset(0L)
{
init();
@@ -937,18 +937,6 @@ void map_def::set_file(const std::string &s)
file = get_base_filename(s);
}
-void map_def::run_strip_prelude()
-{
- run_lua(false);
- prelude.clear();
-}
-
-void map_def::strip_main()
-{
- main.clear();
- index_only = true;
-}
-
std::string map_def::run_lua(bool run_main)
{
dlua.callfn("dgn_set_map", "m", this);
@@ -970,14 +958,23 @@ std::string map_def::run_lua(bool run_main)
}
if (!dlua.callfn("dgn_run_map", 2, 0))
- return (dlua.error);
-
+ return rewrite_chunk_errors(dlua.error);
+
// Clear the map setting.
dlua.callfn("dgn_set_map", 0, 0);
return (dlua.error);
}
+std::string map_def::rewrite_chunk_errors(const std::string &s) const
+{
+ std::string res = s;
+ if (prelude.rewrite_chunk_errors(res))
+ return (res);
+ main.rewrite_chunk_errors(res);
+ return (res);
+}
+
std::string map_def::validate()
{
std::string err = run_lua(true);
diff --git a/crawl-ref/source/mapdef.h b/crawl-ref/source/mapdef.h
index 94bad0bc8f..c2ef6e897d 100644
--- a/crawl-ref/source/mapdef.h
+++ b/crawl-ref/source/mapdef.h
@@ -437,8 +437,6 @@ public:
void set_file(const std::string &s);
std::string run_lua(bool skip_main);
- void run_strip_prelude();
- void strip_main();
std::string validate();
@@ -481,6 +479,7 @@ public:
private:
void write_depth_ranges(FILE *) const;
void read_depth_ranges(FILE *);
+ std::string rewrite_chunk_errors(const std::string &s) const;
std::string add_key_field(
const std::string &s,
diff --git a/crawl-ref/source/util/levcomp.ypp b/crawl-ref/source/util/levcomp.ypp
index bedd60c7ba..daffae671c 100644
--- a/crawl-ref/source/util/levcomp.ypp
+++ b/crawl-ref/source/util/levcomp.ypp
@@ -32,7 +32,10 @@ static map_load_info_t loaded_maps;
void yyerror(const char *e)
{
- fprintf(stderr, "%s:%d: %s\n", lc_desfile.c_str(), yylineno, e);
+ if (strstr(e, lc_desfile.c_str()) == e)
+ fprintf(stderr, "%s\n", e);
+ else
+ fprintf(stderr, "%s:%d: %s\n", lc_desfile.c_str(), yylineno, e);
// Bail bail bail.
end(1);
}
@@ -100,13 +103,13 @@ defdepth : DEFAULT_DEPTH STRING
level : name metalines map_def metalines
{
+ lc_map.set_file(lc_desfile);
std::string err = lc_map.validate();
if (!err.empty())
yyerror(err.c_str());
if (!lc_map.has_depth() && !lc_default_depths.empty())
lc_map.add_depths(lc_default_depths.begin(),
lc_default_depths.end());
- lc_map.set_file(lc_desfile);
add_parsed_map(lc_map);
}
;