From a80b09f91204923e3170e8037f9bcad4bbcb24de Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Thu, 21 Mar 2013 14:43:30 +0100 Subject: [PATCH] Initial implementation of serialization of basic types and namespaces. * src/Makefile.am: Add abg-writer.{h,cc} and abg-config.{h,cc}. * src/abg-config.{h,cc}: New files. * src/abg-corpus.h (abi_corpus::decls_type): New typedef. (abi_corpus::{add,get_decls,get_loc_mgr}): Fix style. (abi_corpus::is_empty): Declare new function. * src/abg-corpus.cc (abi_corpus::add): really add the declaration to the corpus. (abi_corpus::is_empty): Define new function. * src/abg-ir.{h,cc} (location_manager::expand_location): Consti-fy this function. * src/abg-reader.cc (read_file): Add a corpus parameter. * src/abg-serialize.cc: Delete this file. * src/abg-writer.h (write_to_ostream): Rename write into this. Make it take a corpus and an ostream as parameters. * abg-writer.cc: New file. --- src/Makefile.am | 7 +- src/abg-config.cc | 51 ++++++++ src/abg-config.h | 41 ++++++ src/abg-corpus.cc | 8 +- src/abg-corpus.h | 20 ++- src/abg-ir.cc | 3 +- src/abg-ir.h | 4 +- src/abg-reader.cc | 2 +- src/abg-reader.h | 2 +- src/abg-serialize.cc | 0 src/abg-writer.cc | 297 +++++++++++++++++++++++++++++++++++++++++++ src/abg-writer.h | 13 +- 12 files changed, 431 insertions(+), 17 deletions(-) create mode 100644 src/abg-config.cc create mode 100644 src/abg-config.h delete mode 100644 src/abg-serialize.cc create mode 100644 src/abg-writer.cc diff --git a/src/Makefile.am b/src/Makefile.am index d8fcac47..3fed8c60 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -9,14 +9,17 @@ $(h)/abg-reader.h \ $(h)/abg-corpus.h \ $(h)/abg-libxml-utils.h \ $(h)/abg-hash.h \ -$(h)/abg-writer.h +$(h)/abg-writer.h \ +$(h)/abg-config.h 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 +$(h)/abg-hash.cc \ +$(h)/abg-writer.cc \ +$(h)/abg-config.cc libabigail_la_LDFLAGS=@ABIGAIL_LIBS@ -Wl,--as-needed diff --git a/src/abg-config.cc b/src/abg-config.cc new file mode 100644 index 00000000..681c2dca --- /dev/null +++ b/src/abg-config.cc @@ -0,0 +1,51 @@ +// -*- mode: C++ -*- + +#include "abg-config.h" + +namespace abigail +{ +config::config() + : m_format_minor(0), + m_format_major(1),// The version number of the serialization + // format. + m_xml_element_indent(2) +{ +} + +unsigned char +config::get_format_minor_version_number() const +{ + return m_format_minor; +} + +void +config::set_format_minor_version_number(unsigned char v) +{ + m_format_minor = v; +} + +unsigned char +config::get_format_major_version_number() const +{ + return m_format_major; +} + +void +config::set_format_major_version_number(unsigned char v) +{ + m_format_major= v; +} + +unsigned +config::get_xml_element_indent() const +{ + return m_xml_element_indent; +} + +void +config::set_xml_element_indent(unsigned indent) +{ + m_xml_element_indent = indent; +} + +}//end namespace abigail diff --git a/src/abg-config.h b/src/abg-config.h new file mode 100644 index 00000000..919697af --- /dev/null +++ b/src/abg-config.h @@ -0,0 +1,41 @@ +// -*- Mode: C++ -*- +#ifndef __ABG_CONFIG_H__ +#define __ABG_CONFIG_H__ + +namespace abigail +{ + +/// This type abstracts the configuration information of the library. +class config +{ +public: + config(); + + unsigned char + get_format_minor_version_number() const; + + void + set_format_minor_version_number(unsigned char); + + unsigned char + get_format_major_version_number() const; + + + void + set_format_major_version_number(unsigned char); + + unsigned + get_xml_element_indent() const; + + void + set_xml_element_indent(unsigned); + +private: + unsigned char m_format_minor; + unsigned char m_format_major; + unsigned m_xml_element_indent; +};//end class config + +}//end namespace abigail + +#endif //__ABG_CONFIG_H__ diff --git a/src/abg-corpus.cc b/src/abg-corpus.cc index f921b311..d652afaa 100644 --- a/src/abg-corpus.cc +++ b/src/abg-corpus.cc @@ -13,7 +13,7 @@ abi_corpus::abi_corpus(const std::string& name) void abi_corpus::add(const shared_ptr declaration) { - m_members; + m_members.push_back(declaration); } const std::list >& @@ -34,4 +34,10 @@ abi_corpus::get_loc_mgr() return m_loc_mgr; } +bool +abi_corpus::is_empty() const +{ + return m_members.empty(); +} + }//end namespace abigail diff --git a/src/abg-corpus.h b/src/abg-corpus.h index c2b5916e..fbc2f741 100644 --- a/src/abg-corpus.h +++ b/src/abg-corpus.h @@ -18,12 +18,24 @@ class abi_corpus abi_corpus(); public: + typedef std::list > decls_type; + abi_corpus(const std::string& name); - void add(const shared_ptr declaration); - const std::list >& get_decls() const; - location_manager& get_loc_mgr(); - const location_manager& get_loc_mgr() const; + void + add(const shared_ptr declaration); + + const std::list >& + get_decls() const; + + location_manager& + get_loc_mgr(); + + const location_manager& + get_loc_mgr() const; + + bool + is_empty() const; private: std::string m_name; diff --git a/src/abg-ir.cc b/src/abg-ir.cc index edb18e53..c29deee6 100644 --- a/src/abg-ir.cc +++ b/src/abg-ir.cc @@ -94,7 +94,6 @@ location_manager::create_new_location(const std::string& file_path, m_priv->locs.end(), l); - unsigned opaque = 0; if (i == m_priv->locs.end()) { m_priv->locs.push_back(l); @@ -127,7 +126,7 @@ void location_manager::expand_location(const location location, std::string& path, unsigned& line, - unsigned& column) + unsigned& column) const { expanded_location &l = m_priv->locs[location.m_value]; path = l.m_path; diff --git a/src/abg-ir.h b/src/abg-ir.h index 692b9eb7..5e90b44d 100644 --- a/src/abg-ir.h +++ b/src/abg-ir.h @@ -20,7 +20,7 @@ using std::string; namespace abigail { /// \brief The source location of a token. -/// +/// /// This represents the location of a token coming from a given ABI /// Corpus. This location is actually an abstraction of cursor in the /// table of all the locations of all the tokens of the ABI Corpus. @@ -78,7 +78,7 @@ public: expand_location(const location location, std::string& path, unsigned& line, - unsigned& column); + unsigned& column) const; }; class scope_decl; diff --git a/src/abg-reader.cc b/src/abg-reader.cc index 57582bf9..b0450614 100644 --- a/src/abg-reader.cc +++ b/src/abg-reader.cc @@ -129,7 +129,7 @@ static bool handle_type_decl(read_context&, abi_corpus&); static bool handle_namespace_decl(read_context&, abi_corpus&); bool -read_file(string& file_path, +read_file(const string& file_path, abi_corpus& corpus) { read_context read_ctxt(xml::new_reader_from_file(file_path)); diff --git a/src/abg-reader.h b/src/abg-reader.h index 19020bc2..ee1b05a4 100644 --- a/src/abg-reader.h +++ b/src/abg-reader.h @@ -8,7 +8,7 @@ namespace abigail { namespace reader { -bool read_file(std::string& file_path, +bool read_file(const std::string& file_path, abi_corpus& abi_corpus); }// end namespace reader diff --git a/src/abg-serialize.cc b/src/abg-serialize.cc deleted file mode 100644 index e69de29b..00000000 diff --git a/src/abg-writer.cc b/src/abg-writer.cc new file mode 100644 index 00000000..4ad1703d --- /dev/null +++ b/src/abg-writer.cc @@ -0,0 +1,297 @@ +// -*- mode: C++ -*- + +#include +#include +#include +#include "abg-writer.h" +#include "abg-config.h" + +using std::tr1::shared_ptr; +using std::tr1::dynamic_pointer_cast; +using std::ostream; +using std::ostringstream; +using std::list; + +namespace abigail +{ +namespace writer +{ + +class id_manager +{ + + unsigned long long + get_new_id() + { + return ++m_cur_id; + } + +public: + id_manager() + : m_cur_id(0) + { + } + + /// Return a unique string representing a numerical id. + string + get_id() + { + ostringstream o; + o << get_new_id(); + return o.str(); + } + + /// Return a unique string representing a numerical ID, prefixed by + /// #prefix. + /// + /// \param prefix the prefix of the returned unique id. + string + get_id_with_prefix(const string& prefix) + { + ostringstream o; + o << prefix << get_new_id(); + return o.str(); + } + +private: + unsigned long long m_cur_id; +};//end class id_manager + +class write_context +{ + + write_context(); + +public: + + write_context(ostream& os) + : m_ostream(os) + { + } + + const config& + get_config() const + { + return m_config; + } + + ostream& + get_ostream() + { + return m_ostream; + } + + id_manager& + get_id_manager() + { + return m_id_manager; + } + +private: + id_manager m_id_manager; + config m_config; + ostream& m_ostream; +};//end write_context + +static bool write_corpus(const abi_corpus&, + write_context&, + unsigned); +static bool write_decl(const shared_ptr, + const abi_corpus&, + write_context&, + unsigned); +static bool write_type_decl(const shared_ptr, + const abi_corpus&, + write_context&, + unsigned); +static bool write_namespace_decl(const shared_ptr, + const abi_corpus&, + write_context&, + unsigned); + +/// Serialize an abi corpus into an output stream. +/// +/// \param corpus the corpus to serialize +/// +/// \param out the output stream. +/// +/// \return true upon successful completion, false otherwise. +bool +write_to_ostream(const abi_corpus& corpus, + ostream &out) +{ + write_context ctxt(out); + + return write_corpus(corpus, ctxt, /*indent=*/0); +} + +/// Serialize a pointer to an of decl_base into an output stream. +/// +/// \param decl, the pointer to decl_base to serialize +/// +/// \param corpus the abi corpus the decl belongs to. +/// +/// \param ctxt the context of the serialization. It contains e.g, the +/// output stream to serialize to. +/// +/// \param indent how many indentation spaces to use during the +/// serialization. +/// +/// \return true upon successful completion, false otherwise. +static bool +write_decl(const shared_ptr decl, + const abi_corpus& corpus, + write_context& ctxt, + unsigned indent) +{ + if (write_type_decl(dynamic_pointer_cast (decl), + corpus, ctxt, indent)) + return true; + if (write_namespace_decl(dynamic_pointer_cast(decl), + corpus, ctxt, indent)) + return true; + + return false; +} + +/// Serialize an abi corpus into an output stream. +/// +/// \param a corpus the abi corpus to serialize. +/// +/// \param ctxt the context of the serialization. It contains e.g, +/// the output stream to serialize to. +/// +/// \param indent how many indentation spaces to use during the +/// serialization. +/// +/// \return true upon successful completion, false otherwise. +static bool +write_corpus(const abi_corpus& corpus, write_context& ctxt, unsigned indent) +{ + ostream &o = ctxt.get_ostream(); + const config &c = ctxt.get_config(); + + for (unsigned i = 0; i < indent; ++i) + o << ' '; + + o << ""; + return true; + } + + for (abi_corpus::decls_type::const_iterator i = corpus.get_decls().begin(); + i != corpus.get_decls().end(); + ++i) + { + o << "\n"; + write_decl(*i, corpus, ctxt, + indent + c.get_xml_element_indent()); + } + + return true; +} + +/// Serialize a pointer to an instance of basic type declaration, into +/// an output stream. +/// +/// \param d the basic type declaration to serialize. +/// +/// \param corpus the instance of abi corpus the declaration belongs +/// to. +/// +/// \param ctxt the context of the serialization. It contains e.g, the +/// output stream to serialize to. +/// +/// \param indent how many indentation spaces to use during the +/// serialization. +/// +/// \return true upon successful completion, false otherwise. +static bool +write_type_decl(const shared_ptr d, + const abi_corpus& corpus, + write_context& ctxt, + unsigned indent) +{ + ostream &o = ctxt.get_ostream(); + + for (unsigned i = 0; i < indent; ++i) + o << ' '; + + o << "get_size_in_bits(); + if (size_in_bits) + o << " size-in-bits='" << size_in_bits << "'"; + size_t alignment_in_bits = d->get_alignment_in_bits(); + if (alignment_in_bits) + o << " alignment-in-bits='" << alignment_in_bits << "'"; + + location loc = d->get_location(); + if (loc) + { + string path; + unsigned line = 0, column = 0; + corpus.get_loc_mgr().expand_location(loc, path, line, column); + o << " filepath='" << path << "'" + << " line='" << line << "'" + << " column='" << column << "'"; + } + o<< "/>"; + + return true; +} + +/// Serialize a namespace declaration int an output stream. +/// +/// \param decl the namespace declaration to serialize. +/// +/// \param corpus the instance of abi corpus the declaration belongs +/// to. +/// +/// \param ctxt the context of the serialization. It contains e.g, the +/// output stream to serialize to. +/// +/// \param indent how many indentation spaces to use during the +/// serialization. +/// +/// \return true upon successful completion, false otherwise. +static bool +write_namespace_decl(const shared_ptr decl, + const abi_corpus& corpus, + write_context& ctxt, + unsigned indent) +{ + ostream &o = ctxt.get_ostream(); + const config &c = ctxt.get_config(); + + for (unsigned i = 0; i < indent; ++i) + o << ' '; + + o << ""; + + for (list >::const_iterator i = + decl->get_member_decls ().begin(); + i != decl->get_member_decls ().end(); + ++i) + { + o << "\n"; + write_decl(*i, corpus, ctxt, + indent + c.get_xml_element_indent()); + } + + o << ""; + + return true; +} + +}//end namespace writer +}//end namespace abigail diff --git a/src/abg-writer.h b/src/abg-writer.h index f33a3930..423083a0 100644 --- a/src/abg-writer.h +++ b/src/abg-writer.h @@ -3,13 +3,18 @@ #ifndef __ABG_WRITER_H__ #define __ABG_WRITER_H__ -#include "abg-ir.h" +#include +#include "abg-corpus.h" namespace abigail { namespace writer { -bool write(const namespace_decl ns); -}//writer -} + +bool write_to_ostream(const abi_corpus& corpus, + std::ostream& out); + +}//end namespace writer + +}// end namespace abigail #endif //__ABG_WRITER_H__