make {CURRENT_FILE} return the file that used the macro.

if {CURRENT_FILE} or {CURRENT_DIRECTORY} are used inside a macro they now
return the name of the file that use that macro (instead of the name
of the file that defines the macro)
This commit is contained in:
gfgtdf 2016-01-29 17:00:11 +01:00
parent d3615be714
commit f880c6036e

View file

@ -109,18 +109,6 @@ static std::string get_location(const std::string& loc)
return res;
}
// decode the filenames placed in a location
static std::string get_current_file(const std::string& loc)
{
std::string res;
std::vector< std::string > pos = utils::quoted_split(loc, ' ');
if(pos.empty()) {
return res;
}
else {
return get_filename(pos.front());
}
}
bool preproc_define::operator==(preproc_define const &v) const {
return value == v.value && arguments == v.arguments;
@ -219,7 +207,10 @@ public:
* Preprocesses and sends some text to the #target_ buffer.
* @return false when the input has no data left.
*/
preprocessor * get_old_preprocessor() { return old_preprocessor_; }
virtual bool get_chunk() = 0;
///retruns 1 if this parses a macro, -1 if this doesnt parse text (if this is no preprocessor_data). 0 otherwise (this parses a file).
virtual int is_macro() { return -1; }
virtual ~preprocessor();
};
@ -250,11 +241,33 @@ class preprocessor_streambuf: public streambuf
friend struct preprocessor_deleter;
preprocessor_streambuf(preprocessor_streambuf const &);
public:
std::string get_current_file();
preprocessor_streambuf(preproc_map *);
void error(const std::string &, int);
void warning(const std::string &, int);
};
// decode the filenames placed in a location
std::string preprocessor_streambuf::get_current_file()
{
unsigned nested_level = 0;
preprocessor* pre = current_;
while(pre && pre->is_macro()) {
if(pre->is_macro() == 1) {
++nested_level;
}
pre = pre->get_old_preprocessor();
}
std::string res;
std::vector< std::string > pos = utils::quoted_split(location_, ' ');
if(pos.size() <= 2*nested_level) {
return res;
}
else {
return get_filename(pos[2*nested_level]);
}
}
preprocessor_streambuf::preprocessor_streambuf(preproc_map *def) :
streambuf(),
out_buffer_(""),
@ -497,6 +510,8 @@ class preprocessor_data: preprocessor
*/
int skipping_;
int linenum_;
///true iff we are currently parsing a macros content, otherwise false.
bool is_define_;
std::string read_word();
std::string read_line();
@ -515,10 +530,10 @@ public:
std::string const &history,
std::string const &name, int line,
std::string const &dir, std::string const &domain,
std::map<std::string, std::string> *defines);
std::map<std::string, std::string> *defines, bool is_define = false);
~preprocessor_data();
virtual bool get_chunk();
virtual int is_macro() { return is_define_ ? 1 : 0; }
friend bool operator==(preprocessor_data::token_desc::TOKEN_TYPE, char);
friend bool operator==(char, preprocessor_data::token_desc::TOKEN_TYPE);
friend bool operator!=(preprocessor_data::token_desc::TOKEN_TYPE, char);
@ -591,7 +606,7 @@ bool preprocessor_file::get_chunk()
preprocessor_data::preprocessor_data(preprocessor_streambuf &t,
std::istream *i, std::string const &history, std::string const &name, int linenum,
std::string const &directory, std::string const &domain,
std::map<std::string, std::string> *defines) :
std::map<std::string, std::string> *defines, bool is_define) :
preprocessor(t),
in_scope_(i),
in_(*i),
@ -601,7 +616,8 @@ preprocessor_data::preprocessor_data(preprocessor_streambuf &t,
tokens_(),
slowpath_(0),
skipping_(0),
linenum_(linenum)
linenum_(linenum),
is_define_(is_define)
{
std::ostringstream s;
@ -1084,13 +1100,12 @@ bool preprocessor_data::get_chunk()
// If this is a known pre-processing symbol, then we insert it,
// otherwise we assume it's a file name to load.
if(symbol == current_file_str && strings_.size() - token.stack_pos == 1) {
pop_token();
put(get_current_file(target_.location_));
put(target_.get_current_file());
}
else if(symbol == current_dir_str && strings_.size() - token.stack_pos == 1) {
pop_token();
put(filesystem::directory_name(get_current_file(target_.location_)));
put(filesystem::directory_name(target_.get_current_file()));
}
else if (local_defines_ &&
(arg = local_defines_->find(symbol)) != local_defines_->end())
@ -1133,7 +1148,7 @@ bool preprocessor_data::get_chunk()
if (!slowpath_) {
DBG_PREPROC << "substituting macro " << symbol << '\n';
new preprocessor_data(target_, buffer, val.location, "",
val.linenum, dir, val.textdomain, defines);
val.linenum, dir, val.textdomain, defines, true);
} else {
DBG_PREPROC << "substituting (slow) macro " << symbol << '\n';
std::ostringstream res;
@ -1144,7 +1159,7 @@ bool preprocessor_data::get_chunk()
buf->textdomain_ = target_.textdomain_;
{ std::istream in(buf);
new preprocessor_data(*buf, buffer, val.location, "",
val.linenum, dir, val.textdomain, defines);
val.linenum, dir, val.textdomain, defines, true);
res << in.rdbuf(); }
delete buf;
put(res.str());