+2009-07-03 Roland McGrath <roland@redhat.com>
+
+ * c++/dwarf_edit: Fix copy construction using a ref-maker.
+ * c++/dwarf_data: Updates.
+ * c++/subr.hh: Updates.
+ * c++/dwarf_ref_maker: New file.
+ * Makefile.am (pkginclude_HEADERS): Add it.
+
2009-07-02 Roland McGrath <roland@redhat.com>
* c++/dwarf: Get rid of VS::unit_reference.
pkginclude_HEADERS = libdw.h \
c++/subr.hh c++/dwarf_data \
c++/dwarf c++/dwarf_edit c++/dwarf_output \
- c++/dwarf_tracker c++/dwarf_comparator
+ c++/dwarf_tracker c++/dwarf_ref_maker \
+ c++/dwarf_comparator
libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \
dwarf_getpubnames.c dwarf_getabbrev.c dwarf_tag.c \
class attributes_type;
attributes_type attributes () const;
+ class const_pointer;
+
inline int tag () const
{
int t = ::dwarf_tag (thisdie ());
}
};
+ // Actually always const.
+ typedef const_iterator iterator;
+
const_iterator begin () const
{
return const_iterator (raw_children_type::begin ());
}
};
+ class debug_info_entry::const_pointer
+ : public debug_info_entry::children_type::const_iterator
+ {};
+
private:
static inline bool skip_sibling (const attribute &attr)
{
inline std::string to_string () const;
// Return an iterator on which * will yield the referent debug_info_entry.
- inline debug_info_entry::raw_children_type::const_iterator
+ inline debug_info_entry::children_type::const_iterator
reference () const
{
return (debug_info_entry::raw_children_type::const_iterator
typedef typename dwarf2_die::children_type::const_iterator die2;
typedef typename dwarf1_die::attributes_type::const_iterator attr1;
typedef typename dwarf2_die::attributes_type::const_iterator attr2;
+ typedef typename dwarf1_die::children_type::iterator dwarf1_ref;
// This object is created to start a walk and destroyed to finish one.
struct walk
const left_context_type &, const die1 &,
const right_context_type &, const die2 &)
{}
-
};
template<class dwarf1, class dwarf2,
inline bool match (const cu1_it &a, const cu2_it &b)
{
typename tracker::walk in (&_m_tracker, a, b);
- return match (static_cast<die1> (*a), static_cast<die2> (*b));
+ return match (*a, *b);
}
inline bool match (const die1 &a, const die2 &b)
template<typename flavor, typename input, typename arg_type>
static inline value_dispatch *
- make (flavor *&result, const input &x, const arg_type &arg)
+ make (flavor *&result, const input &x, arg_type &arg)
{
return result = new flavor (x, arg);
}
inline value_string () {}
template<typename string, typename arg_type>
- inline value_string (const string &s, const arg_type &arg)
+ inline value_string (const string &s, arg_type &arg)
: std::string (s)
{}
struct value_identifier : public value_string
{
template<typename id, typename arg_type>
- inline value_identifier (const id &s, const arg_type &arg)
+ inline value_identifier (const id &s, arg_type &arg)
: value_string (s, arg)
{}
};
{}
template<typename iter, typename tracker>
- inline value_reference (const iter &i, tracker *t)
- : ref ()
- {}
+ inline value_reference (const iter &i, tracker &t)
+ : ref () // Invalid until t.finish ().
+ {
+ t.refer (&ref, i);
+ }
};
struct value_flag : public value_dispatch
{}
template<typename arg_type>
- inline value_flag (bool t, const arg_type &arg)
+ inline value_flag (bool t, arg_type &arg)
: flag (t)
{}
};
{}
template<typename arg_type>
- inline value_address (::Dwarf_Addr x, const arg_type &arg)
+ inline value_address (::Dwarf_Addr x, arg_type &arg)
: addr (x)
{}
};
inline value_rangelistptr () {}
template<typename list, typename arg_type>
- inline value_rangelistptr (const list &other, const arg_type &arg)
+ inline value_rangelistptr (const list &other, arg_type &arg)
: range_list (other)
{}
};
inline value_lineptr () {}
template<typename table, typename arg_type>
- inline value_lineptr (const table &other, const arg_type &arg)
+ inline value_lineptr (const table &other, arg_type &arg)
: impl::line_info_table (other)
{}
};
{}
template<typename arg_type>
- inline value_constant (::Dwarf_Word x, const arg_type &arg)
+ inline value_constant (::Dwarf_Word x, arg_type &arg)
: word (x)
{}
};
inline value_constant_block () {}
template<typename block, typename arg_type>
- inline value_constant_block (const block &b, const arg_type &arg)
+ inline value_constant_block (const block &b, arg_type &arg)
: std::vector<uint8_t> (b.begin (), b.end ())
{}
};
inline value_dwarf_constant () {}
template<typename constant, typename arg_type>
- inline value_dwarf_constant (const constant &other, const arg_type &arg)
+ inline value_dwarf_constant (const constant &other, arg_type &arg)
: dwarf_enum (other)
{}
};
inline value_source_file () {}
template<typename file, typename arg_type>
- inline value_source_file (const file &other, const arg_type &arg)
+ inline value_source_file (const file &other, arg_type &arg)
: source_file (other)
{}
};
{}
template<typename arg_type>
- inline value_source_line (unsigned int m, const arg_type &arg)
+ inline value_source_line (unsigned int m, arg_type &arg)
: n (m)
{}
};
inline value_location () {}
template<typename loc, typename arg_type>
- inline value_location (const loc &other, const arg_type &arg)
+ inline value_location (const loc &other, arg_type &arg)
: location_attr (other)
{}
};
};
+ // Forward decl.
+ template<class impl, typename v = value<impl> > class attributes_type;
+
template<class impl, typename vw = value<impl> >
class attr_value
{
+ friend class attributes_type<impl, vw>;
+
private:
typename vw::value_dispatch *_m_value;
+ typedef typename impl::debug_info_entry::pointer die_ptr;
- template<typename value, typename arg_type = nothing>
+ template<typename value, typename arg_type = const nothing>
struct init
{
inline init (attr_value *av,
- const value &other, const arg_type &arg = arg_type ())
+ const value &other, arg_type &arg = arg_type ())
{
switch (other.what_space ())
{
}
};
+ // This kosher only when freshly default-constructed.
+ template<typename value, typename arg_type>
+ inline void set (const value &other, arg_type &arg)
+ {
+ assert (_m_value == NULL);
+ init<value, arg_type> me (this, other, arg);
+ }
+
template<typename flavor>
inline flavor &const_variant () const
{
}
template<typename value, typename arg_type>
- attr_value (const value &other, const arg_type &arg)
+ attr_value (const value &other, arg_type &arg)
: _m_value (NULL)
{
- init<value, arg_type> me (this, other, arg);
+ set (this, other, arg);
}
inline attr_value ()
return variant<typename vw::value_address> ().addr;
}
- inline typename impl::debug_info_entry::pointer &reference () const
+ inline die_ptr &reference () const
{
return variant<typename vw::value_reference> ().ref;
}
- inline typename impl::debug_info_entry::pointer &reference ()
+ inline die_ptr &reference ()
{
return variant<typename vw::value_reference> ().ref;
}
}
};
- template<class impl, typename arg = nothing, typename v = value<impl> >
+ template<class impl, typename v>
class attributes_type
: public std::map<int, attr_value<impl, v> >
{
inline attributes_type () {}
public: // XXX should be protected
+
+ /* We don't use the base_type (begin, end) iterator constructor here
+ for good reason. The ref-maker needs to collect back-pointers
+ into our mapped_value (attr_value) objects. It would not fly to
+ have that done in a temporary attr_value object that gets copied
+ into the map cell by assignment. We must make sure that when a
+ value_reference is constructed, it is really the one sitting in
+ our map that the ref-maker will want to update later. */
template<typename input, typename arg_type>
- inline attributes_type (const input &other, const arg_type &c)
- : base_type (subr::argify2nd<input, attributes_type, arg_type>
+ inline attributes_type (const input &other, arg_type &c)
+ : base_type ()
+ {
+ for (typename input::const_iterator attr = other.begin ();
+ attr != other.end ();
+ ++attr)
+ (*this)[(*attr).first].set ((*attr).second, c);
+ }
+
+#if 0
+ // dwarf_output probably will do it this way (?)
+ template<typename input, typename arg_type>
+ inline attributes_type (const input &other, arg_type &c)
+ : base_type (subr::argify2nd<input, attributes_type, arg_type &>
(other.begin (), c),
- subr::argify2nd<input, attributes_type, arg_type>
+ subr::argify2nd<input, attributes_type, arg_type &>
(other.end (), c))
{}
+#endif
public:
typedef typename base_type::key_type key_type;
#include "dwarf"
#include "dwarf_data"
-#include "dwarf_tracker"
+#include "dwarf_ref_maker"
/* Read the comments for elfutils::dwarf first.
{
friend class debug_info_entry;
private:
- children_type () {}
+ inline children_type () {}
template<typename input, typename tracker>
- children_type (const input &other, tracker *t)
- : std::list<debug_info_entry>
- (subr::argify<input, children_type, tracker *> (other.begin (), t),
- subr::argify<input, children_type, tracker *> (other.end (), t))
- {}
+ inline children_type (const input &other, tracker &t)
+ {
+ for (typename input::const_iterator in = other.begin ();
+ in != other.end ();
+ ++in)
+ {
+ /* Don't copy-construct the entry from *in here because that
+ copies it again into the list and destroys the first copy. */
+ push_back (debug_info_entry ());
+ iterator out = --end ();
+ out->set (*in, t);
+ t.equivalence (out, in);
+ }
+ }
public:
typedef debug_info_entry value_type;
inline attributes_type () {}
template<typename attrs, typename tracker>
- inline attributes_type (const attrs &other, tracker *t)
+ inline attributes_type (const attrs &other, tracker &t)
: base_type (other, t)
{}
};
- private:
- const int _m_tag;
+ protected:
+ int _m_tag;
attributes_type _m_attributes;
children_type _m_children;
+ // This is can only be used by the children_type constructor,
+ // which immediately calls set.
+ inline debug_info_entry ()
+ : _m_tag (-1), _m_attributes (), _m_children ()
+ {}
+
+ template<typename die_type, typename arg_type>
+ inline void set (const die_type &die, arg_type &arg)
+ {
+ _m_attributes.clear ();
+ _m_children.clear ();
+ _m_tag = die.tag ();
+ _m_attributes.swap (attributes_type (die.attributes (), arg));
+ _m_children.swap (children_type (die.children (), arg));
+ }
+
public:
- debug_info_entry (int t) : _m_tag (t)
+ inline debug_info_entry (int t)
+ : _m_tag (t), _m_attributes (), _m_children ()
{
if (unlikely (t <= 0))
throw std::invalid_argument ("invalid tag");
/* The template constructor lets us copy in from any class that has
compatibly iterable containers for attributes and children. */
template<typename die_type, typename tracker>
- debug_info_entry (const die_type &die, tracker *t)
+ debug_info_entry (const die_type &die, tracker &t)
: _m_tag (die.tag ()),
_m_attributes (die.attributes (), t),
_m_children (die.children (), t)
// XXX should be private
public:
template<typename die_type, typename tracker>
- inline compile_unit (const die_type &die, tracker *t)
+ inline compile_unit (const die_type &die, tracker &t)
: debug_info_entry (die, t)
{
if (die.tag () != ::DW_TAG_compile_unit)
typedef std::list<compile_unit> _base;
// Default constructor: an empty container, no CUs.
- inline compile_units ()
- {}
+ inline compile_units () {}
// Constructor copying CUs from input container.
template<typename input, typename tracker>
- inline compile_units (const input &units, tracker *t)
- : _base (subr::argify<input, compile_units, tracker *>
+ inline compile_units (const input &other, tracker &t)
+ {
+ for (typename input::const_iterator in = other.begin ();
+ in != other.end ();
+ ++in)
+ {
+ /* Don't copy-construct the entry from *in here because that
+ copies it again into the list and destroys the first copy. */
+ push_back (compile_unit ());
+ iterator out = --end ();
+ out->set (*in, t);
+ }
+ }
+#if 0 // dwarf_output might use this (?)
+ template<typename input, typename tracker>
+ inline compile_units (const input &units, tracker &t)
+ : _base (subr::argify<input, compile_units, tracker &>
(units.begin (), t),
- subr::argify<input, compile_units, tracker *>
+ subr::argify<input, compile_units, tracker &>
(units.end (), t))
{}
+#endif
public:
typedef compile_unit value_type;
public:
// Default constructor: an empty container, no CUs.
- inline dwarf_edit () {}
+ inline dwarf_edit ()
+ : _m_units ()
+ {}
// Constructor copying CUs from an input file (dwarf or dwarf_edit).
template<typename input, typename tracker>
- dwarf_edit (const input &dw, tracker *t)
- : _m_units (dw.compile_units (), t)
- {}
+ inline dwarf_edit (const input &dw, tracker &t,
+ subr::guard<tracker> guard = subr::guard<tracker> ())
+ : _m_units (dw.compile_units (), guard (t))
+ {
+ guard.clear ();
+ }
+
+ // Copying constructor with default ref-maker.
+ template<typename input>
+ inline dwarf_edit (const input &dw,
+ dwarf_ref_maker<dwarf_edit, input> t
+ = dwarf_ref_maker<dwarf_edit, input> (),
+ subr::guard<dwarf_ref_maker<dwarf_edit, input> > guard
+ = subr::guard<dwarf_ref_maker<dwarf_edit, input> > ())
+ : _m_units (dw.compile_units (), guard (t))
+ {
+ guard.clear ();
+ }
template<typename file>
inline bool operator== (const file &other) const
private:
template<typename input>
static inline const input &
- collect (dwarf_output_collector *c,
+ collect (dwarf_output_collector &c,
const subr::auto_ref<const input> &p)
{
return static_cast<const input &> (p);
template<typename input>
static inline const debug_info_entry &
- collect (dwarf_output_collector *,
+ collect (dwarf_output_collector &,
const typename input::debug_info_entry &);
public:
/* The template constructor lets us copy in from any class that has
compatibly iterable containers for attributes and children. */
template<typename die_type>
- debug_info_entry (const die_type &die, dwarf_output_collector *c)
+ debug_info_entry (const die_type &die, dwarf_output_collector &c)
: _m_tag (die.tag ()),
_m_attributes (die.attributes ()),
_m_children (die.children ()),
template<typename input>
struct make
: public std::binary_function<typename input::value_type,
- dwarf_output_collector *,
+ dwarf_output_collector &,
_base::value_type>
{
_base::value_type operator () (const typename input::value_type &cu,
- dwarf_output_collector *c) const
+ dwarf_output_collector &c) const
{
return _base::value_type (collect (c, cu));
}
// Constructor copying CUs from input container.
template<typename input>
- compile_units (const input &units, dwarf_output_collector *c)
+ compile_units (const input &units, dwarf_output_collector &c)
: _base ()
{
for (typename input::const_iterator it = units.begin ();
return !(*this == other);
}
- void recollect (dwarf_output_collector *c)
+ void recollect (dwarf_output_collector &c)
{
std::transform (begin (), end (), begin (),
std::bind2nd (make<compile_units> (), c));
// Constructor copying CUs from an input file (can be any of dwarf,
// dwarf_edit, or dwarf_output).
template<typename input>
- dwarf_output (const input &dw, dwarf_output_collector *c)
+ dwarf_output (const input &dw, dwarf_output_collector &c)
: _m_units (dw.compile_units (), c)
{}
template<typename input>
static inline const std::string &
- collect_string (dwarf_output_collector *, const input &);
+ collect_string (dwarf_output_collector &c, const input &);
/* An iterator adapter for use in iterator-based constructors.
collectify (iterator) yields an iterator on input where *i
constructs output::value_type (input::value_type v, collector). */
template<typename input, typename output>
static inline typename subr::argifier<input, output,
- dwarf_output_collector *>::result_type
+ dwarf_output_collector &>::result_type
collectify (const typename input::const_iterator &in,
- dwarf_output_collector *c)
+ dwarf_output_collector &c)
{
- return subr::argifier<input, output, dwarf_output_collector *> (c) (in);
+ return subr::argifier<input, output, dwarf_output_collector &> (c) (in);
}
struct value_wrapper
const std::string &_m_str;
template<typename string>
- inline value_string (const string &s, dwarf_output_collector *c)
+ inline value_string (const string &s, dwarf_output_collector &c)
: _m_str (collect_string (c, s))
{}
template<typename input>
static inline value_dispatch *
- make (value_string *&result, const input &x, dwarf_output_collector *c)
+ make (value_string *&result, const input &x, dwarf_output_collector &c)
{
return result = new value_string (x, c);
}
children_type () {}
template<typename input>
- inline children_type (const input &other, dwarf_output_collector *c)
+ inline children_type (const input &other, dwarf_output_collector &c)
: std::list<debug_info_entry>
(collectify<input, children_type> (other.begin (), c),
collectify<input, children_type> (other.end (), c))
typedef children_type::const_iterator pointer;
class attributes_type
- : public dwarf_data::attributes_type<dwarf_output,
- dwarf_output_collector *,
- value_wrapper>
+ : public dwarf_data::attributes_type<dwarf_output, value_wrapper>
{
friend class debug_info_entry;
private:
typedef dwarf_data::attributes_type<dwarf_output,
- dwarf_output_collector *,
value_wrapper> base_type;
template<typename input>
- inline attributes_type (const input &other, dwarf_output_collector *c)
+ inline attributes_type (const input &other, dwarf_output_collector &c)
: base_type (other, c)
{}
};
public:
template<typename die_type>
- debug_info_entry (const die_type &die, dwarf_output_collector *c)
+ debug_info_entry (const die_type &die, dwarf_output_collector &c)
: _m_tag (die.tag ()),
_m_attributes (die.attributes (), c),
_m_children (die.children (), c)
// XXX should be private
public:
template<typename die_type>
- compile_unit (const die_type &die, dwarf_output_collector *c)
+ compile_unit (const die_type &die, dwarf_output_collector &c)
: debug_info_entry (die, c)
{
if (die.tag () != ::DW_TAG_compile_unit)
// Constructor copying CUs from input container.
template<typename input>
- compile_units (const input &units, dwarf_output_collector *c)
+ compile_units (const input &units, dwarf_output_collector &c)
: _base (collectify<input, compile_units> (units.begin (), c),
collectify<input, compile_units> (units.end (), c))
{
// Constructor copying CUs from an input file (can be any of dwarf,
// dwarf_edit, or dwarf_output).
template<typename input>
- dwarf_output (const input &dw, dwarf_output_collector *c)
+ dwarf_output (const input &dw, dwarf_output_collector &c)
: _m_units (dw.compile_units (), c)
{}
subr::value_set<std::string> _m_strings;
subr::value_set<dwarf_output::range_list> _m_ranges;
+ public:
+
+ template<typename die1, typename die2> // XXX
+ inline void equivalence (const die1 &a, const die2 &b) {}
+
+ template<typename die1, typename die2> // XXX
+ inline void refer (die1 *ref, const die2 &b) {}
};
template<typename input>
inline const std::string &
- dwarf_output::collect_string (dwarf_output_collector *c, const input &s)
+ dwarf_output::collect_string (dwarf_output_collector &c, const input &s)
{
- return c->_m_strings.add (s);
+ return c._m_strings.add (s);
}
};
--- /dev/null
+/* elfutils::dwarf_ref_maker -- -*- C++ -*- template type specification
+ Copyright (C) 2009 Red Hat, Inc.
+ This file is part of Red Hat elfutils.
+
+ Red Hat elfutils is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by the
+ Free Software Foundation; version 2 of the License.
+
+ Red Hat elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with Red Hat elfutils; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+ In addition, as a special exception, Red Hat, Inc. gives You the
+ additional right to link the code of Red Hat elfutils with code licensed
+ under any Open Source Initiative certified open source license
+ (http://www.opensource.org/licenses/index.php) which requires the
+ distribution of source code with any binary distribution and to
+ distribute linked combinations of the two. Non-GPL Code permitted under
+ this exception must only link to the code of Red Hat elfutils through
+ those well defined interfaces identified in the file named EXCEPTION
+ found in the source code files (the "Approved Interfaces"). The files
+ of Non-GPL Code may instantiate templates or use macros or inline
+ functions from the Approved Interfaces without causing the resulting
+ work to be covered by the GNU General Public License. Only Red Hat,
+ Inc. may make changes or additions to the list of Approved Interfaces.
+ Red Hat's grant of this exception is conditioned upon your not adding
+ any new exceptions. If you wish to add a new Approved Interface or
+ exception, please contact Red Hat. You must obey the GNU General Public
+ License in all respects for all of the Red Hat elfutils code and other
+ code used in conjunction with Red Hat elfutils except the Non-GPL Code
+ covered by this exception. If you modify this file, you may extend this
+ exception to your version of the file, but you are not obligated to do
+ so. If you do not wish to provide this exception without modification,
+ you must delete this exception statement from your version and license
+ this file solely under the GPL without exception.
+
+ Red Hat elfutils is an included package of the Open Invention Network.
+ An included package of the Open Invention Network is a package for which
+ Open Invention Network licensees cross-license their patents. No patent
+ license is granted, either expressly or impliedly, by designation as an
+ included package. Should you wish to participate in the Open Invention
+ Network licensing program, please visit www.openinventionnetwork.com
+ <http://www.openinventionnetwork.com>. */
+
+#ifndef _ELFUTILS_DWARF_REF_MAKER
+#define _ELFUTILS_DWARF_REF_MAKER 1
+
+#include "dwarf"
+#include <tr1/unordered_map>
+#include <vector>
+
+namespace elfutils
+{
+ // Prototypical stub for reference maker object.
+ // This keeps no state and can't really be used.
+ template<class output, class input>
+ struct dwarf_ref_maker_base
+ {
+ typedef typename input::debug_info_entry input_entry;
+ typedef typename input_entry::children_type::const_iterator input_ref;
+ typedef typename output::debug_info_entry::pointer output_ref;
+
+ // These are called around a whole-file construction.
+ inline void start () {}
+
+ // If called, all pointers passed in since start () before are bogus.
+ inline void abort () {}
+
+ // Construction is complete: now snap in all recorded references.
+ inline void finish (output &file) {}
+
+ // The referenced output DIE has been constructed to match the input DIE.
+ inline void equivalence (const output_ref &to, const input_ref &from)
+ {
+ }
+
+ // *REF is an uninitialized attr_value.reference ().
+ // It's meant to refer to the output DIE equivalent to the given input DIE.
+ inline void refer (output_ref *ref, const input_ref &target)
+ {
+ throw std::logic_error ("dwarf_ref_maker_base cannot make references");
+ }
+ };
+
+ // Simple maker used for a single copy-construction.
+ template<class output, class input>
+ class dwarf_ref_maker : public dwarf_ref_maker_base<output, input>
+ {
+ public:
+ typedef typename input::debug_info_entry input_entry;
+ typedef typename output::debug_info_entry output_entry;
+ typedef typename input_entry::children_type::const_iterator input_ref;
+ typedef typename output_entry::children_type::iterator output_ref;
+
+ private:
+
+ struct seen
+ {
+ bool _m_known;
+ output_ref _m_out;
+ std::vector<output_ref *> _m_refs;
+
+ inline seen ()
+ : _m_known (false), _m_out (), _m_refs ()
+ {}
+
+ inline void resolve ()
+ {
+ for (; !_m_refs.empty (); _m_refs.pop_back ())
+ *_m_refs.back () = _m_out;
+ }
+
+ inline void resolve (const output_ref &to)
+ {
+ _m_out = to;
+ _m_known = true;
+ resolve ();
+ }
+
+ inline void refer (output_ref *out)
+ {
+ _m_refs.push_back (out);
+ if (_m_known)
+ resolve ();
+ }
+ };
+
+ std::tr1::unordered_map< ::Dwarf_Off, seen> _m_map;
+
+ public:
+ inline dwarf_ref_maker ()
+ : _m_map ()
+ {}
+
+ inline dwarf_ref_maker (const dwarf_ref_maker &other)
+ : _m_map ()
+ {
+ if (unlikely (!other._m_map.empty ()))
+ throw std::logic_error
+ ("dwarf_ref_maker copy constructs only from default-constructed");
+ }
+
+ inline ~dwarf_ref_maker ()
+ {}
+
+ inline void abort ()
+ {
+ _m_map.clear ();
+ }
+
+ inline void equivalence (const output_ref &out, const input_ref &in)
+ {
+ _m_map[in->identity ()].resolve (out);
+ }
+
+ inline void refer (output_ref *out, const input_ref &in)
+ {
+ _m_map[in->identity ()].refer (out);
+ }
+
+ inline void finish (output &file)
+ {
+ while (_m_map.begin () != _m_map.end ())
+ if (_m_map.begin ()->second._m_known)
+ _m_map.erase (_m_map.begin ());
+ else
+ throw std::logic_error ("construction finished with unresolved refs");
+ }
+ };
+
+};
+
+#endif // <elfutils/dwarf_ref_maker>
typedef typename _base::cu2 cu2;
typedef typename _base::die1 die1;
typedef typename _base::die2 die2;
+ typedef typename _base::dwarf1_ref dwarf1_ref;
private:
template<typename cu, typename die>
/* A wrapped_input_iterator is like an input::const_iterator,
but *i returns wrapper (*i) instead; wrapper returns element
(or const element & or something). */
- template<typename input, typename wrapper,
+ template<typename input, class wrapper,
typename element = typename wrapper::result_type>
class wrapped_input_iterator : public input::const_iterator
{
private:
typedef typename input::const_iterator _base;
- wrapper *_m_wrapper;
+ wrapper _m_wrapper;
public:
typedef element value_type;
- inline wrapped_input_iterator (const _base &i, wrapper &w)
- : _base (static_cast<_base> (i)), _m_wrapper (&w)
+ template<typename arg_type>
+ inline wrapped_input_iterator (const _base &i, const arg_type &arg)
+ : _base (static_cast<_base> (i)), _m_wrapper (arg)
{}
inline wrapped_input_iterator (const wrapped_input_iterator &i)
inline typename wrapper::result_type operator* () const
{
- return (*_m_wrapper) (_base::operator* ());
+ return _m_wrapper (_base::operator* ());
}
};
struct maker
: public std::unary_function<inlet, outlet>
{
- arg_type _m_arg;
- explicit inline maker (const arg_type &c) : _m_arg (c) {}
+ const arg_type _m_arg;
+
+ inline maker (const arg_type &c)
+ : _m_arg (c)
+ {}
+
+ inline maker (const maker &m)
+ : _m_arg (m._m_arg)
+ {}
inline outlet operator () (const inlet &x) const
{
: _m_maker (c)
{}
- typedef subr::wrapped_input_iterator<input, maker> result_type;
+ typedef wrapped_input_iterator<input, maker> result_type;
inline result_type operator () (const inny &i)
{
/* Wrapper worker passed to wrapped_input_iterator.
This object holds the collector pointer. */
- struct maker
- : public std::unary_function<inlet, outlet>
+ struct pair_maker
+ : public argifier<input, output, arg_type>::maker
{
- arg_type _m_arg;
- explicit inline maker (const arg_type &c) : _m_arg (c) {}
+ typedef typename argifier<input, output, arg_type>::maker maker;
+
+ inline pair_maker (const arg_type &c) : maker (c) {}
+ inline pair_maker (const pair_maker &m) : maker (m) {}
inline outlet operator () (const inlet &x) const
{
return std::make_pair (x.first,
typename outlet::second_type (x.second,
- _m_arg));
+ this->_m_arg));
}
} _m_maker;
: _m_maker (c)
{}
- typedef subr::wrapped_input_iterator<input, maker> const_iterator;
+ typedef subr::wrapped_input_iterator<input, pair_maker> const_iterator;
inline const_iterator operator () (const inny &i)
{
return argifier2nd<input, output, arg_type> (arg) (in);
}
+ /* A guard object is intended to be ephemeral, existing solely to be
+ destroyed in exception paths where it was not cleared explicitly.
+ In that case, it calls tracker::soiled ().
+
+ For convenience, it can be constructed from a tracker reference or
+ pointer, or default-constructed and then filled. It's fillable by
+ calling the guard object as a function, passing it the tracker
+ reference or pointer, which it passes through on return:
+
+ guard<tracker> g;
+ use (g (t));
+ g.clear ();
+
+ This first calls T.start (). When G goes out of scope,
+ it calls T.abort () iff G.clear () was never called. */
+
+ template<typename tracker>
+ class guard
+ {
+ private:
+ tracker *_m_tracker;
+
+ inline void start ()
+ {
+ _m_tracker->start ();
+ }
+
+ public:
+ inline guard (tracker *t)
+ : _m_tracker (t)
+ {
+ start ();
+ }
+
+ inline guard (tracker &t)
+ : _m_tracker (&t)
+ {
+ start ();
+ }
+
+ inline guard ()
+ : _m_tracker (NULL)
+ {}
+
+ inline tracker *operator () (tracker *t)
+ {
+ _m_tracker = t;
+ start ();
+ return t;
+ }
+
+ inline tracker &operator () (tracker &t)
+ {
+ _m_tracker = &t;
+ start ();
+ return t;
+ }
+
+ inline operator tracker * () const
+ {
+ return _m_tracker;
+ }
+
+ inline operator tracker & () const
+ {
+ return *_m_tracker;
+ }
+
+ inline void clear ()
+ {
+ _m_tracker = NULL;
+ }
+
+ inline ~guard ()
+ {
+ if (unlikely (_m_tracker != NULL))
+ _m_tracker->abort ();
+ }
+ };
};
};
if (test_writer)
{
- dwarf_ref_tracker<dwarf_edit, dwarf> t1;
- dwarf_ref_tracker<dwarf_edit, dwarf> t2;
- dwarf_edit edit1 (file1, &t1);
- dwarf_edit edit2 (file2, &t2);
+ dwarf_edit edit1 (file1);
+ dwarf_edit edit2 (file2);
test_classes (file1, file2, edit1, edit2, same);
+ /*
{
dwarf_output_collector c1;
dwarf_output_collector c2;
- dwarf_output out1 (file1, &c1);
- dwarf_output out2 (file2, &c2);
+ dwarf_output out1 (file1, c1);
+ dwarf_output out2 (file2, c2);
test_classes (file1, file2, out1, out2, same);
test_classes (edit1, edit2, out1, out2, same);
}
{
dwarf_output_collector c1;
dwarf_output_collector c2;
- dwarf_output out1 (edit1, &c1);
- dwarf_output out2 (edit2, &c2);
+ dwarf_output out1 (edit1, c1);
+ dwarf_output out2 (edit2, c2);
test_classes (file1, file2, out1, out2, same);
test_classes (edit1, edit2, out1, out2, same);
}
+ */
}
result = !same;