summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-04-20 22:11:09 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-04-20 22:11:09 +0000
commit06195a1e5d1bc504543da231baf90558df168064 (patch)
treefdc4afaccd40403625a0eafbde495f9e31d0c088 /crawl-ref/source
parent01d472dce8be0fa04ff3a66b5c35bc1dc98a110d (diff)
downloadcrawl-ref-06195a1e5d1bc504543da231baf90558df168064.tar.gz
crawl-ref-06195a1e5d1bc504543da231baf90558df168064.zip
Fixed source to build on Linux. Should still build on Mac OS, but this is
untested. Will probably not build out-of-the-box on other BSDs (we need an autoconf script to use the right dbm headers). DOS and Windows builds are still broken pending adding Berkeley DB 1.x sources to the Crawl tree, which I'll probably do sometime tomorrow. Renamed descriptions.txt -> descript.txt to fit into DOS filename limits. The descript.txt -> descript.db conversion is now performed automatically by Crawl on startup if descript.txt is newer than descript.db (or descript.db does not exist). descript.db is saved in the save directory which is a convenient directory that is guaranteed writable by Crawl. The makedb.pl script is no longer necessary (and is unreliable anyway, because it's easy to have multiple dbm versions with incompatible db formats and have the installed Perl link with one while Crawl uses the other, leading to nasty segfaults). Some .des file changes (Erik). Deep elf sorcerers are M_EVIL. Ghosts get mephitic cloud. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1337 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/AppHdr.h6
-rw-r--r--crawl-ref/source/acr.cc4
-rw-r--r--crawl-ref/source/dat/descript.txt (renamed from crawl-ref/source/dat/descriptions.txt)0
-rw-r--r--crawl-ref/source/dat/splev.des5
-rw-r--r--crawl-ref/source/dat/vaults.des4
-rw-r--r--crawl-ref/source/database.cc246
-rw-r--r--crawl-ref/source/database.h31
-rw-r--r--crawl-ref/source/files.cc28
-rw-r--r--crawl-ref/source/files.h19
-rw-r--r--crawl-ref/source/ghost.cc1
-rw-r--r--crawl-ref/source/makefile.unix5
-rw-r--r--crawl-ref/source/mon-data.h5
12 files changed, 247 insertions, 107 deletions
diff --git a/crawl-ref/source/AppHdr.h b/crawl-ref/source/AppHdr.h
index 42c371f581..097cfb35a4 100644
--- a/crawl-ref/source/AppHdr.h
+++ b/crawl-ref/source/AppHdr.h
@@ -72,6 +72,8 @@
#define UNIX
#define USE_8_COLOUR_TERM_MAP
#define COL_TO_REPLACE_DARKGREY BLUE
+
+ #define DB_NDBM
#endif
// =========================================================================
@@ -399,6 +401,10 @@
# error Must define USE_FILE_LOCKING for DGL_SIMPLE_MESSAGING
#endif
+#ifndef DB_NDBM
+#define DB_DBH
+#endif
+
// Uncomment these if you can't find these functions on your system
// #define NEED_USLEEP
// #define NEED_SNPRINTF
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index d7bcd81287..0442ede796 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -228,7 +228,6 @@ int main( int argc, char *argv[] )
// override some options for tutorial
init_tutorial_options();
- databaseSystemInit();
if (game_start || Options.always_greet)
{
mprf( "Welcome, %s the %s %s.",
@@ -2878,6 +2877,9 @@ static bool initialise(void)
// Read special levels and vaults.
read_maps();
+
+ // Initialise internal databases.
+ databaseSystemInit();
cio_init();
diff --git a/crawl-ref/source/dat/descriptions.txt b/crawl-ref/source/dat/descript.txt
index 6bc96bb43e..6bc96bb43e 100644
--- a/crawl-ref/source/dat/descriptions.txt
+++ b/crawl-ref/source/dat/descript.txt
diff --git a/crawl-ref/source/dat/splev.des b/crawl-ref/source/dat/splev.des
index a1741de17e..5ff45b2593 100644
--- a/crawl-ref/source/dat/splev.des
+++ b/crawl-ref/source/dat/splev.des
@@ -2936,9 +2936,9 @@ MAP
.wIwwwwwwwwwwwwwwwwwwwwwwwww.
.ww2ccccccccccccccccccccccww.
.ww.c.......3.3.3......w2cww.
-.wwxx........3.3.......wwcww.
+.wwxx........3.3.......cccww.
.122........3.I.3......4Ocww.
-.wwxx........3.3.......wwcww.
+.wwxx........3.3.......cccww.
.ww.c.......3.3.3......w2cww.
.ww2ccccccccccccccccccccccww.
.wIwwwwwwwwwwwwwwwwwwwwwwwww.
@@ -2946,7 +2946,6 @@ MAP
.............................
ENDMAP
-
##############################################################################
# Just like home
#
diff --git a/crawl-ref/source/dat/vaults.des b/crawl-ref/source/dat/vaults.des
index d13d31d445..48f0123dce 100644
--- a/crawl-ref/source/dat/vaults.des
+++ b/crawl-ref/source/dat/vaults.des
@@ -3881,7 +3881,7 @@ FLAGS: no_rotate
ORIENT: float
ITEM: stone
MONS: rat, goblin, kobold, ooze
-SHUFFLE: {[(
+SHUFFLE: {[(
MAP
xxxxxxxxxxx@xxxxxxxxxxxxxxxxxx
x.........l.l................x
@@ -3903,7 +3903,7 @@ x.....lllll..4....lllllll....x
x.....llllll....lllllll......x
x.....lllllllllllll..........x
x.........lllllll............x
-x............................x
+x>..........................>x
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ENDMAP
diff --git a/crawl-ref/source/database.cc b/crawl-ref/source/database.cc
index 71927f6b8e..d8d954e912 100644
--- a/crawl-ref/source/database.cc
+++ b/crawl-ref/source/database.cc
@@ -14,48 +14,71 @@
#include <unistd.h>
#include <stdlib.h>
#endif
-#include <stdlib.h>
+#include <cstdlib>
+#include <fstream>
#include "database.h"
#include "files.h"
+#include "libutil.h"
+#include "stuff.h"
// Convenience functions for (read-only) access to generic
// berkeley DB databases.
-#define nil 0
+db_list openDBList;
+DBM *descriptionDB;
-static bool databaseIsInitted = false;
-dbList_t *openDBList;
-DBM *descriptionDB;
+#define DESC_BASE_NAME "descript"
+#define DESC_TXT (DESC_BASE_NAME ".txt")
+#define DESC_DB (DESC_BASE_NAME ".db")
-struct dbList_s {
- DBM *dbPtr;
- dbList_s *next;
-} dbList_s;
+static void generate_description_db();
+time_t file_modtime(const std::string &file)
+{
+ struct stat filestat;
+ if (stat(file.c_str(), &filestat))
+ return (0);
-void databaseSystemInit() {
- if (!databaseIsInitted) {
- databaseIsInitted = true;
- openDBList = nil;
- std::string descriptionPath = datafile_path("descriptions.db");
- descriptionPath.erase(descriptionPath.length() - 3, descriptionPath.length());
- descriptionDB = openDB(descriptionPath.c_str());
- }
+ return (filestat.st_mtime);
+}
+
+// Returns true if file a is newer than file b.
+bool is_newer(const std::string &a, const std::string &b)
+{
+ return (file_modtime(a) > file_modtime(b));
+}
+
+void check_newer(const std::string &target,
+ const std::string &dependency,
+ void (*action)())
+{
+ if (is_newer(dependency, target))
+ action();
}
-void databaseSystemShutdown() {
- if (!databaseIsInitted) {
- // All done.
- return;
+void databaseSystemInit()
+{
+ if (!descriptionDB)
+ {
+ std::string descriptionPath = get_savedir_path(DESC_DB);
+ check_newer(descriptionPath,
+ datafile_path(DESC_TXT),
+ generate_description_db);
+ descriptionPath.erase(descriptionPath.length() - 3);
+ if (!(descriptionDB = openDB(descriptionPath.c_str())))
+ end(1, true, "Failed to open DB: %s", descriptionPath.c_str());
}
- dbList_t *current = openDBList;
- dbList_t *prev = nil;
- while (current) {
- dbm_close(current->dbPtr);
- prev = current;
- current = current->next;
- free(prev);
+}
+
+void databaseSystemShutdown()
+{
+ for (db_list::iterator i = openDBList.begin();
+ i != openDBList.end(); ++i)
+ {
+ dbm_close(*i);
}
+ openDBList.clear();
+ descriptionDB = NULL;
}
// This is here, and is external, just for future expansion -- if we
@@ -64,76 +87,141 @@ void databaseSystemShutdown() {
// morally wrong to have the database module manage the memory here.
// But hey, life is hard and you can write your own berkeley DB
// calls if you like.
-DBM *openDB(const char *dbFilename) {
- if (!databaseIsInitted) {
- return nil;
- }
+DBM *openDB(const char *dbFilename)
+{
DBM *dbToReturn = dbm_open(dbFilename, O_RDONLY, 0660);
- if (dbToReturn) {
- if (openDBList) {
- dbList_t *endOfDBList = openDBList;
- while (openDBList->next) {
- endOfDBList = openDBList->next;
- }
- endOfDBList->next = (dbList_t *)malloc(sizeof(dbList_t));
- endOfDBList = endOfDBList->next;
- endOfDBList->next = nil;
- endOfDBList->dbPtr = dbToReturn;
-
- } else {
- openDBList = (dbList_t *)malloc(sizeof(dbList_t));
- openDBList->next = nil;
- openDBList->dbPtr = dbToReturn;
- }
- } else {
- dbToReturn = nil;
- }
+ if (dbToReturn)
+ openDBList.push_front(dbToReturn);
+
return dbToReturn;
}
-datum database_fetch(DBM *database, const char *key) {
+datum database_fetch(DBM *database, const std::string &key)
+{
datum result;
- result.dptr = nil;
+ result.dptr = NULL;
result.dsize = 0;
- if (!databaseIsInitted) {
- return result;
- }
datum dbKey;
- dbKey.dptr = (void *)key;
- dbKey.dsize = strlen(key);
+ dbKey.dptr = (DPTR_COERCE) key.c_str();
+ dbKey.dsize = key.length();
result = dbm_fetch(database, dbKey);
return result;
}
-char *private_strlwr(char *string) {
- int i;
- for (i = 0; string[i]; i++) {
- string[i] = tolower(string[i]);
- }
- return string;
-}
+std::string getLongDescription(const char *key)
+{
+ if (!descriptionDB)
+ return ("");
-std::string getLongDescription(const char *key) {
- if (!databaseIsInitted) {
- return nil;
- }
// We have to canonicalize the key (in case the user typed it
// in and got the case wrong.
- int len = strlen(key);
- char *lowercaseKey = (char *)malloc(len+1);
- (void) strncpy(lowercaseKey, key, len+1);
- lowercaseKey = private_strlwr(lowercaseKey);
+ std::string canonical_key = key;
+ lowercase(canonical_key);
// Query the DB.
- datum result = database_fetch(descriptionDB, (const char *)lowercaseKey);
+ datum result = database_fetch(descriptionDB, canonical_key);
// Cons up a (C++) string to return. The caller must release it.
- std::string stringToReturn((const char *)result.dptr, result.dsize);
- // free the result...
- free(lowercaseKey);
-
- return stringToReturn;
+ return std::string((const char *)result.dptr, result.dsize);
+}
+
+static void store_descriptions(const std::string &in, const std::string &out);
+static void generate_description_db()
+{
+ std::string db_path = get_savedir_path(DESC_BASE_NAME);
+ std::string txt_path = datafile_path(DESC_TXT);
+
+ file_lock lock(get_savedir_path(DESC_BASE_NAME ".lk"), "wb");
+ store_descriptions(txt_path, db_path);
+ DO_CHMOD_PRIVATE(get_savedir_path(DESC_DB).c_str());
+}
+
+static void trim_right(std::string &s)
+{
+ s.erase(s.find_last_not_of(" \r\t\n") + 1);
+}
+
+static void trim_leading_newlines(std::string &s)
+{
+ s.erase(0, s.find_first_not_of("\n"));
+}
+
+static void add_entry(DBM *db, const std::string &k, std::string &v)
+{
+ trim_leading_newlines(v);
+ datum key, value;
+ key.dptr = (char *) k.c_str();
+ key.dsize = k.length();
+
+ value.dptr = (char *) v.c_str();
+ value.dsize = v.length();
+
+ if (dbm_store(db, key, value, DBM_REPLACE))
+ end(1, true, "Error storing %s", k.c_str());
+}
+
+static void parse_descriptions(std::ifstream &inf, DBM *db)
+{
+ char buf[1000];
+
+ std::string key;
+ std::string value;
+
+ bool in_entry = false;
+ while (!inf.eof())
+ {
+ inf.getline(buf, sizeof buf);
+
+ if (*buf == '#')
+ continue;
+
+ if (!strncmp(buf, "%%%%", 4))
+ {
+ if (!key.empty())
+ add_entry(db, key, value);
+ key.clear();
+ value.clear();
+ in_entry = true;
+ continue;
+ }
+
+ if (!in_entry)
+ continue;
+
+ if (key.empty())
+ {
+ key = buf;
+ trim_string(key);
+ lowercase(key);
+ }
+ else
+ {
+ std::string line = buf;
+ trim_right(line);
+ value += line + "\n";
+ }
+ }
+
+ if (!key.empty())
+ add_entry(db, key, value);
+}
+
+static void store_descriptions(const std::string &in, const std::string &out)
+{
+ std::ifstream inf(in.c_str());
+ if (!inf)
+ end(1, true, "Unable to open input file: %s", in.c_str());
+
+ if (DBM *db = dbm_open(out.c_str(), O_RDWR | O_CREAT, 0660))
+ {
+ parse_descriptions(inf, db);
+ dbm_close(db);
+ }
+ else
+ end(1, true, "Unable to open DB: %s", out.c_str());
+
+ inf.close();
}
diff --git a/crawl-ref/source/database.h b/crawl-ref/source/database.h
index 71b8474033..364a87c7b6 100644
--- a/crawl-ref/source/database.h
+++ b/crawl-ref/source/database.h
@@ -10,29 +10,34 @@
#ifndef DATABASE_H
#define DATABASE_H
-#undef DEBUG // hack
-#define NDEBUG
+#include "AppHdr.h"
#include "externs.h"
+#include <list>
-#ifdef __cplusplus
extern "C" {
-#endif
+#ifdef DB_NDBM
-#include <ndbm.h>
+# include <ndbm.h>
+# define DPTR_COERCE void *
+
+#else
+
+# define DB_DBM_HSEARCH 1
+# include <db.h>
+# define DPTR_COERCE char *
-// For convenience during shutdown.
-typedef struct dbList_s dbList_t;
-#ifdef __cplusplus
-}
#endif
-extern dbList_t *openDBList;
+}
+
+typedef std::list<DBM *> db_list;
+
+extern db_list openDBList;
void databaseSystemInit();
void databaseSystemShutdown();
DBM *openDB(const char *dbFilename);
-datum *database_fetch(DBM *database, char *key);
-
+datum database_fetch(DBM *database, const std::string &key);
-std::string getLongDescription(const char *key);
+std::string getLongDescription(const std::string &key);
#endif
diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc
index d8753231ef..72379982ad 100644
--- a/crawl-ref/source/files.cc
+++ b/crawl-ref/source/files.cc
@@ -80,12 +80,6 @@
#include "travel.h"
#include "tutorial.h"
-#ifdef SHARED_FILES_CHMOD_PRIVATE
-#define DO_CHMOD_PRIVATE(x) chmod( (x), SHARED_FILES_CHMOD_PRIVATE )
-#else
-#define DO_CHMOD_PRIVATE(x) // empty command
-#endif
-
void save_level(int level_saved, level_area_type lt,
branch_type where_were_you);
@@ -1646,3 +1640,25 @@ void lk_close(FILE *handle, const char *mode, const std::string &file)
chmod(file.c_str(), SHARED_FILES_CHMOD_PUBLIC);
#endif
}
+
+/////////////////////////////////////////////////////////////////////////////
+// file_lock
+//
+// Locks a named file (usually an empty lock file), creating it if necessary.
+
+file_lock::file_lock(const std::string &s, const char *_mode, bool die_on_fail)
+ : handle(NULL), mode(_mode), filename(s)
+{
+#ifdef USE_FILE_LOCKING
+ if (!(handle = lk_open(mode, filename)) && die_on_fail)
+ end(1, true, "Unable to open lock file \"%s\"", filename.c_str());
+#endif
+}
+
+file_lock::~file_lock()
+{
+#ifdef USE_FILE_LOCKING
+ if (handle)
+ lk_close(handle, mode, filename);
+#endif
+}
diff --git a/crawl-ref/source/files.h b/crawl-ref/source/files.h
index 814c25b1eb..ccf73c3a62 100644
--- a/crawl-ref/source/files.h
+++ b/crawl-ref/source/files.h
@@ -40,6 +40,7 @@ std::string get_savedir_filename(const std::string &pre,
const std::string &suf,
const std::string &ext,
bool suppress_uid = false);
+std::string get_savedir_path(const std::string &shortpath);
std::string get_prefs_filename();
@@ -100,4 +101,22 @@ bool lock_file_handle( FILE *handle, int type );
bool unlock_file_handle( FILE *handle );
#endif // USE_FILE_LOCKING
+#ifdef SHARED_FILES_CHMOD_PRIVATE
+#define DO_CHMOD_PRIVATE(x) chmod( (x), SHARED_FILES_CHMOD_PRIVATE )
+#else
+#define DO_CHMOD_PRIVATE(x) // empty command
+#endif
+
+class file_lock
+{
+public:
+ file_lock(const std::string &filename, const char *mode,
+ bool die_on_fail = true);
+ ~file_lock();
+private:
+ FILE *handle;
+ const char *mode;
+ std::string filename;
+};
+
#endif
diff --git a/crawl-ref/source/ghost.cc b/crawl-ref/source/ghost.cc
index d09f1484ac..bda3da6972 100644
--- a/crawl-ref/source/ghost.cc
+++ b/crawl-ref/source/ghost.cc
@@ -85,6 +85,7 @@ static int search_order_misc[] = {
SPELL_BANISHMENT,
SPELL_PARALYSE,
SPELL_CONFUSE,
+ SPELL_MEPHITIC_CLOUD,
SPELL_SLOW,
SPELL_POLYMORPH_OTHER,
SPELL_TELEPORT_OTHER,
diff --git a/crawl-ref/source/makefile.unix b/crawl-ref/source/makefile.unix
index 709421c090..013022bb81 100644
--- a/crawl-ref/source/makefile.unix
+++ b/crawl-ref/source/makefile.unix
@@ -48,7 +48,10 @@ endif
LUALIB = lua
LUALIBA = l$(LUALIB).a
-LIB = -lncurses -L$(LUASRC) -l$(LUALIB)
+LIBDBM = $(shell [ "`ls /usr/lib/libdbm.* 2>/dev/null`" != "" ] \
+ && echo 'dbm' || echo 'db')
+
+LIB = -lncurses -L$(LUASRC) -l$(LUALIB) -l$(LIBDBM)
INCLUDES := $(INCLUDES) -Iutil -I. -I$(LUASRC)
diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h
index 71bcba6ba9..f5b7a4b12c 100644
--- a/crawl-ref/source/mon-data.h
+++ b/crawl-ref/source/mon-data.h
@@ -2849,7 +2849,8 @@
{
MONS_DEEP_ELF_SORCERER, 'e', RED, "deep elf sorcerer",
- M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_SEE_INVIS | M_SPEAKS,
+ M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_SEE_INVIS | M_SPEAKS
+ | M_EVIL,
MR_NO_FLAGS,
450, 10, MONS_ELF, MONS_ELF, MH_NATURAL, -6,
{ {AT_HIT, AF_PLAIN, 12}, {AT_NONE, AF_PLAIN, 0}, {AT_NONE, AF_PLAIN, 0}, {AT_NONE, AF_PLAIN, 0} },
@@ -4425,4 +4426,4 @@
MONUSE_STARTING_EQUIPMENT, SIZE_MEDIUM
},
-#endif \ No newline at end of file
+#endif