diff options
-rw-r--r-- | crawl-ref/source/AppHdr.h | 6 | ||||
-rw-r--r-- | crawl-ref/source/acr.cc | 4 | ||||
-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.des | 5 | ||||
-rw-r--r-- | crawl-ref/source/dat/vaults.des | 4 | ||||
-rw-r--r-- | crawl-ref/source/database.cc | 246 | ||||
-rw-r--r-- | crawl-ref/source/database.h | 31 | ||||
-rw-r--r-- | crawl-ref/source/files.cc | 28 | ||||
-rw-r--r-- | crawl-ref/source/files.h | 19 | ||||
-rw-r--r-- | crawl-ref/source/ghost.cc | 1 | ||||
-rw-r--r-- | crawl-ref/source/makefile.unix | 5 | ||||
-rw-r--r-- | crawl-ref/source/mon-data.h | 5 |
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 |