mirror of
git://sourceware.org/git/libabigail.git
synced 2025-02-15 13:07:00 +00:00
Parse type-decl and namespace-decl elements
* configure.ac: Add libxml2 dependencies. * src/abg-corpus.{h,cc}: New files. * src/abg-hash.{h,cc}: Likewise. * src/abg-libxml-utils.{h,cc}: Likewise. * src/abg-reader.{h,cc}: Likewise. * src/abg-serialize.{h,cc}: Likewise. * src/abg-writer.h: Likewise. * src/Makefile.am: Build the new files above. * src/abg-ir.h (class location): Add public accessors for the value, and a truth operator. Make the methods be inline. (class decl_base): Renamed decl into this. Renamed what_decl_kind into what_kind. Renamed get_context into get_scope. Add virtual destructor, accessors for location and name. (class {scope_decl, type_base, type_decl} ): Add virtual dtor. Re-style. (struct {decl_base_hash, type_decl_hash}): New hashing functors. (class {scope_type_decl, namespace_decl}): Add virtual dtor. * src/abg-ir.cc (location::*): Remove location definitions. There are now inline in the header. (class decl_base): Renamed decl into this. Remove most of the definitions from here as their are now inline in the header. (scope_decl::~scope_decl, type_base::~type_base) (type_decl::~type_decl, scope_type_decl::~scope_type_decl): New definitions.
This commit is contained in:
parent
e20615bf9f
commit
8e225db39a
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
configure
|
||||
aclocal.m4
|
||||
*Makefile.in
|
||||
build/
|
||||
autom4te.cache/
|
13
configure.ac
13
configure.ac
@ -14,6 +14,12 @@ AM_MAINTAINER_MODE([enable])
|
||||
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
dnl *************************************************
|
||||
dnl Here is the list of versions of the dependencies
|
||||
dnl *************************************************
|
||||
|
||||
LIBXML2_VERSION=2.6.22
|
||||
|
||||
AC_PROG_CXX
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
AC_PROG_INSTALL
|
||||
@ -24,6 +30,13 @@ LT_INIT
|
||||
AC_LANG([C++])
|
||||
AC_LANG_COMPILER_REQUIRE
|
||||
|
||||
PKG_CHECK_MODULES(ABIGAIL_DEPS, [libxml-2.0 >= $LIBXML2_VERSION])
|
||||
ABIGAIL_CFLAGS="$ABIGAIL_DEPS_CFLAGS"
|
||||
ABIGAIL_LIBS="$ABIGAIL_DEPS_LIBS"
|
||||
|
||||
AC_SUBST(ABIGAIL_CFLAGS)
|
||||
AC_SUBST(ABIGAIL_LIBS)
|
||||
|
||||
AC_CONFIG_FILES([Makefile
|
||||
src/Makefile])
|
||||
|
||||
|
@ -3,13 +3,24 @@ libabigaildir=$(libdir)/
|
||||
|
||||
h=$(abs_srcdir)
|
||||
|
||||
headers = \
|
||||
$(h)/abg-ir.h
|
||||
headers = \
|
||||
$(h)/abg-ir.h \
|
||||
$(h)/abg-reader.h \
|
||||
$(h)/abg-corpus.h \
|
||||
$(h)/abg-libxml-utils.h \
|
||||
$(h)/abg-hash.h \
|
||||
$(h)/abg-writer.h
|
||||
|
||||
libabigail_la_SOURCES = $(headers) \
|
||||
$(h)/abg-ir.cc
|
||||
libabigail_la_SOURCES = $(headers) \
|
||||
$(h)/abg-ir.cc \
|
||||
$(h)/abg-reader.cc \
|
||||
$(h)/abg-corpus.cc \
|
||||
$(h)/abg-libxml-utils.cc \
|
||||
$(h)/abg-hash.cc
|
||||
|
||||
libabigail_la_LDFLAGS=@ABIGAIL_LIBS@ -Wl,--as-needed
|
||||
|
||||
publicheaders_DATA=$(headers)
|
||||
publicheadersdir=$(includedir)/libabigail
|
||||
|
||||
AM_CPPFLAGS=
|
||||
AM_CPPFLAGS=@ABIGAIL_CFLAGS@ -Wall
|
||||
|
37
src/abg-corpus.cc
Normal file
37
src/abg-corpus.cc
Normal file
@ -0,0 +1,37 @@
|
||||
// -*- mode: c++ -*-
|
||||
|
||||
#include "abg-corpus.h"
|
||||
|
||||
namespace abigail
|
||||
{
|
||||
|
||||
abi_corpus::abi_corpus(const std::string& name)
|
||||
:m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
abi_corpus::add(const shared_ptr<decl_base> declaration)
|
||||
{
|
||||
m_members;
|
||||
}
|
||||
|
||||
const std::list<shared_ptr<decl_base> >&
|
||||
abi_corpus::get_decls() const
|
||||
{
|
||||
return m_members;
|
||||
}
|
||||
|
||||
const location_manager&
|
||||
abi_corpus::get_loc_mgr() const
|
||||
{
|
||||
return m_loc_mgr;
|
||||
}
|
||||
|
||||
location_manager&
|
||||
abi_corpus::get_loc_mgr()
|
||||
{
|
||||
return m_loc_mgr;
|
||||
}
|
||||
|
||||
}//end namespace abigail
|
35
src/abg-corpus.h
Normal file
35
src/abg-corpus.h
Normal file
@ -0,0 +1,35 @@
|
||||
// -*- mode: c++ -*-
|
||||
|
||||
#ifndef __ABG_CORPUS_H__
|
||||
#define __ABG_CORPUS_H__
|
||||
|
||||
#include <tr1/memory>
|
||||
#include "abg-ir.h"
|
||||
|
||||
using std::tr1::shared_ptr;
|
||||
|
||||
namespace abigail
|
||||
{
|
||||
/// This is the abstraction of the set of relevant artefacts (types,
|
||||
/// variable declarations, functions, templates, etc) bundled together
|
||||
/// to represent an Application Binary Interface.
|
||||
class abi_corpus
|
||||
{
|
||||
abi_corpus();
|
||||
|
||||
public:
|
||||
abi_corpus(const std::string& name);
|
||||
|
||||
void add(const shared_ptr<decl_base> declaration);
|
||||
const std::list<shared_ptr<decl_base> >& get_decls() const;
|
||||
location_manager& get_loc_mgr();
|
||||
const location_manager& get_loc_mgr() const;
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
location_manager m_loc_mgr;
|
||||
std::list<shared_ptr<decl_base> > m_members;
|
||||
};
|
||||
|
||||
}//end namespace abigail
|
||||
#endif //__ABG_CORPUS_H__
|
37
src/abg-hash.cc
Normal file
37
src/abg-hash.cc
Normal file
@ -0,0 +1,37 @@
|
||||
// -*- mode: C++ -*-
|
||||
|
||||
#include "abg-hash.h"
|
||||
|
||||
namespace abigail
|
||||
{
|
||||
|
||||
namespace hashing
|
||||
{
|
||||
|
||||
// Mix 3 32 bits values reversibly. Borrowed from hashtab.c in gcc tree.
|
||||
#define abigail_hash_mix(a, b, c) \
|
||||
{ \
|
||||
a -= b; a -= c; a ^= (c>>13); \
|
||||
b -= c; b -= a; b ^= (a<< 8); \
|
||||
c -= a; c -= b; c ^= ((b&0xffffffff)>>13); \
|
||||
a -= b; a -= c; a ^= ((c&0xffffffff)>>12); \
|
||||
b -= c; b -= a; b = (b ^ (a<<16)) & 0xffffffff; \
|
||||
c -= a; c -= b; c = (c ^ (b>> 5)) & 0xffffffff; \
|
||||
a -= b; a -= c; a = (a ^ (c>> 3)) & 0xffffffff; \
|
||||
b -= c; b -= a; b = (b ^ (a<<10)) & 0xffffffff; \
|
||||
c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \
|
||||
}
|
||||
|
||||
/// Produce good hash value combining val1 and val2. This is copied
|
||||
/// from tree.c in GCC.
|
||||
size_t
|
||||
combine_hashes(size_t val1, size_t val2)
|
||||
{
|
||||
/* the golden ratio; an arbitrary value. */
|
||||
size_t a = 0x9e3779b9;
|
||||
abigail_hash_mix(a, val1, val2);
|
||||
return val2;
|
||||
}
|
||||
|
||||
}//end namespace hash
|
||||
}//end namespace abigail
|
16
src/abg-hash.h
Normal file
16
src/abg-hash.h
Normal file
@ -0,0 +1,16 @@
|
||||
// -*- mode: C++ -*-
|
||||
|
||||
#ifndef __ABG_HASH_H__
|
||||
#define __ABG_HASH_H__
|
||||
|
||||
#include <cstddef>
|
||||
namespace abigail
|
||||
{
|
||||
namespace hashing
|
||||
{
|
||||
size_t combine_hashes(size_t, size_t);
|
||||
|
||||
}//end namespace hash
|
||||
}//end namespace abigail
|
||||
|
||||
#endif //__ABG_HASH_H__
|
109
src/abg-ir.cc
109
src/abg-ir.cc
@ -2,24 +2,16 @@
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "abg-ir.h"
|
||||
#include "abg-hash.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace abigail
|
||||
{
|
||||
|
||||
location::location()
|
||||
: m_value(0)
|
||||
{
|
||||
}
|
||||
|
||||
location::location(unsigned value)
|
||||
: m_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
/// \brief the location of a token represented in its simplest form.
|
||||
/// Instances of this type are to be stored in a sorted vector, so the
|
||||
/// type must have proper relational operators.
|
||||
@ -144,39 +136,43 @@ location_manager::expand_location(const location location,
|
||||
}
|
||||
|
||||
// <Decl definition>
|
||||
decl::decl()
|
||||
decl_base::decl_base()
|
||||
: m_kind(KIND_DECL)
|
||||
{
|
||||
}
|
||||
|
||||
decl::decl(const std::string& name,
|
||||
const shared_ptr<scope_decl> context,
|
||||
location locus)
|
||||
decl_base::decl_base(const std::string& name,
|
||||
shared_ptr<scope_decl> context,
|
||||
location locus)
|
||||
:m_kind(KIND_DECL),
|
||||
m_location(locus),
|
||||
m_name(name),
|
||||
m_context(context)
|
||||
{
|
||||
if (m_context)
|
||||
m_context->add_member_decl(shared_ptr<decl_base>(this));
|
||||
}
|
||||
|
||||
decl::decl(kind what_kind,
|
||||
const std::string& name,
|
||||
const shared_ptr<scope_decl> context,
|
||||
location locus)
|
||||
decl_base::decl_base(kind what_kind,
|
||||
const std::string& name,
|
||||
const shared_ptr<scope_decl> context,
|
||||
location locus)
|
||||
: m_kind(what_kind),
|
||||
m_location(locus),
|
||||
m_name(name),
|
||||
m_context(context)
|
||||
{
|
||||
if (m_context)
|
||||
m_context->add_member_decl(shared_ptr<decl_base>(this));
|
||||
}
|
||||
|
||||
decl::decl(location l)
|
||||
decl_base::decl_base(location l)
|
||||
:m_kind(KIND_DECL),
|
||||
m_location(l)
|
||||
{
|
||||
}
|
||||
|
||||
decl::decl(const decl& d)
|
||||
decl_base::decl_base(const decl_base& d)
|
||||
{
|
||||
m_kind = d.m_kind;
|
||||
m_location = d.m_location;
|
||||
@ -184,28 +180,14 @@ decl::decl(const decl& d)
|
||||
m_context = d.m_context;
|
||||
}
|
||||
|
||||
enum decl::kind
|
||||
decl::what_decl_kind () const
|
||||
enum decl_base::kind
|
||||
decl_base::what_kind () const
|
||||
{
|
||||
return m_kind;
|
||||
}
|
||||
|
||||
location
|
||||
decl::get_location() const
|
||||
decl_base::~decl_base()
|
||||
{
|
||||
return m_location;
|
||||
}
|
||||
|
||||
void
|
||||
decl::set_location(const location& loc)
|
||||
{
|
||||
m_location = loc;
|
||||
}
|
||||
|
||||
shared_ptr<scope_decl>
|
||||
decl::get_context() const
|
||||
{
|
||||
return m_context;
|
||||
}
|
||||
|
||||
// </Decl definition>
|
||||
@ -214,7 +196,7 @@ decl::get_context() const
|
||||
scope_decl::scope_decl(const std::string& name,
|
||||
const shared_ptr<scope_decl> context,
|
||||
location locus)
|
||||
: decl(KIND_SCOPE_DECL, name, context, locus)
|
||||
: decl_base(KIND_SCOPE_DECL, name, context, locus)
|
||||
{
|
||||
}
|
||||
|
||||
@ -222,26 +204,31 @@ scope_decl::scope_decl(kind akind,
|
||||
const std::string& name,
|
||||
const shared_ptr<scope_decl> context,
|
||||
location locus)
|
||||
: decl(akind, name, context, locus)
|
||||
: decl_base(akind, name, context, locus)
|
||||
{
|
||||
}
|
||||
|
||||
scope_decl::scope_decl(location l)
|
||||
: decl(KIND_SCOPE_DECL, "", shared_ptr<scope_decl>(), l)
|
||||
: decl_base(KIND_SCOPE_DECL, "", shared_ptr<scope_decl>(), l)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
scope_decl::add_member_decl(const shared_ptr<decl> member)
|
||||
scope_decl::add_member_decl(const shared_ptr<decl_base> member)
|
||||
{
|
||||
m_members.push_back(member);
|
||||
}
|
||||
|
||||
const std::list<shared_ptr<decl> >&
|
||||
const std::list<shared_ptr<decl_base> >&
|
||||
scope_decl::get_member_decls() const
|
||||
{
|
||||
return m_members;
|
||||
}
|
||||
|
||||
scope_decl::~scope_decl()
|
||||
{
|
||||
}
|
||||
|
||||
// </scope_decl definition>
|
||||
|
||||
// <type_base definitions>
|
||||
@ -275,31 +262,39 @@ type_base::get_alignment_in_bits() const
|
||||
return m_alignment_in_bits;
|
||||
}
|
||||
|
||||
type_base::~type_base()
|
||||
{
|
||||
}
|
||||
|
||||
// </type_base definitions>
|
||||
|
||||
//<type_decl definitions>
|
||||
|
||||
type_decl::type_decl(const std::string& name,
|
||||
size_t size_in_bits,
|
||||
size_t alignment_in_bits,
|
||||
const shared_ptr<scope_decl> context,
|
||||
location locus)
|
||||
: decl(KIND_TYPE_DECL, name, context, locus),
|
||||
type_decl::type_decl(const std::string& name,
|
||||
size_t size_in_bits,
|
||||
size_t alignment_in_bits,
|
||||
shared_ptr<scope_decl> context,
|
||||
location locus)
|
||||
: decl_base(KIND_TYPE_DECL, name, context, locus),
|
||||
type_base(size_in_bits, alignment_in_bits)
|
||||
{
|
||||
}
|
||||
|
||||
type_decl::type_decl(kind akind,
|
||||
const std::string& name,
|
||||
size_t size_in_bits,
|
||||
size_t alignment_in_bits,
|
||||
const shared_ptr<scope_decl> context,
|
||||
location locus)
|
||||
: decl(akind, name, context, locus),
|
||||
type_decl::type_decl(kind akind,
|
||||
const std::string& name,
|
||||
size_t size_in_bits,
|
||||
size_t alignment_in_bits,
|
||||
shared_ptr<scope_decl> context,
|
||||
location locus)
|
||||
: decl_base(akind, name, context, locus),
|
||||
type_base(size_in_bits, alignment_in_bits)
|
||||
{
|
||||
}
|
||||
|
||||
type_decl::~type_decl()
|
||||
{
|
||||
}
|
||||
|
||||
//</type_decl definitions>
|
||||
|
||||
// <scope_type_decl definitions>
|
||||
@ -325,6 +320,10 @@ scope_type_decl::scope_type_decl(kind akind,
|
||||
{
|
||||
}
|
||||
|
||||
scope_type_decl::~scope_type_decl()
|
||||
{
|
||||
}
|
||||
|
||||
// </scope_type_decl definitions>
|
||||
|
||||
// <namespace_decl>
|
||||
|
199
src/abg-ir.h
199
src/abg-ir.h
@ -1,11 +1,20 @@
|
||||
// -*- mode: C++ -*-
|
||||
|
||||
#ifndef __ABL_IR_H__
|
||||
#define __ABL_IR_H__
|
||||
|
||||
#include <cstddef>
|
||||
#include <tr1/memory>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <tr1/functional>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "abg-hash.h"
|
||||
|
||||
using std::tr1::shared_ptr;
|
||||
using std::tr1::hash;
|
||||
using std::string;
|
||||
|
||||
// Our real stuff
|
||||
namespace abigail
|
||||
@ -18,10 +27,29 @@ namespace abigail
|
||||
/// That table is managed by the location_manager type.
|
||||
class location
|
||||
{
|
||||
location (unsigned);
|
||||
location (unsigned v)
|
||||
: m_value(v)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
location();
|
||||
location()
|
||||
: m_value(0)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned
|
||||
get_value() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return !!m_value;
|
||||
}
|
||||
|
||||
friend class location_manager;
|
||||
|
||||
private:
|
||||
@ -40,23 +68,28 @@ class location_manager
|
||||
public:
|
||||
|
||||
location_manager();
|
||||
location create_new_location(const std::string& file,
|
||||
size_t line,
|
||||
size_t column);
|
||||
void expand_location(const location location,
|
||||
std::string& path,
|
||||
unsigned& line,
|
||||
unsigned& column);
|
||||
|
||||
location
|
||||
create_new_location(const std::string& file,
|
||||
size_t line,
|
||||
size_t column);
|
||||
|
||||
void
|
||||
expand_location(const location location,
|
||||
std::string& path,
|
||||
unsigned& line,
|
||||
unsigned& column);
|
||||
};
|
||||
|
||||
class scope_decl;
|
||||
|
||||
/// \brief The base type of all declarations.
|
||||
class decl
|
||||
class decl_base
|
||||
{
|
||||
decl();
|
||||
decl_base();
|
||||
|
||||
public:
|
||||
|
||||
protected:
|
||||
enum kind
|
||||
{
|
||||
KIND_DECL,
|
||||
@ -66,24 +99,54 @@ protected:
|
||||
KIND_NAMESPACE_DECL
|
||||
};
|
||||
|
||||
enum kind what_decl_kind () const;
|
||||
enum kind
|
||||
what_kind () const;
|
||||
|
||||
decl(kind what_kind,
|
||||
const std::string& name,
|
||||
const shared_ptr<scope_decl> context,
|
||||
location locus);
|
||||
protected:
|
||||
|
||||
decl_base(kind what_kind,
|
||||
const std::string& name,
|
||||
shared_ptr<scope_decl> context,
|
||||
location locus);
|
||||
|
||||
public:
|
||||
decl(const std::string& name,
|
||||
const shared_ptr<scope_decl> context,
|
||||
location locus);
|
||||
decl(location);
|
||||
decl(const decl&);
|
||||
|
||||
location get_location() const;
|
||||
void set_location(const location&);
|
||||
decl_base(const std::string& name,
|
||||
shared_ptr<scope_decl> context,
|
||||
location locus);
|
||||
decl_base(location);
|
||||
decl_base(const decl_base&);
|
||||
virtual ~decl_base();
|
||||
|
||||
shared_ptr<scope_decl> get_context() const;
|
||||
location
|
||||
get_location() const
|
||||
{
|
||||
return m_location;
|
||||
}
|
||||
|
||||
void
|
||||
set_location(const location&l)
|
||||
{
|
||||
m_location = l;
|
||||
}
|
||||
|
||||
const string&
|
||||
get_name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void
|
||||
set_name(const string& n)
|
||||
{
|
||||
m_name = n;
|
||||
}
|
||||
|
||||
shared_ptr<scope_decl>
|
||||
get_scope() const
|
||||
{
|
||||
return m_context;
|
||||
}
|
||||
|
||||
private:
|
||||
kind m_kind;
|
||||
@ -93,7 +156,7 @@ private:
|
||||
};
|
||||
|
||||
/// \brief A declaration that introduces a scope.
|
||||
class scope_decl : public decl
|
||||
class scope_decl : public decl_base
|
||||
{
|
||||
scope_decl();
|
||||
|
||||
@ -109,13 +172,38 @@ public:
|
||||
location locus);
|
||||
scope_decl(location);
|
||||
|
||||
void add_member_decl(const shared_ptr<decl>);
|
||||
const std::list<shared_ptr<decl> >& get_member_decls() const;
|
||||
void
|
||||
add_member_decl(const shared_ptr<decl_base>);
|
||||
|
||||
const std::list<shared_ptr<decl_base> >&
|
||||
get_member_decls() const;
|
||||
|
||||
virtual ~scope_decl();
|
||||
|
||||
private:
|
||||
std::list<shared_ptr<decl> > m_members;
|
||||
std::list<shared_ptr<decl_base> > m_members;
|
||||
};
|
||||
|
||||
/// \brief Facility to hash instances of decl_base.
|
||||
struct decl_base_hash
|
||||
{
|
||||
size_t
|
||||
operator() (const decl_base& d)
|
||||
{
|
||||
hash<string> str_hash;
|
||||
hash<unsigned> unsigned_hash;
|
||||
|
||||
size_t v = str_hash(typeid(d).name());
|
||||
if (!d.get_name().empty())
|
||||
v = hashing::combine_hashes(v, str_hash(d.get_name()));
|
||||
if (d.get_location())
|
||||
v = hashing::combine_hashes(v, unsigned_hash(d.get_location()));
|
||||
|
||||
v = hashing::combine_hashes(v, this->operator()(*d.get_scope()));
|
||||
return v;
|
||||
}
|
||||
};//end struct decl_base_hash
|
||||
|
||||
/// An abstraction helper for type declarations
|
||||
class type_base
|
||||
{
|
||||
@ -125,12 +213,19 @@ class type_base
|
||||
public:
|
||||
|
||||
type_base(size_t s, size_t a);
|
||||
virtual ~type_base();
|
||||
|
||||
void set_size_in_bits(size_t);
|
||||
size_t get_size_in_bits() const;
|
||||
void
|
||||
set_size_in_bits(size_t);
|
||||
|
||||
void set_alignment_in_bits(size_t);
|
||||
size_t get_alignment_in_bits() const;
|
||||
size_t
|
||||
get_size_in_bits() const;
|
||||
|
||||
void
|
||||
set_alignment_in_bits(size_t);
|
||||
|
||||
size_t
|
||||
get_alignment_in_bits() const;
|
||||
|
||||
private:
|
||||
|
||||
@ -139,19 +234,19 @@ private:
|
||||
};
|
||||
|
||||
/// A basic type declaration that introduces no scope.
|
||||
class type_decl : public decl, public type_base
|
||||
class type_decl : public decl_base, public type_base
|
||||
{
|
||||
// Forbidden.
|
||||
type_decl();
|
||||
|
||||
protected:
|
||||
|
||||
type_decl(kind akind,
|
||||
const std::string& name,
|
||||
size_t size_in_bits,
|
||||
size_t alignment_in_bits,
|
||||
const shared_ptr<scope_decl> context,
|
||||
location locus);
|
||||
type_decl(kind akind,
|
||||
const std::string& name,
|
||||
size_t size_in_bits,
|
||||
size_t alignment_in_bits,
|
||||
shared_ptr<scope_decl> context,
|
||||
location locus);
|
||||
|
||||
public:
|
||||
|
||||
@ -160,8 +255,28 @@ public:
|
||||
size_t alignment_in_bits,
|
||||
const shared_ptr<scope_decl> context,
|
||||
location locus);
|
||||
|
||||
virtual ~type_decl();
|
||||
|
||||
};
|
||||
|
||||
/// Facility to hash instance of type_decl
|
||||
struct type_decl_hash
|
||||
{
|
||||
size_t
|
||||
operator()(const type_decl& t)
|
||||
{
|
||||
decl_base_hash decl_hash;
|
||||
hash<size_t> size_t_hash;
|
||||
|
||||
size_t v = decl_hash(static_cast<type_decl>(t));
|
||||
v = hashing::combine_hashes(v, size_t_hash(t.get_size_in_bits()));
|
||||
v = hashing::combine_hashes(v, size_t_hash(t.get_alignment_in_bits()));
|
||||
|
||||
return v;
|
||||
}
|
||||
};//end struct type_decl_hash
|
||||
|
||||
/// A type that introduces a scope.
|
||||
class scope_type_decl : public scope_decl, public type_base
|
||||
{
|
||||
@ -182,6 +297,8 @@ public:
|
||||
size_t alignment_in_bits,
|
||||
const shared_ptr<scope_decl> context,
|
||||
location locus);
|
||||
|
||||
virtual ~scope_type_decl();
|
||||
};
|
||||
|
||||
class namespace_decl : public scope_decl
|
||||
@ -191,6 +308,8 @@ public:
|
||||
namespace_decl(const std::string& name,
|
||||
const shared_ptr<namespace_decl> context,
|
||||
location locus);
|
||||
|
||||
virtual ~namespace_decl();
|
||||
};
|
||||
|
||||
} // end namespace abigail
|
||||
|
41
src/abg-libxml-utils.cc
Normal file
41
src/abg-libxml-utils.cc
Normal file
@ -0,0 +1,41 @@
|
||||
// -*- mode: C++ -*-
|
||||
|
||||
#include <string>
|
||||
#include "abg-libxml-utils.h"
|
||||
|
||||
namespace abigail
|
||||
{
|
||||
namespace xml
|
||||
{
|
||||
/// Instanciate an xmlTextReader, wrap it into a smart pointer and
|
||||
/// return it.
|
||||
///
|
||||
/// \param path the path to the file to be parsed by the returned
|
||||
/// instance of xmlTextReader.
|
||||
reader_sptr
|
||||
new_reader_from_file(const std::string& path)
|
||||
{
|
||||
reader_sptr p =
|
||||
build_sptr(xmlNewTextReaderFilename (path.c_str()));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/// Build and return a shared_ptr for a pointer to xmlTextReader
|
||||
template<>
|
||||
shared_ptr<xmlTextReader>
|
||||
build_sptr<xmlTextReader>(xmlTextReader *p)
|
||||
{
|
||||
return shared_ptr<xmlTextReader>(p, textReaderDeleter());
|
||||
}
|
||||
|
||||
/// Build and return a shared_ptr for a pointer to xmlChar
|
||||
template<>
|
||||
shared_ptr<xmlChar>
|
||||
build_sptr<xmlChar>(xmlChar *p)
|
||||
{
|
||||
return shared_ptr<xmlChar>(p, charDeleter());
|
||||
}
|
||||
|
||||
}//end namespace xml
|
||||
}//end namespace abigail
|
75
src/abg-libxml-utils.h
Normal file
75
src/abg-libxml-utils.h
Normal file
@ -0,0 +1,75 @@
|
||||
// -*- mode: C++ -*-
|
||||
|
||||
#include <tr1/memory>
|
||||
#include <libxml/xmlreader.h>
|
||||
|
||||
using std::tr1::shared_ptr;
|
||||
|
||||
namespace abigail
|
||||
{
|
||||
namespace xml
|
||||
{
|
||||
|
||||
/// This functor is used to instantiate a shared_ptr for the
|
||||
/// xmlTextReader.
|
||||
struct textReaderDeleter
|
||||
{
|
||||
void
|
||||
operator()(xmlTextReaderPtr reader)
|
||||
{
|
||||
xmlFreeTextReader(reader);
|
||||
}
|
||||
};//end struct textReaderDeleter
|
||||
|
||||
|
||||
typedef shared_ptr<xmlTextReader> reader_sptr;
|
||||
|
||||
/// This functor is used to instantiate a shared_ptr for xmlChar
|
||||
struct charDeleter
|
||||
{
|
||||
void
|
||||
operator()(xmlChar* str)
|
||||
{
|
||||
xmlFree(str);
|
||||
}
|
||||
};//end struct xmlCharDeleter
|
||||
typedef shared_ptr<xmlChar> xml_char_sptr;
|
||||
|
||||
reader_sptr new_reader_from_file(const std::string& path);
|
||||
xml_char_sptr build_xml_char_sptr(xmlChar *);
|
||||
|
||||
template<class T> shared_ptr<T> build_sptr(T* p);
|
||||
|
||||
/// Specialization of build_sptr for xmlTextReader
|
||||
template<>
|
||||
shared_ptr<xmlTextReader>
|
||||
build_sptr<xmlTextReader>(xmlTextReader *p);
|
||||
|
||||
/// Specialization of build_str for xmlChar.
|
||||
template<>
|
||||
shared_ptr<xmlChar>
|
||||
build_sptr<xmlChar>(xmlChar *p);
|
||||
|
||||
/// Get the name of the current element node the reader is pointing
|
||||
/// to. Note that this macro returns an instance of
|
||||
/// shared_ptr<xmlChar> so that the caller doesn't have to worry about
|
||||
/// managing memory itself. Also note that the reader is a
|
||||
/// shared_ptr<xmlTextReader>
|
||||
#define XML_READER_GET_NODE_NAME(reader) \
|
||||
xml::build_sptr(xmlTextReaderName(reader.get()))
|
||||
|
||||
/// Get the type of the current node of the shared_ptr<xmlTextReader>
|
||||
/// passed in argument.
|
||||
#define XML_READER_GET_NODE_TYPE(reader) \
|
||||
static_cast<xmlReaderTypes> (xmlTextReaderNodeType(reader.get()))
|
||||
|
||||
/// Get the value attribute name of the current node of reader which is an
|
||||
/// instance of shared_ptr<xmlTextReader>.
|
||||
#define XML_READER_GET_ATTRIBUTE(reader, name) \
|
||||
xml::build_sptr(xmlTextReaderGetAttribute(reader.get(), BAD_CAST(name)))
|
||||
|
||||
#define CHAR_STR(xml_char_str) \
|
||||
reinterpret_cast<char*>(xml_char_str.get())
|
||||
|
||||
}//end namespace xml
|
||||
}//end namespace abigail
|
379
src/abg-reader.cc
Normal file
379
src/abg-reader.cc
Normal file
@ -0,0 +1,379 @@
|
||||
// -*- mode: C++ -*-
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <tr1/unordered_map>
|
||||
#include <stack>
|
||||
#include <libxml/xmlstring.h>
|
||||
#include <libxml/xmlreader.h>
|
||||
#include "abg-reader.h"
|
||||
#include "abg-libxml-utils.h"
|
||||
|
||||
using std::string;
|
||||
using std::stack;
|
||||
using std::tr1::unordered_map;
|
||||
using std::tr1::dynamic_pointer_cast;
|
||||
|
||||
namespace abigail
|
||||
{
|
||||
namespace reader
|
||||
{
|
||||
|
||||
/// This abstracts the context in which the current ABI
|
||||
/// instrumentation dump is being de-serialized. It carries useful
|
||||
/// information needed during the de-serialization, but that does not
|
||||
/// make sense to be stored in the final resulting in-memory
|
||||
/// representation of ABI Corpus.
|
||||
class read_context
|
||||
{
|
||||
read_context();
|
||||
|
||||
public:
|
||||
|
||||
typedef unordered_map<string,
|
||||
shared_ptr<type_base> >::const_iterator
|
||||
const_types_map_it;
|
||||
|
||||
read_context(xml::reader_sptr reader)
|
||||
: m_depth(0),
|
||||
m_reader(reader)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
get_depth() const
|
||||
{
|
||||
return m_depth;
|
||||
}
|
||||
|
||||
void
|
||||
set_depth(int d)
|
||||
{
|
||||
m_depth = d;
|
||||
}
|
||||
|
||||
xml::reader_sptr
|
||||
get_reader() const
|
||||
{
|
||||
return m_reader;
|
||||
}
|
||||
|
||||
shared_ptr<type_base>
|
||||
get_type_decl(const string& id) const
|
||||
{
|
||||
const_types_map_it i = m_types_map.find(id);
|
||||
if (i == m_types_map.end())
|
||||
return shared_ptr<type_base>();
|
||||
return shared_ptr<type_base>(i->second);
|
||||
}
|
||||
|
||||
shared_ptr<scope_decl>
|
||||
get_cur_scope() const
|
||||
{
|
||||
return m_cur_scope;
|
||||
}
|
||||
|
||||
void
|
||||
set_cur_scope(shared_ptr<scope_decl> s)
|
||||
{
|
||||
m_cur_scope = s;
|
||||
}
|
||||
|
||||
shared_ptr<decl_base>
|
||||
get_cur_decl() const
|
||||
{
|
||||
return m_decls_stack.top();
|
||||
}
|
||||
|
||||
void
|
||||
push_decl(shared_ptr<decl_base> d)
|
||||
{
|
||||
m_decls_stack.push(d);
|
||||
}
|
||||
|
||||
shared_ptr<decl_base>
|
||||
pop_decl()
|
||||
{
|
||||
shared_ptr<decl_base> t = get_cur_decl();
|
||||
m_decls_stack.pop();
|
||||
return t;
|
||||
}
|
||||
|
||||
bool
|
||||
add_type_decl(const string& id,
|
||||
shared_ptr<type_base> type)
|
||||
{
|
||||
const_types_map_it i = m_types_map.find(id);
|
||||
if (i != m_types_map.end())
|
||||
return false;
|
||||
|
||||
m_types_map[id] = type;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
// The depth of the current node in the xml tree.
|
||||
int m_depth;
|
||||
unordered_map<string, shared_ptr<type_base> > m_types_map;
|
||||
xml::reader_sptr m_reader;
|
||||
stack<shared_ptr<decl_base> > m_decls_stack;
|
||||
shared_ptr<scope_decl> m_cur_scope;
|
||||
};//end class read_context
|
||||
|
||||
static void update_read_context(read_context&);
|
||||
static int advance_cursor(read_context&);
|
||||
static bool read_input(read_context&, abi_corpus&);
|
||||
static bool read_location(read_context&, abi_corpus& , location&);
|
||||
static bool handle_element(read_context&, abi_corpus&);
|
||||
static bool handle_type_decl(read_context&, abi_corpus&);
|
||||
static bool handle_namespace_decl(read_context&, abi_corpus&);
|
||||
|
||||
bool
|
||||
read_file(string& file_path,
|
||||
abi_corpus& corpus)
|
||||
{
|
||||
read_context read_ctxt(xml::new_reader_from_file(file_path));
|
||||
|
||||
return read_input(read_ctxt, corpus);
|
||||
}
|
||||
|
||||
// Updates the instance of read_context. This function needs to be
|
||||
// called after each call to xmlTextReaderReader.
|
||||
static void
|
||||
update_read_context(read_context& ctxt)
|
||||
{
|
||||
xml::reader_sptr reader = ctxt.get_reader();
|
||||
|
||||
// Update the depth of the current reader cursor in the reader
|
||||
// context.
|
||||
int depth = xmlTextReaderDepth(reader.get()),
|
||||
ctxt_depth = ctxt.get_depth();
|
||||
|
||||
if (depth > ctxt_depth)
|
||||
{
|
||||
// we went down the tree.
|
||||
shared_ptr<decl_base> cur_decl = ctxt.get_cur_decl();
|
||||
if (dynamic_cast<scope_decl*>(cur_decl.get()))
|
||||
ctxt.set_cur_scope(dynamic_pointer_cast<scope_decl>(cur_decl));
|
||||
}
|
||||
else if (depth < ctxt_depth)
|
||||
{
|
||||
// we went up the tree.
|
||||
for (int nb = ctxt_depth - depth; nb; --nb)
|
||||
ctxt.pop_decl();
|
||||
shared_ptr<decl_base> cur_decl = ctxt.get_cur_decl();
|
||||
if (dynamic_cast<scope_decl*> (cur_decl.get()))
|
||||
ctxt.set_cur_scope(dynamic_pointer_cast<scope_decl>(cur_decl));
|
||||
else
|
||||
ctxt.set_cur_scope(cur_decl->get_scope());
|
||||
}
|
||||
|
||||
ctxt.set_depth(depth);
|
||||
}
|
||||
|
||||
/// Moves the xmlTextReader cursor to the next xml node in the input
|
||||
/// document. Return 1 of the parsing was successful, 0 if no input
|
||||
/// xml token is left, or -1 in case of error.
|
||||
///
|
||||
/// \param ctxt the read context
|
||||
///
|
||||
static int
|
||||
advance_cursor(read_context& ctxt)
|
||||
{
|
||||
xml::reader_sptr reader = ctxt.get_reader();
|
||||
int status = xmlTextReaderRead(reader.get());
|
||||
if (status == 1)
|
||||
update_read_context(ctxt);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/// Parse the input xml document associated to the current context.
|
||||
///
|
||||
/// \param ctxt the current input context
|
||||
///
|
||||
/// \param corpus the result of the parsing.
|
||||
///
|
||||
/// \return true upon successufl parsing, false otherwise.
|
||||
static bool
|
||||
read_input(read_context& ctxt,
|
||||
abi_corpus& corpus)
|
||||
{
|
||||
xml::reader_sptr reader = ctxt.get_reader();
|
||||
if (!reader)
|
||||
return false;
|
||||
|
||||
if (!xmlTextReaderIsValid(reader.get()))
|
||||
return false;
|
||||
|
||||
// The document must start with the abi-instr node.
|
||||
int status = advance_cursor (ctxt);
|
||||
if (status != 1 || !xmlStrEqual (XML_READER_GET_NODE_NAME(reader).get(),
|
||||
BAD_CAST("abi-instr")))
|
||||
return false;
|
||||
|
||||
for (status = advance_cursor(ctxt);
|
||||
status;
|
||||
status = advance_cursor(ctxt))
|
||||
{
|
||||
xmlReaderTypes node_type = XML_READER_GET_NODE_TYPE(reader);
|
||||
|
||||
switch (node_type)
|
||||
{
|
||||
case XML_READER_TYPE_ELEMENT:
|
||||
if (!handle_element(ctxt, corpus))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(status == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// This function is called by #read_input. It handles the current
|
||||
/// xml element node of the reading context. The result of the
|
||||
/// "handling" is to build the representation of the xml node and tied
|
||||
/// it to the corpus.
|
||||
///
|
||||
/// \param ctxt the current parsing context.
|
||||
///
|
||||
/// \param corpus the resulting ABI Corpus.
|
||||
///
|
||||
/// \return true upon successful completion, false otherwise.
|
||||
static bool
|
||||
handle_element(read_context& ctxt,
|
||||
abi_corpus& corpus)
|
||||
{
|
||||
xml::reader_sptr reader = ctxt.get_reader();
|
||||
if (!reader)
|
||||
return false;
|
||||
|
||||
if (xmlStrEqual (XML_READER_GET_NODE_NAME(reader).get(),
|
||||
BAD_CAST("namespace-decl")))
|
||||
return handle_namespace_decl(ctxt, corpus);
|
||||
if (xmlStrEqual (XML_READER_GET_NODE_NAME(reader).get(),
|
||||
BAD_CAST("type-decl")))
|
||||
return handle_type_decl(ctxt, corpus);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Parses location attributes on the current xml element node.
|
||||
///
|
||||
///\param ctxt the current parsing context
|
||||
///
|
||||
///\param loc the resulting location.
|
||||
///
|
||||
/// \return true upon sucessful parsing, false otherwise.
|
||||
static bool
|
||||
read_location(read_context& ctxt, abi_corpus& corpus, location& loc)
|
||||
{
|
||||
xml::reader_sptr r = ctxt.get_reader();
|
||||
xml::xml_char_sptr f = XML_READER_GET_ATTRIBUTE(r, "filepath");
|
||||
if (!f)
|
||||
{
|
||||
loc = location();
|
||||
return true;
|
||||
}
|
||||
|
||||
xml::xml_char_sptr l = XML_READER_GET_ATTRIBUTE(r, "line");
|
||||
xml::xml_char_sptr c = XML_READER_GET_ATTRIBUTE(r, "column");
|
||||
if (!l || !c)
|
||||
return false;
|
||||
|
||||
loc = corpus.get_loc_mgr().create_new_location
|
||||
(reinterpret_cast<char*>(f.get()),
|
||||
atoi(reinterpret_cast<char*>(l.get())),
|
||||
atoi(reinterpret_cast<char*>(c.get())));
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Parses 'type-decl' xml element.
|
||||
///
|
||||
/// \param ctxt the parsing context.
|
||||
///
|
||||
/// \param corpus the ABI corpus the resulting in-memory
|
||||
/// representation is added to.
|
||||
///
|
||||
/// \return true upon successful parsing, false otherwise.
|
||||
static bool
|
||||
handle_type_decl(read_context& ctxt,
|
||||
abi_corpus& corpus)
|
||||
{
|
||||
xml::reader_sptr reader = ctxt.get_reader();
|
||||
if (!reader)
|
||||
return false;
|
||||
|
||||
string name = CHAR_STR(XML_READER_GET_ATTRIBUTE(reader, "name"));
|
||||
string id = CHAR_STR(XML_READER_GET_ATTRIBUTE(reader, "id"));
|
||||
size_t size_in_bits=
|
||||
atoi(CHAR_STR(XML_READER_GET_ATTRIBUTE(reader, "size-in-bits")));
|
||||
size_t alignment_in_bits =
|
||||
atoi(CHAR_STR (XML_READER_GET_ATTRIBUTE(reader, "alignment-in-bits")));
|
||||
location loc;
|
||||
read_location(ctxt, corpus, loc);
|
||||
|
||||
if (ctxt.get_type_decl(id))
|
||||
// Hugh? How come a type which ID is supposed to be unique exist
|
||||
// already? Bail out!
|
||||
return false;
|
||||
|
||||
shared_ptr<decl_base> decl(new type_decl(name, size_in_bits,
|
||||
alignment_in_bits,
|
||||
ctxt.get_cur_scope(),
|
||||
loc));
|
||||
|
||||
// If This decl is at global scope, then it needs to be added to the
|
||||
// corpus. If it's not at global scope, then it's scope is (maybe
|
||||
// indirectely) in the corpus already.
|
||||
if (!decl->get_scope())
|
||||
corpus.add(decl);
|
||||
|
||||
ctxt.push_decl(decl);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Parses 'namespace-decl' xml element.
|
||||
///
|
||||
/// \param ctxt the parsing context.
|
||||
///
|
||||
/// \param corpus the ABI corpus the resulting in-memory
|
||||
/// representation is added to.
|
||||
///
|
||||
/// \return true upon successful parsing, false otherwise.
|
||||
static bool
|
||||
handle_namespace_decl(read_context& ctxt, abi_corpus& corpus)
|
||||
{
|
||||
xml::reader_sptr r = ctxt.get_reader();
|
||||
if (!r)
|
||||
return false;
|
||||
if (ctxt.get_cur_scope()
|
||||
&& !dynamic_cast<namespace_decl*>(ctxt.get_cur_scope().get()))
|
||||
return false;
|
||||
|
||||
string name = CHAR_STR(XML_READER_GET_ATTRIBUTE(r, "name"));
|
||||
location loc;
|
||||
read_location(ctxt, corpus, loc);
|
||||
|
||||
shared_ptr<namespace_decl> scope(dynamic_pointer_cast<namespace_decl>
|
||||
(ctxt.get_cur_scope()));
|
||||
shared_ptr<decl_base> decl(new namespace_decl(name, scope, loc));
|
||||
|
||||
// If This decl is at global scope, then it needs to be added to the
|
||||
// corpus. If it's not at global scope, then it's scope is (maybe
|
||||
// indirectely) in the corpus already.
|
||||
if (!decl->get_scope())
|
||||
corpus.add(decl);
|
||||
|
||||
ctxt.push_decl(decl);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}//end namespace reader
|
||||
}//end namespace abigail
|
17
src/abg-reader.h
Normal file
17
src/abg-reader.h
Normal file
@ -0,0 +1,17 @@
|
||||
// -*- mode: C++ -*-
|
||||
#ifndef __ABG_READER_H__
|
||||
#define __ABG_READER_H__
|
||||
|
||||
#include "abg-corpus.h"
|
||||
|
||||
namespace abigail
|
||||
{
|
||||
namespace reader
|
||||
{
|
||||
bool read_file(std::string& file_path,
|
||||
abi_corpus& abi_corpus);
|
||||
|
||||
}// end namespace reader
|
||||
}// end namespace abigail
|
||||
|
||||
#endif //__ABG_READER_H__
|
0
src/abg-serialize.cc
Normal file
0
src/abg-serialize.cc
Normal file
15
src/abg-writer.h
Normal file
15
src/abg-writer.h
Normal file
@ -0,0 +1,15 @@
|
||||
// -*- mode: C++ -*-
|
||||
|
||||
#ifndef __ABG_WRITER_H__
|
||||
#define __ABG_WRITER_H__
|
||||
|
||||
#include "abg-ir.h"
|
||||
|
||||
namespace abigail
|
||||
{
|
||||
namespace writer
|
||||
{
|
||||
bool write(const namespace_decl ns);
|
||||
}//writer
|
||||
}
|
||||
#endif //__ABG_WRITER_H__
|
Loading…
Reference in New Issue
Block a user