All pastes #878769 Raw Edit

Unbenannt

public text v1 · immutable
#878769 ·published 2008-01-29 15:01 UTC
rendered paste body
in preprocessor_data::get_chunk()

			if (macro != unknown_macro) {
                
                ERR_CF<<called_macros_.size();
                for(std::vector<std::string>::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<<linenum_<<' '<<target_.location_;
					target_.error(error.str(), location.str());
				}

				std::stringstream *buffer = new std::stringstream;
				std::string::const_iterator i_bra = val.value.end();
				int macro_num = val.linenum;
				std::string macro_textdomain = val.textdomain;
				bool quoting = false;
				for(std::string::const_iterator i = val.value.begin(),
				    i_end = val.value.end(); i != i_end; ++i) {
					char c = *i;
					if (c == '\n') {
						++macro_num;
					} else if (c == '"') {
						quoting = !quoting;
					}

					if (c == '{') {
						if (i_bra != i_end)
							buffer->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<std::string> &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<std::string> 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);
}