in preprocessor_data::get_chunk() if (macro != unknown_macro) { ERR_CF<::iterator iter=called_macros_.begin(); iter!=called_macros_.end(); ++iter) { ERR_CF<<*iter; } preproc_define const &val = macro->second; size_t nb_arg = strings_.size() - token.stack_pos - 1; if (nb_arg != val.arguments.size()) { std::ostringstream error; error << "preprocessor symbol '" << symbol << "' expects " << val.arguments.size() << " arguments, but has " << nb_arg << " arguments"; std::ostringstream location; location<write(&*i_bra - 1, i - i_bra + 1); i_bra = i + 1; } else if (i_bra == i_end) { if (c == '#' && !quoting) { // Keep track of textdomain changes in the body of the // macro, so they can be restored after each substitution // of a macro argument. std::string::const_iterator i_beg = i + 1; if (i_end - i_beg >= 13 && std::equal(i_beg, i_beg + 10, "textdomain")) { i_beg += 10; i = std::find(i_beg, i_end, '\n'); if (i_beg != i) ++i_beg; macro_textdomain = std::string(i_beg, i); *buffer << "#textdomain " << macro_textdomain; ++macro_num; c = '\n'; } else if((i_end - i_beg < 6 || (!std::equal(i_beg, i_beg + 6, "define") && !std::equal(i_beg, i_beg + 6, "ifndef"))) && (i_end - i_beg < 5 || (!std::equal(i_beg, i_beg + 5, "ifdef") && !std::equal(i_beg, i_beg + 5, "endif") && !std::equal(i_beg, i_beg + 5, "undef"))) && (i_end - i_beg < 4 || !std::equal(i_beg, i_beg + 4, "else"))) { // Check for define, ifdef, ifndef, endif, undef, else. // Otherwise, this is a comment and should be skipped. i = std::find(i_beg, i_end, '\n'); ++macro_num; c = '\n'; } } buffer->put(c); } else if (c == '}') { size_t sz = i - i_bra; for(size_t n = 0; n < nb_arg; ++n) { std::string const &arg = val.arguments[n]; if (arg.size() != sz || !std::equal(i_bra, i, arg.begin())) continue; *buffer << strings_[token.stack_pos + n + 1] << "\376line " << macro_num << ' ' << val.location << "\n\376textdomain " << macro_textdomain << '\n'; i_bra = i_end; break; } if (i_bra != i_end) { // The bracketed text was no macro argument buffer->write(&*i_bra - 1, sz + 2); i_bra = i_end; } } } pop_token(); called_macros_.push_back(symbol); std::string const &dir = directory_name(val.location.substr(0, val.location.find(' '))); if (!slowpath_) { DBG_CF << "substituting macro " << symbol << '\n'; new preprocessor_data(target_, called_macros_, buffer, val.location, "", val.linenum, dir, val.textdomain); } else { DBG_CF << "substituting (slow) macro " << symbol << '\n'; std::ostringstream res; preprocessor_streambuf *buf = new preprocessor_streambuf(target_); { std::istream in(buf); new preprocessor_data(*buf, called_macros_, buffer, val.location, "", val.linenum, dir, val.textdomain); res << in.rdbuf(); } delete buf; strings_.back() += res.str(); } called_macros_.pop_back(); preprocessor::preprocessor(preprocessor_streambuf &t, std::vector &callstack) : old_preprocessor_(t.current_), old_textdomain_(t.textdomain_), old_location_(t.location_), old_linenum_(t.linenum_), target_(t), called_macros_(callstack) { ++target_.depth_; target_.current_ = this; } preprocessor_file::preprocessor_file(preprocessor_streambuf &t, std::vector< std::string > &callstack, std::string const &name) : preprocessor(t,callstack), files_(), pos_(), end_() { if (is_directory(name)) get_files_in_dir(name, &files_, NULL, ENTIRE_FILE_PATH, SKIP_MEDIA_DIR, DO_REORDER); else new preprocessor_data(t, called_macros_, istream_file(name), "", name, 1, directory_name(name), t.textdomain_); pos_ = files_.begin(); end_ = files_.end(); } preprocessor_data::preprocessor_data(preprocessor_streambuf &t, std::vector< std::string > &callstack, std::istream *i, std::string const &history, std::string const &name, int linenum, std::string const &directory, std::string const &domain) : preprocessor(t, callstack), in_(i), directory_(directory), strings_(), tokens_(), slowpath_(0), skipping_(0), linenum_(linenum) { std::ostringstream s; s << history; if (!name.empty()) { std::string ename(name); if (!history.empty()) s << ' '; s << utils::escape(ename, " \\"); } if (!t.location_.empty()) s << ' ' << t.linenum_ << ' ' << t.location_; t.location_ = s.str(); t.linenum_ = linenum; t.textdomain_ = domain; t.buffer_ << "\376line " << linenum << ' ' << t.location_ << "\n\376textdomain " << domain << '\n'; const int fixed_char_count = 22; count_extra_digits(linenum, t.buffer_size_); t.buffer_size_ += t.location_.size() + domain.size() + fixed_char_count; push_token('*'); } std::istream *preprocess_file(std::string const &fname, preproc_map *defines, std::string *error_log) { log_scope("preprocessing file..."); preproc_map *owned_defines = NULL; if (!defines) { // If no preproc_map has been given, create a new one, // and ensure it is destroyed when the stream is // ?? // by giving it to the deleter. owned_defines = new preproc_map; defines = owned_defines; } preprocessor_streambuf *buf = new preprocessor_streambuf(defines, error_log); std::vector call_stack; new preprocessor_file(*buf, call_stack, fname); if(error_log!=NULL&&error_log->empty()==false) throw preproc_config::error("Error preprocessing files."); return new preprocessor_deleter(buf, owned_defines); }