summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2008-11-18 20:09:38 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2008-11-18 20:09:38 +0000
commit42c0cf066213e022a8f1f0ea4230b668095c605b (patch)
tree792728ce498a6c6160a9cba6cd49f86ed3c4d887 /crawl-ref
parent82cc08db3375be0e6ab3b871f7dde5916ed67c30 (diff)
downloadcrawl-ref-42c0cf066213e022a8f1f0ea4230b668095c605b.tar.gz
crawl-ref-42c0cf066213e022a8f1f0ea4230b668095c605b.zip
Lua marker code is now converted into an anonymous function in the same scope as the rest of the map Lua code so that locals defined in the map Lua are visible to the marker code.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7479 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/clua.cc21
-rw-r--r--crawl-ref/source/clua.h4
-rw-r--r--crawl-ref/source/luadgn.cc18
-rw-r--r--crawl-ref/source/mapdef.cc33
-rw-r--r--crawl-ref/source/mapdef.h24
-rw-r--r--crawl-ref/source/mapmark.cc11
-rw-r--r--crawl-ref/source/mapmark.h1
-rw-r--r--crawl-ref/source/util/levcomp.lpp17
-rw-r--r--crawl-ref/source/util/levcomp.ypp50
9 files changed, 127 insertions, 52 deletions
diff --git a/crawl-ref/source/clua.cc b/crawl-ref/source/clua.cc
index 9fa1a79a9a..7fb7a310a7 100644
--- a/crawl-ref/source/clua.cc
+++ b/crawl-ref/source/clua.cc
@@ -131,10 +131,15 @@ void CLua::setregistry(const char *name)
lua_settable(state(), LUA_REGISTRYINDEX);
}
+void CLua::_getregistry(lua_State *ls, const char *name)
+{
+ lua_pushstring(ls, name);
+ lua_gettable(ls, LUA_REGISTRYINDEX);
+}
+
void CLua::getregistry(const char *name)
{
- lua_pushstring(state(), name);
- lua_gettable(state(), LUA_REGISTRYINDEX);
+ _getregistry(state(), name);
}
void CLua::save(const char *file)
@@ -639,6 +644,18 @@ void CLua::init_lua()
lua_pushboolean(_state, managed_vm);
setregistry("lua_vm_is_managed");
+
+ lua_pushlightuserdata(_state, this);
+ setregistry("__clua");
+}
+
+CLua &CLua::get_vm(lua_State *ls)
+{
+ _getregistry(ls, "__clua");
+ CLua *vm = util_get_userdata<CLua>(ls, -1);
+ if (!vm)
+ end(1, false, "Failed to find CLua for lua state %p", ls);
+ return (*vm);
}
bool CLua::is_managed_vm(lua_State *ls)
diff --git a/crawl-ref/source/clua.h b/crawl-ref/source/clua.h
index ae465aa3a0..e6ae4ecde7 100644
--- a/crawl-ref/source/clua.h
+++ b/crawl-ref/source/clua.h
@@ -93,6 +93,8 @@ public:
CLua(bool managed = true);
~CLua();
+ static CLua &get_vm(lua_State *);
+
lua_State *state();
operator lua_State * ()
@@ -170,6 +172,8 @@ private:
void load_chooks();
void init_throttle();
+ static void _getregistry(lua_State *, const char *name);
+
void vfnreturns(const char *par, va_list va);
bool proc_returns(const char *par) const;
diff --git a/crawl-ref/source/luadgn.cc b/crawl-ref/source/luadgn.cc
index 8ad3fc37ac..ca773b84d8 100644
--- a/crawl-ref/source/luadgn.cc
+++ b/crawl-ref/source/luadgn.cc
@@ -764,6 +764,23 @@ static int dgn_item(lua_State *ls)
return (0);
}
+static int dgn_lua_marker(lua_State *ls)
+{
+ MAP(ls, 1, map);
+ if (lua_gettop(ls) != 3 || !lua_isstring(ls, 2) || !lua_isfunction(ls, 3))
+ luaL_error(ls, "Expected marker key and marker function.");
+
+ CLua &lvm(CLua::get_vm(ls));
+ std::string key = lua_tostring(ls, 2);
+ lua_datum function(lvm, 3, false);
+
+ const std::string err = map->map.add_lua_marker(key, function);
+ if (!err.empty())
+ luaL_error(ls, err.c_str());
+
+ return (0);
+}
+
static int dgn_marker(lua_State *ls)
{
MAP(ls, 1, map);
@@ -2106,6 +2123,7 @@ static const struct luaL_reg dgn_lib[] =
{ "mons", dgn_mons },
{ "item", dgn_item },
{ "marker", dgn_marker },
+ { "lua_marker", dgn_lua_marker },
{ "kfeat", dgn_kfeat },
{ "kitem", dgn_kitem },
{ "kmons", dgn_kmons },
diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc
index 0f9cb1f838..3eaea9b11f 100644
--- a/crawl-ref/source/mapdef.cc
+++ b/crawl-ref/source/mapdef.cc
@@ -63,11 +63,11 @@ static int find_weight(std::string &s, int defweight = TAG_UNFOUND)
return (weight == TAG_UNFOUND? defweight : weight);
}
-static std::string split_key_item(const std::string &s,
+std::string mapdef_split_key_item(const std::string &s,
std::string *key,
int *separator,
std::string *arg,
- int key_max_len = 1)
+ int key_max_len)
{
std::string::size_type
norm = s.find("=", 1),
@@ -383,7 +383,7 @@ std::string map_lines::add_feature_marker(const std::string &s)
{
std::string key, arg;
int sep = 0;
- std::string err = split_key_item(s, &key, &sep, &arg);
+ std::string err = mapdef_split_key_item(s, &key, &sep, &arg);
if (!err.empty())
return (err);
@@ -391,6 +391,13 @@ std::string map_lines::add_feature_marker(const std::string &s)
return ("");
}
+std::string map_lines::add_lua_marker(const std::string &key,
+ const lua_datum &function)
+{
+ transforms.push_back(new map_marker_spec(key[0], function));
+ return ("");
+}
+
void map_lines::apply_markers(const coord_def &c)
{
for (int i = 0, size = markers.size(); i < size; ++i)
@@ -546,7 +553,7 @@ std::string map_lines::add_colour(const std::string &sub)
std::string key;
std::string substitute;
- std::string err = split_key_item(sub, &key, &sep, &substitute);
+ std::string err = mapdef_split_key_item(sub, &key, &sep, &substitute);
if (!err.empty())
return (err);
@@ -570,7 +577,7 @@ std::string map_lines::add_subst(const std::string &sub)
std::string key;
std::string substitute;
- std::string err = split_key_item(sub, &key, &sep, &substitute);
+ std::string err = mapdef_split_key_item(sub, &key, &sep, &substitute);
if (!err.empty())
return (err);
@@ -589,7 +596,7 @@ std::string map_lines::parse_nsubst_spec(const std::string &s,
{
std::string key, arg;
int sep;
- std::string err = split_key_item(s, &key, &sep, &arg);
+ std::string err = mapdef_split_key_item(s, &key, &sep, &arg);
if (!err.empty())
return err;
const int keyval = key == "*"? -1 : atoi(key.c_str());
@@ -612,7 +619,7 @@ std::string map_lines::add_nsubst(const std::string &s)
int sep;
std::string key, arg;
- std::string err = split_key_item(s, &key, &sep, &arg);
+ std::string err = mapdef_split_key_item(s, &key, &sep, &arg);
if (!err.empty())
return (err);
@@ -1769,7 +1776,7 @@ std::string map_def::add_key_field(
int separator = 0;
std::string key, arg;
- std::string err = split_key_item(s, &key, &separator, &arg);
+ std::string err = mapdef_split_key_item(s, &key, &separator, &arg);
if (!err.empty())
return (err);
@@ -2810,8 +2817,7 @@ std::string map_marker_spec::apply_transform(map_lines &map)
{
try
{
- map_marker *mark =
- map_marker::parse_marker(marker);
+ map_marker *mark = create_marker();
if (!mark)
return make_stringf("Unable to parse marker from %s",
marker.c_str());
@@ -2826,6 +2832,13 @@ std::string map_marker_spec::apply_transform(map_lines &map)
return ("");
}
+map_marker *map_marker_spec::create_marker()
+{
+ return lua_fn.get()
+ ? new map_lua_marker(*lua_fn.get())
+ : map_marker::parse_marker(marker);
+}
+
map_transformer::transform_type map_marker_spec::type() const
{
return (TT_MARKER);
diff --git a/crawl-ref/source/mapdef.h b/crawl-ref/source/mapdef.h
index 775f2e82b2..83098d2b5a 100644
--- a/crawl-ref/source/mapdef.h
+++ b/crawl-ref/source/mapdef.h
@@ -15,6 +15,7 @@
#include <string>
#include <vector>
#include <cstdio>
+#include <memory>
#include "luadgn.h"
#include "enum.h"
@@ -202,15 +203,25 @@ class shuffle_spec : public map_transformer
class map_marker_spec : public map_transformer
{
- public:
+public:
int key;
std::string marker;
+ // Special handling for Lua markers:
+ std::auto_ptr<lua_datum> lua_fn;
+
map_marker_spec(int _key, const std::string &mark)
- : key(_key), marker(mark) { }
+ : key(_key), marker(mark), lua_fn() { }
+
+ map_marker_spec(int _key, const lua_datum &fn)
+ : key(_key), marker(), lua_fn(new lua_datum(fn)) { }
+
std::string apply_transform(map_lines &map);
transform_type type() const;
std::string describe() const;
+
+private:
+ map_marker *create_marker();
};
class map_def;
@@ -266,6 +277,8 @@ public:
void add_marker(map_marker *marker);
std::string add_feature_marker(const std::string &desc);
+ std::string add_lua_marker(const std::string &key,
+ const lua_datum &fn);
void apply_markers(const coord_def &pos);
void apply_colours(const coord_def &pos);
@@ -742,6 +755,13 @@ private:
std::string escape_string(std::string in, const std::string &toesc,
const std::string &escapewith);
+
+std::string mapdef_split_key_item(const std::string &s,
+ std::string *key,
+ int *separator,
+ std::string *arg,
+ int key_max_len = 1);
+
const char *map_section_name(int msect);
#endif
diff --git a/crawl-ref/source/mapmark.cc b/crawl-ref/source/mapmark.cc
index 7fadb6330e..ecbed091e3 100644
--- a/crawl-ref/source/mapmark.cc
+++ b/crawl-ref/source/mapmark.cc
@@ -165,6 +165,17 @@ map_lua_marker::map_lua_marker()
{
}
+map_lua_marker::map_lua_marker(const lua_datum &fn)
+ : map_marker(MAT_LUA_MARKER, coord_def())
+{
+ lua_stack_cleaner clean(dlua);
+ fn.push();
+ if (!dlua.callfn("dgn_run_map", 1, 1))
+ mprf(MSGCH_ERROR, "lua_marker exec error: %s", dlua.error.c_str());
+ else
+ check_register_table();
+}
+
map_lua_marker::map_lua_marker(const std::string &s, const std::string &,
bool mapdef_marker)
: map_marker(MAT_LUA_MARKER, coord_def()), initialised(false)
diff --git a/crawl-ref/source/mapmark.h b/crawl-ref/source/mapmark.h
index 07d89331be..eb7eb22ba4 100644
--- a/crawl-ref/source/mapmark.h
+++ b/crawl-ref/source/mapmark.h
@@ -98,6 +98,7 @@ class map_lua_marker : public map_marker, public dgn_event_listener
{
public:
map_lua_marker();
+ map_lua_marker(const lua_datum &function);
map_lua_marker(const std::string &s, const std::string &ctx,
bool mapdef_marker = true);
~map_lua_marker();
diff --git a/crawl-ref/source/util/levcomp.lpp b/crawl-ref/source/util/levcomp.lpp
index 42297b5016..590cd59122 100644
--- a/crawl-ref/source/util/levcomp.lpp
+++ b/crawl-ref/source/util/levcomp.lpp
@@ -122,7 +122,6 @@ static void cattext(bool trim_right = false, int strip_trailing = 0)
%s MNAME
%s KEYWORDS
%x ITEM_LIST
-%x TOEOL
%option yylineno
%option never-interactive
@@ -213,19 +212,9 @@ SPACE [\ \t\r]
cattext();
}
-<ARGUMENT>{SPACE}*$ { BEGIN(INITIAL); str_check(); return STRING; }
-
-<TOEOL>.*\\[ \t\r]*$ {
- settext(true, 1);
- return STRING;
- }
+<ARGUMENT>{NSPACE} cattext();
-<TOEOL>.+$ {
- BEGIN(INITIAL);
- settext(true);
- return STRING;
- }
-<TOEOL>\r?\n ;
+<ARGUMENT>{SPACE}*$ { BEGIN(INITIAL); str_check(); return STRING; }
^[ \t]*#.* ;
@@ -259,7 +248,7 @@ FLOORCOL: { CBEGIN(ARGUMENT); return FLOORCOL; }
ROCKCOL: { CBEGIN(ARGUMENT); return ROCKCOL; }
MONS: { CBEGIN(MNAME); return MONS; }
ITEM: { CBEGIN(ITEM_LIST); return ITEM; }
-MARKER: { CBEGIN(TOEOL); return MARKER; }
+MARKER: { CBEGIN(ARGUMENT); return MARKER; }
SHUFFLE: { CBEGIN(ITEM_LIST); return SHUFFLE; }
KFEAT: { CBEGIN(ARGUMENT); return KFEAT; }
diff --git a/crawl-ref/source/util/levcomp.ypp b/crawl-ref/source/util/levcomp.ypp
index fc75c4a53b..f2bb2b17b6 100644
--- a/crawl-ref/source/util/levcomp.ypp
+++ b/crawl-ref/source/util/levcomp.ypp
@@ -17,8 +17,6 @@ int yylex();
extern int yylineno;
-static bool start_marker_segment = false;
-
void yyerror(const char *e)
{
if (strstr(e, lc_desfile.c_str()) == e)
@@ -319,32 +317,36 @@ bflags : BFLAGS STRING
}
;
-marker : MARKER
- {
- lc_map.main.add(yylineno, "marker(");
- start_marker_segment = true;
- }
- marker_spec
+marker : MARKER STRING
{
- lc_map.main.add(yylineno, ")");
- }
- ;
+ std::string key, arg;
+ int sep(0);
-marker_spec : mspec_segments
+ const std::string err =
+ mapdef_split_key_item($2, &key, &sep, &arg);
-mspec_segments : /* nothing */
- | mspec_segments mspec_segment
- ;
+ if (!err.empty())
+ yyerror(err.c_str());
-mspec_segment : STRING
- {
- lc_map.main.add(
- yylineno,
- make_stringf(
- "%s\"%s\"",
- start_marker_segment? "" : " .. ",
- quote_lua_string($1).c_str()));
- start_marker_segment = false;
+ // Special treatment for Lua markers.
+ if (arg.find("lua:") == 0)
+ {
+ arg = arg.substr(4);
+ lc_map.main.add(
+ yylineno,
+ make_stringf("lua_marker(\"%s\", function () "
+ " return %s "
+ "end)",
+ quote_lua_string(key).c_str(),
+ arg.c_str()));
+ }
+ else
+ {
+ lc_map.main.add(
+ yylineno,
+ make_stringf("marker(\"%s\")",
+ quote_lua_string($2).c_str()));
+ }
}
;