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:
Dodji Seketeli 2013-03-08 13:49:05 +01:00
parent e20615bf9f
commit 8e225db39a
15 changed files with 899 additions and 100 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
configure
aclocal.m4
*Makefile.in
build/
autom4te.cache/

View File

@ -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])

View File

@ -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
View 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
View 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
View 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
View 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__

View File

@ -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>

View File

@ -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
View 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
View 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
View 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
View 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
View File

15
src/abg-writer.h Normal file
View 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__