summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libdw/c++/dwarf_data252
-rw-r--r--libdw/c++/dwarf_edit23
-rw-r--r--libdw/c++/dwarf_output22
-rw-r--r--tests/Makefile.am6
-rw-r--r--tests/dwarf-print.cc69
-rw-r--r--tests/dwarf_edit.cc68
-rw-r--r--tests/print-die.hh75
7 files changed, 384 insertions, 131 deletions
diff --git a/libdw/c++/dwarf_data b/libdw/c++/dwarf_data
index 423028f2..6d039009 100644
--- a/libdw/c++/dwarf_data
+++ b/libdw/c++/dwarf_data
@@ -52,6 +52,7 @@
#include "dwarf"
#include <bitset>
+#include <typeinfo>
/* This contains common classes/templates used by dwarf_output and dwarf_edit.
@@ -470,7 +471,12 @@ namespace elfutils
private:
typedef std::pair< ::Dwarf_Word, unsigned int> _base;
+ inline dwarf_enum ()
+ : _base (0, 0)
+ {}
+
public:
+
inline dwarf_enum (unsigned int attr, unsigned int value)
: _base (value, attr)
{}
@@ -491,10 +497,26 @@ namespace elfutils
return this->first;
}
+ inline dwarf_enum &operator= (::Dwarf_Word value)
+ {
+ this->first = value;
+ return *this;
+ }
+
inline dwarf_enum &operator= (const dwarf_enum& other)
{
+ if (this->second == 0)
+ {
+ throw std::logic_error("dwarf_enum default constructed");
+ this->second = other.second;
+ }
+ else if (this->second != other.second)
+ throw std::runtime_error
+ ("cannot assign dwarf_constant () from "
+ + dwarf::attributes::name (other.second) + "to "
+ + dwarf::attributes::name (this->second));
+
this->first = other.first;
- this->second = other.second;
return *this;
}
@@ -654,9 +676,8 @@ namespace elfutils
template<typename impl>
struct value
{
- class value_dispatch
+ struct value_dispatch
{
- public:
virtual ~value_dispatch () {}
};
@@ -669,6 +690,8 @@ namespace elfutils
struct value_string : public value_dispatch, public std::string
{
+ inline value_string () {}
+
template<typename string, typename arg_type>
inline value_string (const string &s, const arg_type &arg)
: std::string (s)
@@ -728,6 +751,10 @@ namespace elfutils
{
bool flag;
+ inline value_flag ()
+ : flag (true)
+ {}
+
template<typename arg_type>
inline value_flag (bool t, const arg_type &arg)
: flag (t)
@@ -739,6 +766,10 @@ namespace elfutils
// XXX dwfl, reloc
::Dwarf_Addr addr;
+ inline value_address ()
+ : addr (0)
+ {}
+
template<typename arg_type>
inline value_address (::Dwarf_Addr x, const arg_type &arg)
: addr (x)
@@ -747,6 +778,8 @@ namespace elfutils
struct value_rangelistptr : public value_dispatch, public range_list
{
+ inline value_rangelistptr () {}
+
template<typename list, typename arg_type>
inline value_rangelistptr (const list &other, const arg_type &arg)
: range_list (other)
@@ -755,6 +788,8 @@ namespace elfutils
struct value_lineptr : public value_dispatch, public impl::line_info_table
{
+ inline value_lineptr () {}
+
template<typename table, typename arg_type>
inline value_lineptr (const table &other, const arg_type &arg)
: impl::line_info_table (other)
@@ -769,6 +804,10 @@ namespace elfutils
::Dwarf_Sword sword;
};
+ inline value_constant ()
+ : word (0)
+ {}
+
template<typename arg_type>
inline value_constant (::Dwarf_Word x, const arg_type &arg)
: word (x)
@@ -778,6 +817,8 @@ namespace elfutils
struct value_constant_block : public value_dispatch,
public std::vector<uint8_t>
{
+ inline value_constant_block () {}
+
template<typename block, typename arg_type>
inline value_constant_block (const block &b, const arg_type &arg)
: std::vector<uint8_t> (b.begin (), b.end ())
@@ -786,6 +827,8 @@ namespace elfutils
struct value_dwarf_constant : public value_dispatch, public dwarf_enum
{
+ inline value_dwarf_constant () {}
+
template<typename constant, typename arg_type>
inline value_dwarf_constant (const constant &other, const arg_type &arg)
: dwarf_enum (other)
@@ -794,6 +837,8 @@ namespace elfutils
struct value_source_file : public value_dispatch, public source_file
{
+ inline value_source_file () {}
+
template<typename file, typename arg_type>
inline value_source_file (const file &other, const arg_type &arg)
: source_file (other)
@@ -804,6 +849,10 @@ namespace elfutils
{
unsigned int n;
+ inline value_source_line ()
+ : n (0)
+ {}
+
template<typename arg_type>
inline value_source_line (unsigned int m, const arg_type &arg)
: n (m)
@@ -815,6 +864,8 @@ namespace elfutils
struct value_location : public value_dispatch, public location_attr
{
+ inline value_location () {}
+
template<typename loc, typename arg_type>
inline value_location (const loc &other, const arg_type &arg)
: location_attr (other)
@@ -828,56 +879,60 @@ namespace elfutils
private:
typename vw::value_dispatch *_m_value;
- template<typename value, typename arg_type>
- inline void init (const value &other, const arg_type &arg)
+ template<typename value, typename arg_type = nothing>
+ struct init
{
- switch (other.what_space ())
- {
-#define _DWARF_DATA_AV_MAKE(flavor, fetch) \
- case dwarf::VS_##flavor: \
- { \
- typename vw::value_##flavor *p; \
- _m_value = vw::make (p, other.fetch (), arg); \
- } \
- break
-
- _DWARF_DATA_AV_MAKE (identifier, identifier);
- _DWARF_DATA_AV_MAKE (string, string);
- _DWARF_DATA_AV_MAKE (flag, flag);
- _DWARF_DATA_AV_MAKE (rangelistptr, ranges);
- _DWARF_DATA_AV_MAKE (lineptr, line_info);
- _DWARF_DATA_AV_MAKE (address, address);
- _DWARF_DATA_AV_MAKE (source_line, source_line);
- _DWARF_DATA_AV_MAKE (source_file, source_file);
- _DWARF_DATA_AV_MAKE (dwarf_constant, dwarf_constant);
- _DWARF_DATA_AV_MAKE (reference, reference);
- _DWARF_DATA_AV_MAKE (unit_reference, unit_reference);
- _DWARF_DATA_AV_MAKE (location, location);
- //_DWARF_DATA_AV_MAKE (macptr, macros); XXX
-
- case dwarf::VS_constant:
- if (other.constant_is_integer ())
- {
- typename vw::value_constant *p;
- _m_value = vw::make (p, other.constant (), arg);
- }
- else
- {
- typename vw::value_constant_block *p;
- _m_value = vw::make (p, other.constant_block (), arg);
- }
- break;
-
- default:
- case dwarf::VS_discr_list:
- throw std::runtime_error ("XXX unimplemented");
+ inline init (attr_value *av,
+ const value &other, const arg_type &arg = arg_type ())
+ {
+ switch (other.what_space ())
+ {
+#define _DWARF_DATA_AV_MAKE(flavor, fetch) \
+ case dwarf::VS_##flavor: \
+ { \
+ typename vw::value_##flavor *p; \
+ av->_m_value = vw::make (p, other.fetch (), arg); \
+ } \
+ break
+
+ _DWARF_DATA_AV_MAKE (identifier, identifier);
+ _DWARF_DATA_AV_MAKE (string, string);
+ _DWARF_DATA_AV_MAKE (flag, flag);
+ _DWARF_DATA_AV_MAKE (rangelistptr, ranges);
+ _DWARF_DATA_AV_MAKE (lineptr, line_info);
+ _DWARF_DATA_AV_MAKE (address, address);
+ _DWARF_DATA_AV_MAKE (source_line, source_line);
+ _DWARF_DATA_AV_MAKE (source_file, source_file);
+ _DWARF_DATA_AV_MAKE (dwarf_constant, dwarf_constant);
+ _DWARF_DATA_AV_MAKE (reference, reference);
+ _DWARF_DATA_AV_MAKE (unit_reference, unit_reference);
+ _DWARF_DATA_AV_MAKE (location, location);
+ //_DWARF_DATA_AV_MAKE (macptr, macros); XXX
+
+ case dwarf::VS_constant:
+ if (other.constant_is_integer ())
+ {
+ typename vw::value_constant *p;
+ av->_m_value = vw::make (p, other.constant (), arg);
+ }
+ else
+ {
+ typename vw::value_constant_block *p;
+ av->_m_value = vw::make (p, other.constant_block (), arg);
+ }
+ break;
+
+ default:
+ case dwarf::VS_discr_list:
+ throw std::runtime_error ("XXX unimplemented");
#undef _DWARF_DATA_AV_MAKE
- }
- }
+ }
+ }
+ };
template<typename flavor>
- inline flavor &variant () const
+ inline flavor &const_variant () const
{
flavor *p = dynamic_cast<flavor *> (_m_value);
if (p == NULL)
@@ -885,20 +940,33 @@ namespace elfutils
return *p;
}
+ template<typename flavor>
+ inline flavor &variant () const
+ {
+ return const_variant<flavor> ();
+ }
+
+ template<typename flavor>
+ inline flavor &variant ()
+ {
+ if (_m_value == NULL)
+ _m_value = new flavor;
+ return const_variant<flavor> ();
+ }
+
public:
- /*
attr_value (const attr_value &other)
: _m_value (NULL)
{
- init (other);
+ if (other._m_value != NULL)
+ init<attr_value> me (this, other);
}
- */
template<typename value, typename arg_type>
attr_value (const value &other, const arg_type &arg)
: _m_value (NULL)
{
- init (other, arg);
+ init<value, arg_type> me (this, other, arg);
}
inline attr_value ()
@@ -918,7 +986,7 @@ namespace elfutils
delete _m_value;
_m_value = NULL;
}
- init (other);
+ init<attr_value> me (this, other);
return *this;
}
template<typename value>
@@ -929,7 +997,7 @@ namespace elfutils
delete _m_value;
_m_value = NULL;
}
- init (other);
+ init<value> me (this, other);
return *this;
}
@@ -964,49 +1032,95 @@ namespace elfutils
(variant<typename vw::value_location> ());
}
+ inline std::string &string ()
+ {
+ return static_cast<std::string &>
+ (variant<typename vw::value_string> ());
+ }
inline const std::string &string () const
{
return static_cast<const std::string &>
(variant<typename vw::value_string> ());
}
+ inline std::string &identifier ()
+ {
+ return string ();
+ }
inline const std::string &identifier () const
{
return string ();
}
- inline typename impl::source_file &source_file () const
+ inline const typename impl::source_file &source_file () const
+ {
+ return static_cast<typename impl::source_file &>
+ (variant<typename vw::value_source_file> ());
+ }
+
+ inline typename impl::source_file &source_file ()
{
return static_cast<typename impl::source_file &>
(variant<typename vw::value_source_file> ());
}
- inline unsigned int &source_line () const
+ inline const unsigned int &source_line () const
+ {
+ return variant<typename vw::value_source_line> ().n;
+ }
+
+ inline unsigned int &source_line ()
{
return variant<typename vw::value_source_line> ().n;
}
- inline unsigned int &source_column () const
+ inline const unsigned int &source_column () const
+ {
+ return variant<typename vw::value_source_column> ().n;
+ }
+
+ inline unsigned int &source_column ()
{
return variant<typename vw::value_source_column> ().n;
}
- inline ::Dwarf_Word &constant () const
+ inline const ::Dwarf_Word &constant () const
+ {
+ return variant<typename vw::value_constant> ().word;
+ }
+
+ inline ::Dwarf_Word &constant ()
{
return variant<typename vw::value_constant> ().word;
}
- inline ::Dwarf_Sword &signed_constant () const
+ inline const ::Dwarf_Sword &signed_constant () const
+ {
+ return variant<typename vw::value_constant> ().sword;
+ }
+
+ inline ::Dwarf_Sword &signed_constant ()
{
return variant<typename vw::value_constant> ().sword;
}
- inline std::vector<uint8_t> &constant_block () const
+ inline const std::vector<uint8_t> &constant_block () const
+ {
+ return static_cast<std::vector<uint8_t> &>
+ (variant<typename vw::value_constant_block> ());
+ }
+
+ inline std::vector<uint8_t> &constant_block ()
{
return static_cast<std::vector<uint8_t> &>
(variant<typename vw::value_constant_block> ());
}
- inline typename impl::dwarf_enum &dwarf_constant () const
+ inline const typename impl::dwarf_enum &dwarf_constant () const
+ {
+ return variant<typename vw::value_dwarf_constant> ();
+ }
+
+ inline typename impl::dwarf_enum &dwarf_constant ()
{
return variant<typename vw::value_dwarf_constant> ();
}
@@ -1016,13 +1130,25 @@ namespace elfutils
return dynamic_cast<typename vw::value_constant *> (_m_value) != NULL;
}
- inline typename impl::range_list &ranges () const
+ inline const typename impl::range_list &ranges () const
+ {
+ return static_cast<range_list &>
+ (variant<typename vw::value_rangelistptr> ());
+ }
+
+ inline typename impl::range_list &ranges ()
{
return static_cast<range_list &>
(variant<typename vw::value_rangelistptr> ());
}
- inline typename impl::line_info_table &line_info () const
+ inline const typename impl::line_info_table &line_info () const
+ {
+ return static_cast<typename impl::line_info_table &>
+ (variant<typename vw::value_lineptr> ());
+ }
+
+ inline typename impl::line_info_table &line_info ()
{
return static_cast<typename impl::line_info_table &>
(variant<typename vw::value_lineptr> ());
diff --git a/libdw/c++/dwarf_edit b/libdw/c++/dwarf_edit
index 239fb3f7..8e12c5da 100644
--- a/libdw/c++/dwarf_edit
+++ b/libdw/c++/dwarf_edit
@@ -119,6 +119,12 @@ namespace elfutils
public:
typedef debug_info_entry value_type;
+
+ inline debug_info_entry &add_entry (int tag)
+ {
+ push_back (debug_info_entry (tag));
+ return back ();
+ }
};
class attributes_type
@@ -207,6 +213,12 @@ namespace elfutils
{
return identity ();
}
+
+ // Convenience entry points.
+ inline debug_info_entry &add_entry (int child_tag)
+ {
+ return children ().add_entry (child_tag);
+ }
};
typedef debug_info_entry::attributes_type::value_type attribute;
@@ -258,10 +270,9 @@ namespace elfutils
typedef _base::iterator iterator;
typedef _base::const_iterator const_iterator;
- inline compile_unit &new_unit ()
+ inline compile_unit &add_unit ()
{
- compile_unit nu;
- push_back (nu);
+ push_back (compile_unit ());
return back ();
}
@@ -290,6 +301,12 @@ namespace elfutils
return _m_units;
}
+ // Convenience entry point.
+ inline compile_unit &add_unit ()
+ {
+ return compile_units ().add_unit ();
+ }
+
public:
// Default constructor: an empty container, no CUs.
inline dwarf_edit () {}
diff --git a/libdw/c++/dwarf_output b/libdw/c++/dwarf_output
index 255afa27..ff2621ba 100644
--- a/libdw/c++/dwarf_output
+++ b/libdw/c++/dwarf_output
@@ -328,6 +328,28 @@ namespace elfutils
return result;
}
};
+
+ template<typename flavor, typename input>
+ static inline value_dispatch *
+ make (flavor *&result, const input &x, const dwarf_data::nothing &)
+ {
+ throw std::logic_error ("dwarf_output cannot be default-constructed");
+ }
+
+ template<typename flavor, typename input, typename arg_type>
+ static inline value_dispatch *
+ make (flavor *&result, const input &x, const arg_type &arg)
+ {
+ return result = new flavor (x, arg);
+ }
+
+ template<typename input>
+ static inline value_dispatch *
+ make (value_string *&result, const input &x, dwarf_output_collector *c)
+ {
+ return result = new value_string (x, c);
+ }
+
};
public:
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ba950088..3531c9d2 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -60,7 +60,8 @@ noinst_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \
find-prologues funcretval allregs rdwrmmap \
dwfl-bug-addr-overflow arls dwfl-bug-fd-leak \
dwfl-addr-sect dwfl-bug-report early-offscn \
- dwfl-bug-getmodules dwarf-getmacros dwarf-print
+ dwfl-bug-getmodules dwarf-getmacros dwarf-print \
+ dwarf_edit
# get-ciefde
asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
asm-tst6 asm-tst7 asm-tst8 asm-tst9
@@ -193,6 +194,9 @@ libdwpp = ../libdw/libdwpp.a $(libdw)
dwarf_print_SOURCES = dwarf-print.cc
dwarf_print_LDADD = $(libdwpp) $(libmudflap) -ldl
+dwarf_edit_SOURCES = dwarf_edit.cc
+dwarf_edit_LDADD = $(libdwpp) $(libmudflap) -ldl
+
arextract_LDADD = $(libelf) $(libmudflap)
arsymtest_LDADD = $(libelf) $(libmudflap)
newfile_LDADD = $(libelf) $(libmudflap)
diff --git a/tests/dwarf-print.cc b/tests/dwarf-print.cc
index d37a006a..8d09ba15 100644
--- a/tests/dwarf-print.cc
+++ b/tests/dwarf-print.cc
@@ -41,6 +41,8 @@
using namespace elfutils;
using namespace std;
+#include "print-die.hh"
+
static Dwarf *
open_file (const char *fname)
{
@@ -57,75 +59,14 @@ open_file (const char *fname)
return dw;
}
-static void
-print_die (const dwarf::debug_info_entry &die,
- unsigned int indent, unsigned int limit)
-{
- string prefix (indent, ' ');
- const string tag = dwarf::tags::name (die.tag ());
-
- cout << prefix << "<" << tag << " offset=[" << die.offset () << "]";
-
- for (dwarf::debug_info_entry::attributes_type::const_iterator i
- = die.attributes ().begin (); i != die.attributes ().end (); ++i)
- cout << " " << (*i).to_string ();
-
- if (die.has_children ())
- {
- if (limit != 0 && indent >= limit)
- {
- cout << ">...\n";
- return;
- }
-
- cout << ">\n";
-
- for (dwarf::debug_info_entry::children_type::const_iterator i
- = die.children ().begin (); i != die.children ().end (); ++i)
- print_die (*i, indent + 1, limit);
-
- cout << prefix << "</" << tag << ">\n";
- }
- else
- cout << "/>\n";
-}
-
-static void
-process_file (const char *file, unsigned int limit)
-{
- dwarf dw (open_file (file));
-
- cout << file << ":\n";
-
- for (dwarf::compile_units::const_iterator i = dw.compile_units ().begin ();
- i != dw.compile_units ().end ();
- ++i)
- print_die (*i, 1, limit);
-}
-
int
main (int argc, char *argv[])
{
- /* Set locale. */
- (void) setlocale (LC_ALL, "");
-
- /* Make sure the message catalog can be found. */
- (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
-
- /* Initialize the message catalog. */
- (void) textdomain (PACKAGE_TARNAME);
-
- cout << hex << setiosflags (ios::showbase);
-
- unsigned int depth = 0;
- if (argc > 1 && sscanf (argv[1], "--depth=%u", &depth) == 1)
- {
- --argc;
- ++argv;
- }
+ unsigned int depth;
+ print_die_main (argc, argv, depth);
for (int i = 1; i < argc; ++i)
- process_file (argv[i], depth);
+ print_file (argv[i], dwarf (open_file (argv[i])), depth);
return 0;
}
diff --git a/tests/dwarf_edit.cc b/tests/dwarf_edit.cc
new file mode 100644
index 00000000..35e6b1c2
--- /dev/null
+++ b/tests/dwarf_edit.cc
@@ -0,0 +1,68 @@
+/* Test program for elfutils::dwarf_edit basics.
+ 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.
+
+ 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>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <error.h>
+#include <fcntl.h>
+#include <clocale>
+#include <cstdio>
+#include <libintl.h>
+#include <ostream>
+#include <iomanip>
+
+#include "c++/dwarf_edit"
+
+using namespace elfutils;
+using namespace std;
+
+#include "print-die.hh"
+
+
+int
+main (int argc, char **argv)
+{
+ unsigned int depth;
+ print_die_main (argc, argv, depth);
+
+ dwarf_edit f;
+
+ dwarf_edit::compile_unit &cu = f.add_unit ();
+
+ cu.attributes ()[DW_AT_name].source_file () = "source-file.c";
+
+ dwarf_edit::debug_info_entry &ent = cu.add_entry (DW_TAG_subprogram);
+
+ ent.attributes ()[DW_AT_name].identifier () = "foo";
+
+ ent.attributes ()[DW_AT_description] = ent.attributes ()[DW_AT_name];
+
+ print_file ("consed", f, depth);
+
+ return 0;
+}
diff --git a/tests/print-die.hh b/tests/print-die.hh
new file mode 100644
index 00000000..c4ff8a25
--- /dev/null
+++ b/tests/print-die.hh
@@ -0,0 +1,75 @@
+
+static void
+print_die_main (int &argc, char **&argv, unsigned int &depth)
+{
+ /* Set locale. */
+ (void) setlocale (LC_ALL, "");
+
+ /* Make sure the message catalog can be found. */
+ (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
+
+ /* Initialize the message catalog. */
+ (void) textdomain (PACKAGE_TARNAME);
+
+ cout << hex << setiosflags (ios::showbase);
+
+ depth = 0;
+ if (argc > 1 && sscanf (argv[1], "--depth=%u", &depth) == 1)
+ {
+ --argc;
+ ++argv;
+ }
+}
+
+template<typename file>
+static void
+print_die (const typename file::debug_info_entry &die,
+ unsigned int indent, unsigned int limit)
+{
+ string prefix (indent, ' ');
+ const string tag = dwarf::tags::name (die.tag ());
+
+ cout << prefix << "<" << tag << " offset=[" << die.offset () << "]";
+
+ for (typename file::debug_info_entry::attributes_type::const_iterator i
+ = die.attributes ().begin (); i != die.attributes ().end (); ++i)
+ cout << " " << to_string (*i);
+
+ if (die.has_children ())
+ {
+ if (limit != 0 && indent >= limit)
+ {
+ cout << ">...\n";
+ return;
+ }
+
+ cout << ">\n";
+
+ for (typename file::debug_info_entry::children_type::const_iterator i
+ = die.children ().begin (); i != die.children ().end (); ++i)
+ print_die<file> (*i, indent + 1, limit);
+
+ cout << prefix << "</" << tag << ">\n";
+ }
+ else
+ cout << "/>\n";
+}
+
+template<typename file>
+static void
+print_cu (const typename file::compile_unit &cu, const unsigned int limit)
+{
+ print_die<file> (static_cast<const typename file::debug_info_entry &> (cu),
+ 1, limit);
+}
+
+template<typename file>
+static void
+print_file (const char *name, const file &dw, const unsigned int limit)
+{
+ cout << name << ":\n";
+
+ for (typename file::compile_units::const_iterator i
+ = dw.compile_units ().begin (); i != dw.compile_units ().end (); ++i)
+ print_cu<file> (*i, limit);
+}