Remove the line_source stuff...

...and embed the inclusion data directly into the stream. Now we are
finally freed of any stateful WML processing, and we can go on with
the preprocessor cleanup. Small drawback: the error display is
temporarily disabled in the parser; I will add it back in a few
days. In the meantime, the commit will serve to detect for situations
where the inclusion data is embedded in the wrong place.
This commit is contained in:
Guillaume Melquiond 2005-04-11 18:39:33 +00:00
parent 6275902bee
commit 7b88a4033d
6 changed files with 67 additions and 85 deletions

View file

@ -259,7 +259,7 @@ private:
game_controller(const game_controller&);
void operator=(const game_controller&);
void read_game_cfg(preproc_map& defines, std::vector<line_source>& line_src, config& cfg, bool use_cache);
void read_game_cfg(preproc_map& defines, config& cfg, bool use_cache);
void refresh_game_cfg();
void download_campaigns();
@ -1328,7 +1328,7 @@ bool game_controller::change_language()
}
//this function reads the game configuration, searching for valid cached copies first
void game_controller::read_game_cfg(preproc_map& defines, std::vector<line_source>& line_src, config& cfg, bool use_cache)
void game_controller::read_game_cfg(preproc_map& defines, config& cfg, bool use_cache)
{
log_scope("read_game_cfg");
@ -1387,10 +1387,10 @@ void game_controller::read_game_cfg(preproc_map& defines, std::vector<line_sourc
std::cerr << "no valid cache found. Writing cache to '" << fname << "'\n";
//read the file and then write to the cache
scoped_istream stream = preprocess_file("data/game.cfg", &defines, &line_src);
scoped_istream stream = preprocess_file("data/game.cfg", &defines);
std::string error_log;
read(cfg, *stream, &line_src, &error_log);
read(cfg, *stream, &error_log);
if(!error_log.empty()) {
// FIXME: fix this string after the string-freeze is
// over, to clearly state this is a warning.
@ -1416,8 +1416,8 @@ void game_controller::read_game_cfg(preproc_map& defines, std::vector<line_sourc
}
std::cerr << "caching cannot be done. Reading file\n";
scoped_istream stream = preprocess_file("data/game.cfg", &defines, &line_src);
read(cfg, *stream, &line_src);
scoped_istream stream = preprocess_file("data/game.cfg", &defines);
read(cfg, *stream);
}
void game_controller::refresh_game_cfg()
@ -1428,8 +1428,7 @@ void game_controller::refresh_game_cfg()
units_data_.clear();
game_config_.clear();
std::vector<line_source> line_src;
read_game_cfg(defines_map_,line_src,game_config_,use_caching_);
read_game_cfg(defines_map_, game_config_, use_caching_);
const config* const units = game_config_.child("units");
if(units != NULL) {

View file

@ -26,7 +26,7 @@ bool detect_format_and_read(config &cfg, std::istream &in, std::string* error_lo
read_compressed(cfg, in);
return true;
} else {
read(cfg, in, NULL, error_log);
read(cfg, in, error_log);
return false;
}
}

View file

@ -38,26 +38,12 @@
static const size_t max_recursion_levels = 100;
line_source get_line_source(std::vector< line_source > const &line_src, int line)
{
line_source res(line, "", 0);
std::vector< line_source >::const_iterator it =
std::upper_bound(line_src.begin(), line_src.end(), res);
if (it != line_src.begin()) {
--it;
res.file = it->file;
res.fileline = it->fileline + (line - it->linenum);
}
return res;
}
namespace {
class parser
{
public:
parser(config& cfg, std::istream& in, std::vector<line_source> const* line_sources);
parser(config& cfg, std::istream& in);
void operator() (std::string* error_log=NULL);
private:
@ -70,7 +56,6 @@ private:
config& cfg_;
tokenizer tok_;
std::vector<line_source> const* line_sources;
struct element {
element(config* cfg, const std::string& name, size_t start_line, const std::string& textdomain) :
@ -89,10 +74,9 @@ private:
std::string current_textdomain_location;
};
parser::parser(config &cfg, std::istream &in, std::vector<line_source> const *line_sources) :
parser::parser(config &cfg, std::istream &in) :
cfg_(cfg),
tok_(in),
line_sources(line_sources),
current_textdomain_location("")
{
}
@ -308,6 +292,7 @@ std::string parser::lineno_string(utils::string_map& i18n_symbols, size_t lineno
{
std::string res;
/*
if(line_sources != NULL) {
const line_source src = get_line_source(*line_sources, lineno);
i18n_symbols["file"] = lexical_cast<std::string>(src.file);
@ -321,6 +306,7 @@ std::string parser::lineno_string(utils::string_map& i18n_symbols, size_t lineno
res = vgettext(string2.c_str(), i18n_symbols);
}
*/
return res;
}
@ -336,10 +322,9 @@ void parser::error(const std::string& error_type)
} // end anon namespace
void read(config &cfg, std::istream &data_in, std::vector< line_source > const *line_sources,
std::string* error_log)
void read(config &cfg, std::istream &data_in, std::string* error_log)
{
parser(cfg, data_in, line_sources)(error_log);
parser(cfg, data_in)(error_log);
}
static char const *AttributeEquals = "=";

View file

@ -18,13 +18,9 @@
#include <vector>
class config;
struct line_source;
line_source get_line_source(std::vector< line_source > const &line_src, int line);
//read data in, clobbering existing data.
void read(config &cfg, std::istream &in, std::vector< line_source > const *lines = 0,
std::string* error_log=NULL); //throws config::error
void read(config &cfg, std::istream &in, std::string* error_log = NULL); //throws config::error
void write(std::ostream &out, config const &cfg);

View file

@ -86,13 +86,14 @@ static std::vector<std::string> parse_macro_arguments(const std::string& macro)
static void internal_preprocess_file(const std::string& fname,
preproc_map& defines_map,
int depth, std::ostream &out,
std::vector<line_source>* lines_src, int& line);
std::string const &included_from);
static void internal_preprocess_data(std::istream &data_in,
preproc_map& defines_map,
int depth, std::ostream &out,
std::vector<line_source>* lines_src, int& line,
const std::string& fname, int srcline)
std::string const &included_from,
bool need_linenum,
std::string const &current_directory)
{
std::string data_str;
{
@ -104,6 +105,8 @@ static void internal_preprocess_data(std::istream &data_in,
std::string const &data = data_str;
bool in_quotes = false;
int current_line = 1;
bool previous_was_newline = !included_from.empty();
for(std::string::const_iterator i = data.begin(); i != data.end(); ++i) {
const char c = *i;
@ -170,8 +173,15 @@ static void internal_preprocess_data(std::istream &data_in,
}
}
std::ostringstream from;
if (!in_quotes && !included_from.empty()) {
from << " {" << symbol << "} " << current_line << included_from;
if (previous_was_newline)
out << "#line 0" << from.str();
}
std::istringstream stream(str);
internal_preprocess_data(stream, defines_map, depth, out, NULL, line, fname, srcline);
internal_preprocess_data(stream, defines_map, depth, out, from.str(),
!previous_was_newline, "");
} else if(depth < 20) {
std::string prefix;
std::string nfname;
@ -209,7 +219,7 @@ static void internal_preprocess_data(std::istream &data_in,
//being preprocessed
nfname = newfilename;
nfname.erase(nfname.begin(),nfname.begin()+2);
nfname = directory_name(fname) + nfname;
nfname = current_directory + nfname;
} else {
#ifdef USE_ZIPIOS
@ -223,19 +233,18 @@ static void internal_preprocess_data(std::istream &data_in,
nfname = "data/" + newfilename;
}
internal_preprocess_file(nfname,
defines_map, depth+1, out,
lines_src,line);
std::ostringstream from;
if (!in_quotes && !included_from.empty())
from << ' ' << current_line << included_from;
internal_preprocess_file(nfname, defines_map, depth + 1, out, from.str());
}
} else {
const std::string& str = read_file(newfilename);
out.write(&*str.begin(), str.length());
line += std::count(str.begin(),str.end(),'\n');
scoped_istream stream = istream_file(newfilename);
out << stream->rdbuf();
}
if(lines_src != NULL) {
lines_src->push_back(line_source(line,fname,srcline));
}
previous_was_newline = false;
need_linenum = true;
} else if(c == '#' && !in_quotes) {
//we are about to skip some things, so keep track of
//the start of where we're skipping, so we can count
@ -273,7 +282,8 @@ static void internal_preprocess_data(std::istream &data_in,
}
if(i > data.end() - hash_enddef.size()) {
throw config::error("pre-processing condition unterminated in '" + fname + "': '" + items + "'");
throw config::error("pre-processing condition unterminated " +
included_from + ": '" + items + "'");
}
i += hash_enddef.size();
@ -356,17 +366,25 @@ static void internal_preprocess_data(std::istream &data_in,
if(i == data.end())
break;
srcline += std::count(begin,i,'\n');
++line;
out.put('\n');
current_line += std::count(begin, i, '\n');
need_linenum = true;
goto linenum_output;
} else {
if(c == '\n') {
++line;
++srcline;
if (c == '\n') {
linenum_output:
if (need_linenum && !in_quotes && !included_from.empty()) {
out << "#line " << current_line << included_from;
need_linenum = false;
} else
out.put('\n');
++current_line;
previous_was_newline = true;
} else {
out.put(c);
if ((unsigned)c > 32)
previous_was_newline = false;
}
out.put(c);
}
}
}
@ -374,7 +392,7 @@ static void internal_preprocess_data(std::istream &data_in,
static void internal_preprocess_file(const std::string& fname,
preproc_map& defines_map,
int depth, std::ostream &out,
std::vector<line_source>* lines_src, int& line)
std::string const &included_from)
{
//if it's a directory, we process all files in the directory
//that end in .cfg
@ -386,32 +404,31 @@ static void internal_preprocess_file(const std::string& fname,
for(std::vector<std::string>::const_iterator f = files.begin();
f != files.end(); ++f) {
if(is_directory(*f) || f->size() > 4 && std::equal(f->end()-4,f->end(),".cfg")) {
internal_preprocess_file(*f, defines_map, depth, out, lines_src, line);
internal_preprocess_file(*f, defines_map, depth, out, included_from);
}
}
return;
}
if(lines_src != NULL) {
lines_src->push_back(line_source(line,fname,1));
std::string from;
if (!included_from.empty()) {
from = " " + fname + included_from;
out << "#line 0" << from;
}
scoped_istream stream = istream_file(fname);
internal_preprocess_data(*stream, defines_map, depth, out, lines_src, line, fname, 1);
internal_preprocess_data(*stream, defines_map, depth, out, from, false, directory_name(fname));
}
std::istream *preprocess_file(std::string const &fname,
const preproc_map* defines,
std::vector<line_source>* line_sources)
preproc_map const *defines)
{
log_scope("preprocessing file...");
preproc_map defines_copy;
if(defines != NULL)
defines_copy = *defines;
int linenum = 0;
std::stringstream *stream = new std::stringstream;
internal_preprocess_file(fname, defines_copy, 0, *stream, line_sources, linenum);
internal_preprocess_file(fname, defines_copy, 0, *stream, "\n");
return stream;
}

View file

@ -19,19 +19,6 @@
#include <string>
#include <vector>
//an object which defines the location an error occurred at when
//parsing WML files
struct line_source
{
line_source(int ln, std::string const &fname, int line)
: linenum(ln), file(fname), fileline(line) {}
int linenum;
std::string file;
int fileline;
bool operator<(line_source const &v) const { return linenum < v.linenum; }
};
struct preproc_define
{
preproc_define() {}
@ -47,10 +34,8 @@ struct preproc_define
typedef std::map< std::string, preproc_define > preproc_map;
//function to use the WML preprocessor on a file, and returns the resulting
//preprocessed file data. defines is a map of symbols defined. src is used
//internally and should be set to NULL
//preprocessed file data. defines is a map of symbols defined.
std::istream *preprocess_file(std::string const &fname,
preproc_map const *defines = NULL,
std::vector< line_source > *src = NULL);
preproc_map const *defines = NULL);
#endif