mirror of
git://sourceware.org/git/libabigail.git
synced 2025-02-21 16:26:57 +00:00
Make bilint read input from stdin
* include/abg-libxml-utils.h (new_reader_from_istream): Declare new public entry point. * src/abg-libxml-utils.cc (xml_istream_input_read) (xml_istream_input_close): New static functions. (new_reader_from_istream): Define new public input function. * include/abg-reader.h (read_translation_unit_from_istream): Declare new entry points. * src/abg-reader.cc (read_translation_unit_from_istream): Define new entry points. * tools/bilint.cc (options::{read_from_stdin, noout}): New members. (display_usage): Document --stdin and --noout. (parse_command_line): Adjust to consider that no option on the command line means reading from stdin, just like --stdin. Support the --noout option as well. (main): Support Read the abi instr from stdin; in that case, what was read is just serialized back to stdout, unless --noout was supplied. Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
parent
d3929eaf23
commit
7350cfd893
@ -21,6 +21,7 @@
|
||||
/// @file
|
||||
|
||||
#include <tr1/memory>
|
||||
#include <istream>
|
||||
#include <libxml/xmlreader.h>
|
||||
|
||||
namespace abigail
|
||||
@ -55,6 +56,7 @@ typedef shared_ptr<xmlChar> xml_char_sptr;
|
||||
|
||||
reader_sptr new_reader_from_file(const std::string& path);
|
||||
reader_sptr new_reader_from_buffer(const std::string& buffer);
|
||||
reader_sptr new_reader_from_istream(std::istream*);
|
||||
xml_char_sptr build_xml_char_sptr(xmlChar*);
|
||||
|
||||
template<class T>
|
||||
|
@ -29,6 +29,7 @@
|
||||
#ifndef __ABG_READER_H__
|
||||
#define __ABG_READER_H__
|
||||
|
||||
#include <istream>
|
||||
#include "abg-corpus.h"
|
||||
|
||||
namespace abigail
|
||||
@ -55,6 +56,13 @@ bool
|
||||
read_translation_unit_from_buffer(const string& buffer,
|
||||
translation_unit& tu);
|
||||
|
||||
bool
|
||||
read_translation_unit_from_istream(std::istream* in,
|
||||
translation_unit& tu);
|
||||
|
||||
translation_unit_sptr
|
||||
read_translation_unit_from_istream(std::istream* in);
|
||||
|
||||
abigail::corpus_sptr
|
||||
read_corpus_from_file(const string& path);
|
||||
|
||||
|
@ -21,12 +21,15 @@
|
||||
/// @file
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include "abg-libxml-utils.h"
|
||||
|
||||
namespace abigail
|
||||
{
|
||||
namespace xml
|
||||
{
|
||||
using std::istream;
|
||||
|
||||
/// Instantiate an xmlTextReader that parses the content of an on-disk
|
||||
/// file, wrap it into a smart pointer and return it.
|
||||
///
|
||||
@ -56,6 +59,58 @@ new_reader_from_buffer(const std::string& buffer)
|
||||
return p;
|
||||
}
|
||||
|
||||
/// This is an xmlInputReadCallback, meant to be passed to
|
||||
/// xmlNewTextReaderForIO. It reads a number of bytes from an istream.
|
||||
///
|
||||
/// @param context an std::istream* cast into a void*. This is the
|
||||
/// istream that the xmlTextReader is too read data from.
|
||||
///
|
||||
/// @param buffer the buffer where to copy the data read from the
|
||||
/// input stream.
|
||||
///
|
||||
/// @param len the number of byte to read from the input stream and to
|
||||
/// copy into @ref buffer.
|
||||
///
|
||||
/// @return the number of bytes read or -1 in case of error.
|
||||
static int
|
||||
xml_istream_input_read(void* context,
|
||||
char* buffer,
|
||||
int len)
|
||||
{
|
||||
istream* in = reinterpret_cast<istream*>(context);
|
||||
in->read(buffer, len);
|
||||
if (in->fail())
|
||||
return -1;
|
||||
return in->gcount();
|
||||
}
|
||||
|
||||
/// This is an xmlInputCloseCallback, meant to be passed to
|
||||
/// xmlNewTextReaderForIO. It's supposed to close the input stream
|
||||
/// that the xmlTextReader is reading from. This particular
|
||||
/// implementation is noop; it does nothing.
|
||||
///
|
||||
/// @return 0.
|
||||
static int
|
||||
xml_istream_input_close(void*)
|
||||
{return 0;}
|
||||
|
||||
/// Instanciate an xmlTextReader that parses a content coming from an
|
||||
/// input stream.
|
||||
///
|
||||
/// @param in the input stream to consider.
|
||||
///
|
||||
/// @return reader_sptr a pointer to the newly instantiated xml
|
||||
/// reader.
|
||||
reader_sptr
|
||||
new_reader_from_istream(std::istream* in)
|
||||
{
|
||||
reader_sptr p =
|
||||
build_sptr(xmlReaderForIO(&xml_istream_input_read,
|
||||
&xml_istream_input_close,
|
||||
in, "", 0, 0));
|
||||
return p;
|
||||
}
|
||||
|
||||
/// Build and return a shared_ptr for a pointer to xmlTextReader
|
||||
template<>
|
||||
shared_ptr<xmlTextReader>
|
||||
|
@ -48,6 +48,7 @@ using std::stack;
|
||||
using std::tr1::unordered_map;
|
||||
using std::tr1::dynamic_pointer_cast;
|
||||
using std::vector;
|
||||
using std::istream;
|
||||
using zip_utils::zip_sptr;
|
||||
using zip_utils::zip_file_sptr;
|
||||
using zip_utils::open_archive;
|
||||
@ -2697,6 +2698,38 @@ handle_class_tdecl(read_context& ctxt)
|
||||
return is_ok;
|
||||
}
|
||||
|
||||
/// De-serialize a translation unit from an ABI Instrumentation xml
|
||||
/// file coming from an input stream.
|
||||
///
|
||||
/// @param in a pointer to the input stream.
|
||||
///
|
||||
/// @param tu the translation unit resulting from the parsing. This
|
||||
/// is populated iff the function returns true.
|
||||
///
|
||||
/// @return true upon successful parsing, false otherwise.
|
||||
bool
|
||||
read_translation_unit_from_istream(istream* in,
|
||||
translation_unit& tu)
|
||||
{
|
||||
read_context read_ctxt(xml::new_reader_from_istream(in));
|
||||
return read_input(read_ctxt, tu);
|
||||
}
|
||||
|
||||
/// De-serialize a translation unit from an ABI Instrumentation xml
|
||||
/// file coming from an input stream.
|
||||
///
|
||||
/// @param in a pointer to the input stream.
|
||||
///
|
||||
/// @return a pointer to the resulting translation unit.
|
||||
translation_unit_sptr
|
||||
read_translation_unit_from_istream(istream* in)
|
||||
{
|
||||
translation_unit_sptr result(new translation_unit(""));
|
||||
if (!read_translation_unit_from_istream(in, *result))
|
||||
return translation_unit_sptr();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// De-serialize a translation unit from an ABI Instrumentation XML
|
||||
/// file at a given path.
|
||||
///
|
||||
|
124
tools/bilint.cc
124
tools/bilint.cc
@ -41,14 +41,25 @@
|
||||
|
||||
using std::string;
|
||||
using std::cerr;
|
||||
using std::cin;
|
||||
using std::cout;
|
||||
using std::ostream;
|
||||
using std::ofstream;
|
||||
using abigail::tools::check_file;
|
||||
using abigail::xml_reader::read_translation_unit_from_file;
|
||||
using abigail::xml_reader::read_translation_unit_from_istream;
|
||||
using abigail::xml_writer::write_translation_unit;
|
||||
|
||||
struct options
|
||||
{
|
||||
string file_path;
|
||||
bool read_from_stdin;
|
||||
bool noout;
|
||||
|
||||
options()
|
||||
: read_from_stdin(false),
|
||||
noout(false)
|
||||
{}
|
||||
};//end struct options;
|
||||
|
||||
void
|
||||
@ -56,14 +67,19 @@ display_usage(const string& prog_name, ostream& out)
|
||||
{
|
||||
out << "usage: " << prog_name << "[options] [<bi-file1>\n"
|
||||
<< " where options can be:\n"
|
||||
<< " --help display this message\n";
|
||||
<< " --help display this message\n"
|
||||
<< " --noout do not display anything on stdout\n"
|
||||
<< " --stdin|-- read bi-file content from stdin\n";
|
||||
}
|
||||
|
||||
bool
|
||||
parse_command_line(int argc, char* argv[], options& opts)
|
||||
{
|
||||
if (argc < 2)
|
||||
return false;
|
||||
{
|
||||
opts.read_from_stdin = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
@ -76,13 +92,16 @@ parse_command_line(int argc, char* argv[], options& opts)
|
||||
}
|
||||
else if (!strcmp(argv[i], "--help"))
|
||||
return false;
|
||||
else if (!strcmp(argv[i], "--stdin"))
|
||||
opts.read_from_stdin = true;
|
||||
else if (!strcmp(argv[i], "--noout"))
|
||||
opts.noout = true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
if (opts.file_path.empty())
|
||||
return false;
|
||||
|
||||
opts.read_from_stdin = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -97,45 +116,68 @@ main(int argc, char* argv[])
|
||||
display_usage(argv[0], cerr);
|
||||
return true;
|
||||
}
|
||||
if (!check_file(opts.file_path, cerr))
|
||||
return true;
|
||||
|
||||
abigail::translation_unit_sptr tu =
|
||||
read_translation_unit_from_file(opts.file_path);
|
||||
|
||||
if (!tu)
|
||||
if (opts.read_from_stdin)
|
||||
{
|
||||
cerr << "failed to read " << opts.file_path << "\n";
|
||||
return true;
|
||||
if (!cin.good())
|
||||
return true;
|
||||
|
||||
abigail::translation_unit_sptr tu =
|
||||
read_translation_unit_from_istream(&cin);
|
||||
|
||||
if (!tu)
|
||||
{
|
||||
cerr << "failed to read the ABI instrumentation from stdin\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!opts.noout)
|
||||
write_translation_unit(*tu, 0, cout);
|
||||
return false;
|
||||
}
|
||||
else if (!opts.file_path.empty())
|
||||
{
|
||||
if (!check_file(opts.file_path, cerr))
|
||||
return true;
|
||||
|
||||
abigail::translation_unit_sptr tu =
|
||||
read_translation_unit_from_file(opts.file_path);
|
||||
|
||||
if (!tu)
|
||||
{
|
||||
cerr << "failed to read " << opts.file_path << "\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
char tmpn[L_tmpnam];
|
||||
tmpnam(tmpn);
|
||||
|
||||
string ofile_name = tmpn;
|
||||
|
||||
ofstream of(ofile_name.c_str(), std::ios_base::trunc);
|
||||
if (!of.is_open())
|
||||
{
|
||||
cerr << "open temporary output file " << ofile_name << "\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool r = write_translation_unit(*tu, /*indent=*/0, of);
|
||||
bool is_ok = r;
|
||||
of.close();
|
||||
|
||||
if (!is_ok)
|
||||
cerr << "failed to write the translation unit "
|
||||
<< opts.file_path << " back\n";
|
||||
|
||||
if (is_ok)
|
||||
{
|
||||
string cmd = "diff -u " + opts.file_path + " " + ofile_name;
|
||||
if (system(cmd.c_str()))
|
||||
is_ok = false;
|
||||
}
|
||||
remove(ofile_name.c_str());
|
||||
return !is_ok;
|
||||
}
|
||||
|
||||
char tmpn[L_tmpnam];
|
||||
tmpnam(tmpn);
|
||||
|
||||
string ofile_name = tmpn;
|
||||
|
||||
ofstream of(ofile_name.c_str(), std::ios_base::trunc);
|
||||
if (!of.is_open())
|
||||
{
|
||||
cerr << "open temporary output file " << ofile_name << "\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool r = abigail::xml_writer::write_translation_unit(*tu, /*indent=*/0, of);
|
||||
bool is_ok = r;
|
||||
of.close();
|
||||
|
||||
if (!is_ok)
|
||||
cerr << "failed to write the translation unit "
|
||||
<< opts.file_path << " back\n";
|
||||
|
||||
if (is_ok)
|
||||
{
|
||||
string cmd = "diff -u " + opts.file_path + " " + ofile_name;
|
||||
if (system(cmd.c_str()))
|
||||
is_ok = false;
|
||||
}
|
||||
remove(ofile_name.c_str());
|
||||
|
||||
return !is_ok;
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user