summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2008-05-26 15:30:07 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2008-05-26 15:30:07 +0000
commita844f8e10213c19b6e48d6ff98e97bc9f026a42a (patch)
tree9cada2344ca78a2c2de555dc8b7fa943ee7382fe
parent1f1939b11a6ed95f769644c21e53589a1e7abeb9 (diff)
downloadcrawl-ref-a844f8e10213c19b6e48d6ff98e97bc9f026a42a.tar.gz
crawl-ref-a844f8e10213c19b6e48d6ff98e97bc9f026a42a.zip
Better support for settings files that include other files:
- Files can be included as "include foo" in .crawlrc instead of using the Lua call: : crawl.read_options('foo'). include foo and the Lua crawl.read_options('foo') are not equivalent - Lua only runs after the start of a new game, which is too late for some option settings. - Crawl searches for included files in this sequence: - Absolute paths: use the path directly (but not if DATA_DIR_PATH is set, since we don't want Crawl to read arbitrary files on multiuser systems). - Search relative to the including file. - Search relative to any -rcdir(s) provided. - Search in the data file search path. - The data file search path now includes settings/ for when we move rc stuff to settings/ .gitignore: ignore saves and morgue dirs correctly. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@5256 c06c8d41-db1a-0410-9941-cceddc491573
-rw-r--r--.gitignore4
-rw-r--r--crawl-ref/init.txt13
-rw-r--r--crawl-ref/source/acr.cc5
-rw-r--r--crawl-ref/source/clua.cc13
-rw-r--r--crawl-ref/source/externs.h18
-rw-r--r--crawl-ref/source/files.cc108
-rw-r--r--crawl-ref/source/files.h12
-rw-r--r--crawl-ref/source/initfile.cc255
-rw-r--r--crawl-ref/source/initfile.h7
-rw-r--r--crawl-ref/source/itemname.cc4
-rw-r--r--crawl-ref/source/mapmark.cc1
-rw-r--r--crawl-ref/source/newgame.cc28
12 files changed, 407 insertions, 61 deletions
diff --git a/.gitignore b/.gitignore
index 1fba213d8b..e989de04fd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,8 @@
*.[oa]
*.ann
*.diff
-saves/
-morgue/
+saves
+morgue
*.orig
*.rej
*.swp
diff --git a/crawl-ref/init.txt b/crawl-ref/init.txt
index 1e31156b5c..1d54405d03 100644
--- a/crawl-ref/init.txt
+++ b/crawl-ref/init.txt
@@ -8,7 +8,7 @@
# targeting interface.
# (New players should just ignore these lines.)
#
-# : crawl.read_options('docs/034_monster_glyphs.txt')
+# include docs/034_monster_glyphs.txt
# additional_macro_file = docs/034_command_keys.txt
# classic_item_colours = true
# classic_hud = true
@@ -180,9 +180,11 @@ runrest_ignore_monster = butterfly:1
trapwalk_safe_hp = dart:20,needle:15,arrow:35,bolt:45,spear:40,axe:45,blade:95
-# You can use the travel_stop_message for making autotravel better behaved.
-# The following file contains a list of such options, with explanations.
-: crawl.read_options('docs/travel_stoppers.txt')
+# You can use travel_stop_message to make autotravel stop for situations that
+# warrant your attention. This file (travel_stoppers.txt) contains a list of
+# travel_stop_message settings, with brief descriptions of what they do.
+
+include docs/travel_stoppers.txt
##### 4-h Stashes ###############################
#
@@ -351,9 +353,6 @@ tile_show_items = !?/%=([)X}+\_.
# colour.lightgray = black
# colour.lightcyan = cyan
# colour.yellow = brown
-#
-# Set the monster glyphs back to the way they were in 0.3.4
-# : crawl.read_options('docs/monster_glyphs.txt')
# See options_guide.txt for the options
# cset_ascii, cset_ibm, cset_dec, cset_unicode, cset_any,
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index 397abc48dd..0f96a4f61e 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -155,7 +155,7 @@ game_state crawl_state;
-std::string init_file_location; // externed in newgame.cc
+std::string init_file_error; // externed in newgame.cc
char info[ INFO_SIZE ]; // messaging queue extern'd everywhere {dlb}
@@ -225,7 +225,7 @@ int main( int argc, char *argv[] )
init_monsters(mcolour);
// Read the init file.
- init_file_location = read_init_file();
+ init_file_error = read_init_file();
// now parse the args again, looking for everything else.
parse_args( argc, argv, false );
@@ -294,6 +294,7 @@ static void _show_commandline_options_help()
puts(" -plain don't use IBM extended characters");
puts(" -dir <path> crawl directory");
puts(" -rc <file> init file name");
+ puts(" -rcdir <dir> directory that contains (included) rc files");
puts(" -morgue <dir> directory to save character dumps");
puts(" -macro <dir> directory to save/find macro.txt");
puts("");
diff --git a/crawl-ref/source/clua.cc b/crawl-ref/source/clua.cc
index 1b80f2f498..982c208388 100644
--- a/crawl-ref/source/clua.cc
+++ b/crawl-ref/source/clua.cc
@@ -1794,18 +1794,7 @@ static int crawl_read_options(lua_State *ls)
return (0);
const char* filename = lua_tostring(ls, 1);
- FILE* f = fopen( filename, "r" );
- if (f)
- {
- FileLineInput fl(f);
- Options.read_options(fl, true);
- fclose(f);
- }
- else
- {
- mprf(MSGCH_WARN, "Warning: could not read options file '%s'", filename);
- }
-
+ Options.include(filename, true, true);
return (0);
}
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index b6e6e2bf18..340acef5df 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -1561,7 +1561,23 @@ public:
void read_options(InitLineInput &, bool runscripts,
bool clear_aliases = true);
+ void include(const std::string &file, bool resolve, bool runscript);
+ void report_error(const std::string &error);
+
+ std::string resolve_include(const std::string &file,
+ const char *type = "");
+
+ bool was_included(const std::string &file) const;
+
+ static std::string resolve_include(
+ std::string including_file,
+ std::string included_file,
+ const std::vector<std::string> *rcdirs = NULL)
+ throw (std::string);
+
public:
+ std::string filename; // The name of the file containing options.
+
// View options
std::vector<feature_override> feature_overrides;
std::vector<mon_display> mon_glyph_overrides;
@@ -1872,6 +1888,7 @@ public:
private:
std::map<std::string, std::string> aliases;
+ std::set<std::string> included; // Files we've included already.
public:
// Convenience accessors for the second-class options in named_options.
@@ -1922,6 +1939,7 @@ private:
void add_mon_glyph_override(const std::string &);
mon_display parse_mon_glyph(const std::string &s) const;
void set_option_fragment(const std::string &s);
+ bool include_file_directive(const std::string &line, bool runscript);
static const std::string interrupt_prefix;
};
diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc
index fe2a654037..02ddf79278 100644
--- a/crawl-ref/source/files.cc
+++ b/crawl-ref/source/files.cc
@@ -281,6 +281,44 @@ std::string get_base_filename(const std::string &filename)
return (filename);
}
+bool is_absolute_path(const std::string &path)
+{
+ return (!path.empty()
+ && (path[0] == FILE_SEPARATOR
+#if defined(WIN32CONSOLE) || defined(WIN32TILES)
+ || path.find(':') != std::string::npos
+#endif
+ ));
+}
+
+// Concatenates two paths, separating them with FILE_SEPARATOR if necessary.
+// Assumes that the second path is not absolute.
+//
+// If the first path is empty, returns the second unchanged. The second path
+// may be absolute in this case.
+std::string catpath(const std::string &first, const std::string &second)
+{
+ if (first.empty())
+ return (second);
+
+ std::string directory = first;
+ if (directory[directory.length() - 1] != FILE_SEPARATOR)
+ directory += FILE_SEPARATOR;
+ directory += second;
+
+ return (directory);
+}
+
+// Given a relative path and a reference file name, returns the relative path
+// suffixed to the directory containing the reference file name. Assumes that
+// the second path is not absolute.
+std::string get_path_relative_to(const std::string &referencefile,
+ const std::string &relativepath)
+{
+ return catpath(get_parent_directory(referencefile),
+ relativepath);
+}
+
std::string change_file_extension(const std::string &filename,
const std::string &ext)
{
@@ -312,7 +350,7 @@ void check_newer(const std::string &target,
action();
}
-static bool file_exists(const std::string &name)
+bool file_exists(const std::string &name)
{
#ifdef HAVE_STAT
struct stat st;
@@ -328,12 +366,16 @@ static bool file_exists(const std::string &name)
}
// Low-tech existence check.
-static bool dir_exists(const std::string &dir)
+bool dir_exists(const std::string &dir)
{
#ifdef _MSC_VER
DWORD lAttr = GetFileAttributes(dir.c_str());
return (lAttr != INVALID_FILE_ATTRIBUTES
&& (lAttr & FILE_ATTRIBUTE_DIRECTORY));
+#elif defined(HAVE_STAT)
+ struct stat st;
+ const int err = ::stat(dir.c_str(), &st);
+ return (!err && S_ISDIR(st.st_mode));
#else
DIR *d = opendir(dir.c_str());
const bool exists = !!d;
@@ -385,36 +427,84 @@ static bool create_dirs(const std::string &dir)
return (true);
}
+// Checks whether the given path is safe to read from. A path is safe if:
+// 1. If Unix: It contains no shell metacharacters.
+// 2. If DATA_DIR_PATH is set: the path is not an absolute path.
+// 3. If DATA_DIR_PATH is set: the path contains no ".." sequence.
+void assert_read_safe_path(const std::string &path) throw (std::string)
+{
+ // Check for rank tomfoolery first:
+ if (path.empty())
+ throw "Empty file name.";
+
+#ifdef UNIX
+ if (!shell_safe(path.c_str()))
+ throw make_stringf("\"%s\" contains bad characters.",
+ path.c_str());
+#endif
+
+#ifdef DATA_DIR_PATH
+ if (is_absolute_path(path))
+ throw make_stringf("\"%s\" is an absolute path.", path.c_str());
+
+ if (path.find("..") != std::string::npos)
+ throw make_stringf("\"%s\" contains \"..\" sequences.",
+ path.c_str());
+#endif
+
+ // Path is okay.
+}
+
+bool is_read_safe_path(const std::string &path)
+{
+ try
+ {
+ assert_read_safe_path(path);
+ }
+ catch (const std::string &err)
+ {
+ return (false);
+ }
+ return (true);
+}
+
+std::string canonicalise_file_separator(const std::string &path)
+{
+#if FILE_SEPARATOR != '/'
+ return (replace_all_of(path, "/", std::string(1, FILE_SEPARATOR)));
+#else
+ // No action needed here.
+ return (path);
+#endif
+}
+
std::string datafile_path(std::string basename,
bool croak_on_fail,
bool test_base_path)
{
-#if FILE_SEPARATOR != '/'
- basename = replace_all_of(basename, "/", std::string(1, FILE_SEPARATOR));
-#endif
+ basename = canonicalise_file_separator(basename);
if (test_base_path && file_exists(basename))
return (basename);
- std::string cdir = !SysEnv.crawl_dir.empty()? SysEnv.crawl_dir : "";
-
const std::string rawbases[] = {
#ifdef DATA_DIR_PATH
DATA_DIR_PATH,
#else
- cdir,
+ !SysEnv.crawl_dir.empty()? SysEnv.crawl_dir : "",
#endif
};
const std::string prefixes[] = {
std::string("dat") + FILE_SEPARATOR,
std::string("docs") + FILE_SEPARATOR,
+ std::string("settings") + FILE_SEPARATOR,
#ifndef DATA_DIR_PATH
std::string("..") + FILE_SEPARATOR + "docs" + FILE_SEPARATOR,
std::string("..") + FILE_SEPARATOR + "dat" + FILE_SEPARATOR,
+ std::string("..") + FILE_SEPARATOR + "settings" + FILE_SEPARATOR,
std::string("..") + FILE_SEPARATOR,
#endif
- std::string(".") + FILE_SEPARATOR,
"",
};
diff --git a/crawl-ref/source/files.h b/crawl-ref/source/files.h
index 830f99bc41..3e28c65a30 100644
--- a/crawl-ref/source/files.h
+++ b/crawl-ref/source/files.h
@@ -34,11 +34,23 @@ enum load_mode_type
// referenced in files - newgame - ouch:
extern FixedArray<bool, MAX_LEVELS, NUM_BRANCHES> tmp_file_pairs;
+bool file_exists(const std::string &name);
+bool dir_exists(const std::string &dir);
+bool is_absolute_path(const std::string &path);
+bool is_read_safe_path(const std::string &path);
+void assert_read_safe_path(const std::string &path) throw (std::string);
+
std::string datafile_path(std::string basename,
bool croak_on_fail = true,
bool test_base_path = false);
+
std::string get_parent_directory(const std::string &filename);
std::string get_base_filename(const std::string &filename);
+std::string get_path_relative_to(const std::string &referencefile,
+ const std::string &relativepath);
+std::string catpath(const std::string &first, const std::string &second);
+std::string canonicalise_file_separator(const std::string &path);
+
bool check_dir(const std::string &what, std::string &dir, bool silent = false);
bool travel_load_map( branch_type branch, int absdepth );
diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc
index 5b8ecad4f2..02e74c0a30 100644
--- a/crawl-ref/source/initfile.cc
+++ b/crawl-ref/source/initfile.cc
@@ -892,6 +892,9 @@ void game_options::reset_options()
// Setup travel information. What's a better place to do this?
initialise_travel();
+
+ // Forget any files we remembered as included.
+ included.clear();
}
void game_options::clear_cset_overrides()
@@ -1080,53 +1083,85 @@ void game_options::add_cset_override(char_set_type set, dungeon_char_type dc,
cset_override[set][dc] = symbol;
}
-// returns where the init file was read from
-std::string read_init_file(bool runscript)
+static std::string _find_crawlrc()
{
const char* locations_data[][2] = {
- { SysEnv.crawl_rc.c_str(), "" },
{ SysEnv.crawl_dir.c_str(), "init.txt" },
#ifdef MULTIUSER
- { SysEnv.home.c_str(), "/.crawlrc" },
+ { SysEnv.home.c_str(), ".crawlrc" },
{ SysEnv.home.c_str(), "init.txt" },
#endif
+#ifndef DATA_DIR_PATH
{ "", "init.txt" },
-#ifdef WIN32CONSOLE
- { "", ".crawlrc" },
- { "", "_crawlrc" },
+ { "..", "init.txt" },
#endif
{ NULL, NULL } // placeholder to mark end
};
- Options.reset_options();
+ // We'll look for these files in any supplied -rcdirs.
+ static const char *rc_dir_filenames[] = {
+ ".crawlrc", "init.txt"
+ };
+
+ // -rc option always wins.
+ if (!SysEnv.crawl_rc.empty())
+ return (SysEnv.crawl_rc);
+
+ // If we have any rcdirs, look in them for files from the
+ // rc_dir_names list.
+ for (int i = 0, size = SysEnv.rcdirs.size(); i < size; ++i)
+ {
+ for (unsigned n = 0; n < ARRAYSZ(rc_dir_filenames); ++n)
+ {
+ const std::string rc(
+ catpath(SysEnv.rcdirs[i], rc_dir_filenames[n]));
+ if (file_exists(rc))
+ return (rc);
+ }
+ }
- FILE* f = NULL;
- char name_buff[kPathLen];
// Check all possibilities for init.txt
- for ( int i = 0; f == NULL && locations_data[i][1] != NULL; ++i )
+ for ( int i = 0; locations_data[i][1] != NULL; ++i )
{
// Don't look at unset options
if ( locations_data[i][0] != NULL )
{
- snprintf( name_buff, sizeof name_buff, "%s%s",
- locations_data[i][0], locations_data[i][1] );
- f = fopen( name_buff, "r" );
+ const std::string rc =
+ catpath(locations_data[i][0], locations_data[i][1]);
+ if (file_exists(rc))
+ return (rc);
}
}
+ return ("");
+}
+
+// Returns an error message if the init.txt was not found.
+std::string read_init_file(bool runscript)
+{
+ Options.reset_options();
+
+ const std::string init_file_name( _find_crawlrc() );
+
+ FILE* f = fopen(init_file_name.c_str(), "r");
if ( f == NULL )
{
+ if (!init_file_name.empty())
+ return make_stringf("(\"%s\" is not readable)",
+ init_file_name.c_str());
+
#ifdef MULTIUSER
- return "not found (~/.crawlrc missing)";
+ return "(~/.crawlrc missing)";
#else
- return "not found (init.txt missing from current directory)";
+ return "(no init.txt in current directory)";
#endif
}
+ Options.filename = init_file_name;
read_options(f, runscript);
fclose(f);
- return std::string(name_buff);
-} // end read_init_file()
+ return ("");
+}
void read_startup_prefs()
{
@@ -1580,6 +1615,23 @@ void game_options::set_option_fragment(const std::string &s)
}
}
+bool game_options::include_file_directive(const std::string &line,
+ bool runscript)
+{
+ const std::string prefix = "include ";
+ if (line.find(prefix) == std::string::npos)
+ return (false);
+
+ std::string include_line = trimmed_string(line);
+ if (include_line.find(prefix) == 0)
+ {
+ include(trimmed_string(include_line.substr(prefix.length())),
+ true, runscript);
+ return (true);
+ }
+ return (false);
+}
+
void game_options::read_option_line(const std::string &str, bool runscript)
{
#define BOOL_OPTION_NAMED(_opt_str, _opt_var) \
@@ -1634,6 +1686,11 @@ void game_options::read_option_line(const std::string &str, bool runscript)
bool plus_equal = false;
bool minus_equal = false;
+ // If the user asked us to include a file, don't try to process the line
+ // as an option.
+ if (include_file_directive(str, runscript))
+ return;
+
const int first_equals = str.find('=');
// all lines with no equal-signs we ignore
@@ -2033,12 +2090,15 @@ void game_options::read_option_line(const std::string &str, bool runscript)
field.c_str() );
}
}
+ // If DATA_DIR_PATH is set, don't set crawl_dir from .crawlrc.
+#ifndef DATA_DIR_PATH
else if (key == "crawl_dir")
{
// We shouldn't bother to allocate this a second time
// if the user puts two crawl_dir lines in the init file.
SysEnv.crawl_dir = field;
}
+#endif
else if (key == "race")
{
race = _str_to_race( field );
@@ -2592,7 +2652,9 @@ void game_options::read_option_line(const std::string &str, bool runscript)
}
else if (key == "additional_macro_file")
{
- additional_macro_files.push_back(orig_field);
+ const std::string resolved = resolve_include(orig_field, "macro ");
+ if (!resolved.empty())
+ additional_macro_files.push_back(resolved);
}
#ifdef USE_TILE
else if (key == "tile_show_items")
@@ -2718,6 +2780,128 @@ void game_options::read_option_line(const std::string &str, bool runscript)
}
}
+// Checks an include file name for safety and resolves it to a readable path.
+// If safety check fails, throws a string with the reason for failure.
+// If file cannot be resolved, returns the empty string (this does not throw!)
+// If file can be resolved, returns the resolved path.
+std::string game_options::resolve_include(
+ std::string parent_file,
+ std::string included_file,
+ const std::vector<std::string> *rcdirs)
+
+ throw (std::string)
+{
+ // Before we start, make sure we convert forward slashes to the platform's
+ // favoured file separator.
+ parent_file = canonicalise_file_separator(parent_file);
+ included_file = canonicalise_file_separator(included_file);
+
+ // How we resolve include paths:
+ // 1. If it's an absolute path, use it directly.
+ // 2. Try the name relative to the parent filename, if supplied.
+ // 3. Try the name relative to any of the provided rcdirs.
+ // 4. Try locating the name as a regular data file (also checks for the
+ // file name relative to the current directory).
+ // 5. Fail, and return empty string.
+
+ assert_read_safe_path(included_file);
+
+ // There's only so much you can do with an absolute path.
+ // Note: absolute paths can only get here if we're not on a
+ // multiuser system. On multiuser systems assert_read_safe_path()
+ // will throw an exception if it sees absolute paths.
+ if (is_absolute_path(included_file))
+ return (file_exists(included_file)? included_file : "");
+
+ if (!parent_file.empty())
+ {
+ const std::string candidate =
+ get_path_relative_to(parent_file, included_file);
+ if (file_exists(candidate))
+ return (candidate);
+ }
+
+ if (rcdirs)
+ {
+ const std::vector<std::string> &dirs(*rcdirs);
+ for (int i = 0, size = dirs.size(); i < size; ++i)
+ {
+ const std::string candidate( catpath(dirs[i], included_file) );
+ if (file_exists(candidate))
+ return (candidate);
+ }
+ }
+
+ return datafile_path(included_file, false, true);
+}
+
+std::string game_options::resolve_include(
+ const std::string &file,
+ const char *type)
+{
+ try
+ {
+ const std::string resolved =
+ resolve_include(this->filename, file, &SysEnv.rcdirs);
+
+ if (resolved.empty())
+ report_error(
+ make_stringf("Cannot find %sfile \"%s\".",
+ type, file.c_str()));
+ return (resolved);
+ }
+ catch (const std::string &err)
+ {
+ report_error(
+ make_stringf("Cannot include %sfile: %s", type, err.c_str()));
+ return "";
+ }
+}
+
+bool game_options::was_included(const std::string &file) const
+{
+ return (included.find(file) != included.end());
+}
+
+void game_options::include(const std::string &rawfilename,
+ bool resolve,
+ bool runscript)
+{
+ const std::string include_file =
+ resolve ? resolve_include(rawfilename) : rawfilename;
+
+ if (was_included(include_file))
+ {
+ // Report error with rawfilename, not the resolved file name - we
+ // don't want to leak file paths in dgamelaunch installs.
+ report_error(make_stringf("Skipping previously included file: \"%s\".",
+ rawfilename.c_str()));
+ return;
+ }
+
+ included.insert(include_file);
+
+ // Change this->filename to the included filename while we're reading it.
+ unwind_var<std::string> optfile(this->filename, include_file);
+ FILE* f = fopen( include_file.c_str(), "r" );
+ if (f)
+ {
+ FileLineInput fl(f);
+ read_options(fl, runscript);
+ fclose(f);
+ }
+}
+
+void game_options::report_error(const std::string &error)
+{
+ // If called before game starts, log a startup error,
+ // otherwise spam the warning channel.
+ if (crawl_state.need_save)
+ mprf(MSGCH_WARN, "Warning: %s", error.c_str());
+ else
+ crawl_state.add_startup_error(error);
+}
+
static std::string check_string(const char *s)
{
return (s? s : "");
@@ -2778,6 +2962,7 @@ enum commandline_option_type {
CLO_PLAIN,
CLO_DIR,
CLO_RC,
+ CLO_RCDIR,
CLO_TSCORES,
CLO_VSCORES,
CLO_SCOREFILE,
@@ -2788,10 +2973,11 @@ enum commandline_option_type {
CLO_NOPS
};
-static const char *cmd_ops[] = { "scores", "name", "race", "class",
- "pizza", "plain", "dir", "rc", "tscores",
- "vscores", "scorefile", "morgue",
- "macro", "mapstat" };
+static const char *cmd_ops[] = {
+ "scores", "name", "race", "class", "pizza", "plain", "dir", "rc",
+ "rcdir", "tscores", "vscores", "scorefile", "morgue", "macro",
+ "mapstat"
+};
const int num_cmd_ops = CLO_NOPS;
bool arg_seen[num_cmd_ops];
@@ -2800,6 +2986,8 @@ bool parse_args( int argc, char **argv, bool rc_only )
{
set_crawl_base_dir(argv[0]);
+ SysEnv.rcdirs.clear();
+
if (argc < 2) // no args!
return (true);
@@ -2991,6 +3179,15 @@ bool parse_args( int argc, char **argv, bool rc_only )
}
break;
+ case CLO_RCDIR:
+ // Always parse
+ if (!next_is_param)
+ return (false);
+
+ SysEnv.add_rcdir(next_arg);
+ nextUsed = true;
+ break;
+
case CLO_DIR:
// ALWAYS PARSE
if (!next_is_param)
@@ -3078,6 +3275,18 @@ int game_options::o_colour(const char *name, int def) const
}
///////////////////////////////////////////////////////////////////////
+// system_environment
+
+void system_environment::add_rcdir(const std::string &dir)
+{
+ std::string cdir = canonicalise_file_separator(dir);
+ if (dir_exists(cdir))
+ rcdirs.push_back(cdir);
+ else
+ end(1, false, "Cannot find -rcdir \"%s\"", cdir.c_str());
+}
+
+///////////////////////////////////////////////////////////////////////
// menu_sort_condition
menu_sort_condition::menu_sort_condition(menu_type _mt, int _sort)
diff --git a/crawl-ref/source/initfile.h b/crawl-ref/source/initfile.h
index c700be59ef..b04b3f3850 100644
--- a/crawl-ref/source/initfile.h
+++ b/crawl-ref/source/initfile.h
@@ -53,10 +53,14 @@ void get_system_environment(void);
struct system_environment
{
+public:
std::string crawl_name;
std::string crawl_pizza;
std::string crawl_rc;
std::string crawl_dir;
+
+ std::vector<std::string> rcdirs; // Directories to search for includes.
+
std::string morgue_dir;
std::string crawl_base; // Directory from argv[0], may be used to
// locate datafiles.
@@ -73,6 +77,9 @@ struct system_environment
std::vector<std::string> cmd_args;
int map_gen_iters;
+
+public:
+ void add_rcdir(const std::string &dir);
};
extern system_environment SysEnv;
diff --git a/crawl-ref/source/itemname.cc b/crawl-ref/source/itemname.cc
index c44b0f88a6..4f1dce7695 100644
--- a/crawl-ref/source/itemname.cc
+++ b/crawl-ref/source/itemname.cc
@@ -1696,6 +1696,9 @@ bool item_type_known(const object_class_type base_type, const int sub_type)
return false;
}
+// [ds] Will the owner of this unused function step up and end its
+// suffering? :P
+#if 0
static bool _randart_has_known_property(const item_def &item)
{
for (int rap = 0; rap < RAP_NUM_PROPERTIES; rap++)
@@ -1704,6 +1707,7 @@ static bool _randart_has_known_property(const item_def &item)
return false;
}
+#endif
bool item_type_tried( const item_def& item )
{
diff --git a/crawl-ref/source/mapmark.cc b/crawl-ref/source/mapmark.cc
index 3ecbe9afd1..d1ea2d624a 100644
--- a/crawl-ref/source/mapmark.cc
+++ b/crawl-ref/source/mapmark.cc
@@ -762,6 +762,7 @@ void map_markers::read(reader &inf, int minorVersion)
{
const long cooky = unmarshallLong(inf);
ASSERT(cooky == MARKERS_COOKY);
+ UNUSED(cooky);
}
const int nmarkers = unmarshallShort(inf);
diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc
index 2b2baa873a..67b2a69516 100644
--- a/crawl-ref/source/newgame.cc
+++ b/crawl-ref/source/newgame.cc
@@ -102,7 +102,7 @@
#include "version.h"
#include "view.h"
-extern std::string init_file_location;
+extern std::string init_file_error;
#define MIN_START_STAT 1
@@ -2468,15 +2468,31 @@ static void _opening_screen(void)
"Please consult crawl_manual.txt for instructions and legal details."
"</brown>" EOL;
- const bool init_found =
- (init_file_location.find("not found") == std::string::npos);
+ const bool init_found = init_file_error.empty();
if (!init_found)
- msg += "<lightred>Init file ";
+ msg += "<lightred>No init file ";
else
- msg += "<lightgrey>Init file read: ";
+ msg += "<lightgrey>(Read options from ";
+
+ if (init_found)
+ {
+#ifdef DGAMELAUNCH
+ // For dgl installs, show only the last segment of the .crawlrc
+ // file name so that we don't leak details of the directory
+ // structure to (untrusted) users.
+ msg += get_base_filename(Options.filename);
+#else
+ msg += Options.filename;
+#endif
+ msg += ".)";
+ }
+ else
+ {
+ msg += init_file_error;
+ msg += ", using defaults.";
+ }
- msg += init_file_location;
msg += EOL;
formatted_string::parse_string(msg).display();