fixed a lot of issues, now successfully runs the test with --enable-pedantic; refs #8

This commit is contained in:
Marc Wäckerlin
2014-03-28 11:50:39 +00:00
parent e846c326f1
commit 190b469d56
33 changed files with 398 additions and 409 deletions

View File

@@ -103,25 +103,26 @@ namespace mrw {
std::string arg(argv[i]);
if (arg.find("--")==0 && arg!="--") { // long arguments
LongOpts::iterator it(_longopts.find(arg));
if (it!=_longopts.end() || i+it->second->args().size()>=argc)
if (it!=_longopts.end() || i+(int)it->second->args().size()>=argc)
throw mrw::invalid_argument(arg);
it->second->set();
for (int j(0), l(it->second->args().size()); j<l; ++j) {
for (int j(0), l((int)it->second->args().size()); j<l; ++j) {
*(it->second->args().setable(j)) = argv[++i];
}
} else if (arg.find("-")==0) { // short arguments
// first check all, then set all
for (int j(1), l(arg.size()); j<l; ++j) {
for (std::string::size_type j(1), l(arg.size()); j<l; ++j) {
ShortOpts::iterator it(_shortopts.find(arg[j]));
if (it==_shortopts.end() || it->second->args().size()>0 &&
(j+1!=l || i+it->second->args().size()>=argc))
if (it==_shortopts.end() ||
(it->second->args().size()>0 &&
(j+1!=l || i+(int)it->second->args().size()>=argc)))
throw mrw::invalid_argument(arg);
}
for (int j(1), l(arg.size()); j<l; ++j) {
for (std::string::size_type j(1), l(arg.size()); j<l; ++j) {
ShortOpts::iterator it(_shortopts.find(arg[j]));
it->second->set();
if (j+1==l && it->second->args().size()>0) {
for (int k(0); k < it->second->args().size(); ++k) {
for (int k(0); k < (int)it->second->args().size(); ++k) {
*(it->second->args().setable(k)) = argv[++i];
}
}

View File

@@ -100,17 +100,17 @@ namespace mrw {
try {
throw;
} catch (const mrw::exception& x) {
std::string txt(std::string("Reason:\n")+x.what()
std::string txt2(std::string("Reason:\n")+x.what()
+"\nStack:\n"+x.stacktrace());
logger->fatal(std::string(txt.begin(), txt.end()));
logger->fatal(std::string(txt2.begin(), txt2.end()));
} catch (const std::exception& x) {
std::string txt(std::string("Reason:\n")+x.what()
std::string txt2(std::string("Reason:\n")+x.what()
+"\nStack:\n"+st);
logger->fatal(std::string(txt.begin(), txt.end()));
logger->fatal(std::string(txt2.begin(), txt2.end()));
} catch (...) {
std::string txt(std::string("Reason: **** not available ****")
std::string txt2(std::string("Reason: **** not available ****")
+"\nStack:\n"+st);
logger->fatal(std::string(txt.begin(), txt.end()));
logger->fatal(std::string(txt2.begin(), txt2.end()));
}
throw std::bad_exception();
}
@@ -156,17 +156,17 @@ namespace mrw {
try {
throw;
} catch (const mrw::exception& x) {
std::string txt(std::string("Reason:\n")+x.what()
std::string txt2(std::string("Reason:\n")+x.what()
+"\nStack:\n"+x.stacktrace());
logger->fatal(std::string(txt.begin(), txt.end()));
logger->fatal(std::string(txt2.begin(), txt2.end()));
} catch (const std::exception& x) {
std::string txt(std::string("Reason:\n")+x.what()
std::string txt2(std::string("Reason:\n")+x.what()
+"\nStack:\n"+st);
logger->fatal(std::string(txt.begin(), txt.end()));
logger->fatal(std::string(txt2.begin(), txt2.end()));
} catch (...) {
std::string txt(std::string("Reason: **** not available ****")
std::string txt2(std::string("Reason: **** not available ****")
+"\nStack:\n"+st);
logger->fatal(std::string(txt.begin(), txt.end()));
logger->fatal(std::string(txt2.begin(), txt2.end()));
}
exit(1);
}

View File

@@ -106,8 +106,8 @@ mrw::ConfigFileReader::parseValue(const std::string& file,
endVal = file.find_last_not_of("\n\t ", // remove trailing white spaces
endVal!=std::string::npos?endVal-1:endVal)+1;
std::string::size_type realEnd(endVal!=std::string::npos && // quotes?
(file[realStart]=='"' && file[endVal]=='"' ||
file[realStart]=='\'' && file[endVal]=='\'')
((file[realStart]=='"' && file[endVal]=='"') ||
(file[realStart]=='\'' && file[endVal]=='\''))
? endVal+1 : endVal);
if (endVal<=startVal)
return std::make_pair // empty value
@@ -152,18 +152,21 @@ mrw::ConfigFileWriter& mrw::ConfigFileWriter::save() throw(std::exception) {
changed = true;
// check if we need quoting
std::string value(var->second.value);
if (value.find_first_of("[=#")!=std::string::npos)
if (value.find('"')==std::string::npos)
if (value.find_first_of("[=#")!=std::string::npos) {
if (value.find('"')==std::string::npos) {
value = '"'+value+'"';
else if (value.find('\'')==std::string::npos)
} else if (value.find('\'')==std::string::npos) {
value = '\''+value+'\'';
else
} else {
throw mrw::invalid_argument("Configuration value is not quotable: "
+value);
}
}
// recalculate all positions
if (var->second.start &&
value.size() != var->second.end-var->second.start) {
int diff(value.size()-var->second.end+var->second.start);
std::string::size_type diff
(value.size()-var->second.end+var->second.start);
for (Values::iterator sec2(_values.begin());
sec2!=_values.end(); ++sec2)
for (Values::mapped_type::iterator var2(sec2->second.begin());

View File

@@ -208,25 +208,29 @@ mrw::Exec& mrw::Exec::execute(bool exc) throw(std::exception) {
one. */
while (num1||num2||!res) try { // not end of files or child terminated
if (!res && (res=waitpid(pid, &s, WNOHANG)))
if (res!=pid || WIFEXITED(s)!=0 && WEXITSTATUS(s)!=0)
if (res!=pid || (WIFEXITED(s)!=0 && WEXITSTATUS(s)!=0))
throw ExecutionFailedExc("execution failed", *_cmd);
if (num1<=0&&num2<=0) usleep(10000); // nothing to read last time
// check and handle stdout
if (num1 && (num1=read(stdOut.istream(), buf, sizeof(buf)))>0)
if (num1 && (num1=read(stdOut.istream(), buf, sizeof(buf)))>0) {
_res += std::string(buf, num1);
else if (num1==-1)
if (errno!=EINTR&&errno!=EAGAIN)
} else if (num1==-1) {
if (errno!=EINTR&&errno!=EAGAIN) {
throw ExecutionFailedExc("readin stdout", *_cmd);
else
} else {
num1 = 1;
}
}
// check and handle stderr
if (num2 && (num2=read(stdErr.istream(), buf, sizeof(buf)))>0)
if (num2 && (num2=read(stdErr.istream(), buf, sizeof(buf)))>0) {
_err += std::string(buf, num2);
else if (num2==-1)
if (errno!=EINTR&&errno!=EAGAIN)
} else if (num2==-1) {
if (errno!=EINTR&&errno!=EAGAIN) {
throw ExecutionFailedExc("readin stderr", *_cmd);
else
} else {
num2 = 1;
}
}
} catch (...) {
_success = false;
if (exc) throw;
@@ -283,7 +287,7 @@ mrw::Exec& mrw::Exec::execute(const std::string& input, bool exc)
one. */
while (num0||num1||num2||!res) try { // not end of files or child terminated
if (!res && (res=waitpid(pid, &s, WNOHANG)))
if (res!=pid || WIFEXITED(s)!=0 && WEXITSTATUS(s)!=0)
if (res!=pid || (WIFEXITED(s)!=0 && WEXITSTATUS(s)!=0))
throw ExecutionFailedExc("execution failed", *_cmd);
if (num0<=0&&num1<=0&&num2<=0) usleep(10000); // no activity last time
// check and handle stdin
@@ -292,27 +296,32 @@ mrw::Exec& mrw::Exec::execute(const std::string& input, bool exc)
in = in.substr(num0);
else if ((unsigned int)num0==in.size())
num0=0, stdIn.close_out();
} else if (num0==-1)
} else if (num0==-1) {
if (errno!=EINTR&&errno!=EAGAIN)
throw ExecutionFailedExc("writing stdin", *_cmd);
else
num0 = 1;
}
// check and handle stdout
if (num1 && (num1=read(stdOut.istream(), buf, sizeof(buf)))>0)
if (num1 && (num1=read(stdOut.istream(), buf, sizeof(buf)))>0) {
_res += std::string(buf, num1);
else if (num1==-1)
if (errno!=EINTR&&errno!=EAGAIN)
} else if (num1==-1) {
if (errno!=EINTR&&errno!=EAGAIN) {
throw ExecutionFailedExc("readin stdout", *_cmd);
else
} else {
num1 = 1;
}
}
// check and handle stderr
if (num2 && (num2=read(stdErr.istream(), buf, sizeof(buf)))>0)
if (num2 && (num2=read(stdErr.istream(), buf, sizeof(buf)))>0) {
_err += std::string(buf, num2);
else if (num2==-1)
if (errno!=EINTR&&errno!=EAGAIN)
} else if (num2==-1) {
if (errno!=EINTR&&errno!=EAGAIN) {
throw ExecutionFailedExc("readin stderr", *_cmd);
else
} else {
num2 = 1;
}
}
} catch (...) {
_success = false;
if (exc) throw;
@@ -498,7 +507,7 @@ std::pair<std::string, std::string>
char buf[4096];
int s(0);
if (!_lastPid && (_lastPid=waitpid(_pid, &s, WNOHANG))) {
if (_lastPid!=_pid || WIFEXITED(s)!=0 && WEXITSTATUS(s)!=0)
if (_lastPid!=_pid || (WIFEXITED(s)!=0 && WEXITSTATUS(s)!=0))
throw ExecutionFailedExc("execution failed", *_cmd);
}
// check and handle stdin
@@ -508,27 +517,30 @@ std::pair<std::string, std::string>
_input = _input.substr(_num0);
else if ((unsigned int)_num0==_input.size())
_input.clear();
} else if (_num0==-1)
} else if (_num0==-1) {
if (errno!=EINTR&&errno!=EAGAIN)
throw ExecutionFailedExc("writing stdin", *_cmd);
else
_num0 = 1;
}
// check and handle stdout
if (_num1 && (_num1=::read(_stdOut->istream(), buf, sizeof(buf)))>0)
if (_num1 && (_num1=::read(_stdOut->istream(), buf, sizeof(buf)))>0) {
_res += output.first=std::string(buf, _num1);
else if (_num1==-1)
} else if (_num1==-1) {
if (errno!=EINTR&&errno!=EAGAIN)
throw ExecutionFailedExc("readin stdout", *_cmd);
else
_num1 = 1;
}
// check and handle stderr
if (_num2 && (_num2=::read(_stdErr->istream(), buf, sizeof(buf)))>0)
if (_num2 && (_num2=::read(_stdErr->istream(), buf, sizeof(buf)))>0) {
_err += output.second=std::string(buf, _num2);
else if (_num2==-1)
} else if (_num2==-1) {
if (errno!=EINTR&&errno!=EAGAIN)
throw ExecutionFailedExc("readin stderr", *_cmd);
else
_num2 = 1;
}
if (_finish && !_input.size()) {
_stdIn->close_out();
_num0 = 0;

View File

@@ -332,7 +332,7 @@ namespace mrw {
public:
/// @brief returns the number of (mandatory) parameter
int size() const throw(std::bad_exception) {
Params::size_type size() const throw(std::bad_exception) {
return _params.size();
}
@@ -774,13 +774,14 @@ namespace mrw {
<<"OPTIONS:"<<std::endl;
for (Options::iterator it(_options.begin()); it!=_options.end(); ++it) {
std::cout<<" -"<<it->_shortname<<" | "<<it->_longname;
for (int i(0); i<it->_param.size(); ++i)
std::cout<<" <"<<(*it)[i]->typestr()<<">";
for (Param::Params::size_type i(0); i<it->_param.size(); ++i)
std::cout<<" <"<<(*it)[(unsigned int)i]->typestr()<<">";
if (it->_param.size()>0) std::cout<<" (default: ";
for (int i(0); i<it->_param.size()-1; ++i)
std::cout<<(*it)[i]->printable()<<" ";
for (Param::Params::size_type i(0); i<it->_param.size()-1; ++i)
std::cout<<(*it)[(unsigned int)i]->printable()<<" ";
if (it->_param.size()>0)
std::cout<<(*it)[it->_param.size()-1]->printable()<<")";
std::cout<<(*it)[(unsigned int)(it->_param.size()-1)]->printable()
<<")";
std::cout<<std::endl<<" "<<it->help()<<std::endl;
}
if (_description.size()>0)

View File

@@ -23,7 +23,7 @@
/** @page oldcompiler Workaround for old non C++11 compilers
... to be documented
@note Old compilers are automatically detected and the flag
@refs MRW__OLD_PRE11_COMPILER is set.
@ref MRW__OLD_PRE11_COMPILER is set.
*/
// Add version information for @c what and @c ident
@@ -240,12 +240,12 @@ namespace mrw {
}
/// Initialize all parameters according to the commandline options.
/** Sets up the parser from the @ref list of parameters
@param argc the argument count as given in C++ @c main function
@param argv the array of arguments as given in C++ @c main function
@param descr a string describing what the program does,
used in @ref show_help
@param l list of options and parameters to be parsed
@raram ret documentation of the return values of the program */
@param argc the argument count as given in C++ @c main function
@param argv the array of arguments as given in C++ @c main function
@param desc a string describing what the program does,
used in @ref show_help
@param l list of options and parameters to be parsed
@param ret documentation of the return values of the program */
static void parse(int argc, char** argv, const std::string& desc, list l,
const std::string& ret = std::string()) {
filename(argv[0]); // store filename for later use in help
@@ -286,8 +286,9 @@ namespace mrw {
const std::string& description_txt="DESCRIPTION",
const std::string& options_txt="OPTIONS",
const std::string& returns_txt="RETURNS",
int max_line=80, int indent=2, int long_indent=4,
int option_len=16, int param_len=21) {
unsigned int max_line=80, unsigned int indent=2,
unsigned int long_indent=4,
unsigned int option_len=16, unsigned int param_len=21) {
std::cout<<synopsis_txt<<std::endl<<std::endl
<<" "<<filename()<<" ["<<options_txt<<"]"<<std::endl<<std::endl
<<description_txt<<std::endl<<std::endl
@@ -322,13 +323,13 @@ namespace mrw {
}));
#endif
std::cout<<std::endl<<" "
<<o<<std::setw(option_len-o.size())<<' '
<<o<<std::setw(int(option_len-o.size()))<<' '
<<a;
if (arg->desc.size()>max_line-indent-option_len-param_len)
std::cout<<std::endl<<std::endl<<ssplit(max_line, long_indent)
<<arg->desc;
else
std::cout<<std::setw(param_len-a.size())<<' '<<arg->desc;
std::cout<<std::setw(int(param_len-a.size()))<<' '<<arg->desc;
std::cout<<std::endl;
}
if (returns().size()) {

View File

@@ -34,7 +34,7 @@ namespace mrw {
you and not a system call allocates memory), @c open and so on.
These classes can take over the resource ownership.
The following ressource handler are predefined:
The following resource handler are predefined:
- mrw::AutoPtr<> is the same as std::auto_ptr, but can be stored
in STL containers
@code
@@ -55,7 +55,7 @@ namespace mrw {
- mrw::AutoMapper calls @c munmap on memory mapped files
- mrw::AutoBfd automatically calls @c bfd_close
If this is not enough, you can @c typedef your own ressource
If this is not enough, you can @c typedef your own resource
handler from the template class mrw::AutoResource<>. For example,
mrw::AutoFile is defined as:
@code
@@ -101,6 +101,8 @@ namespace mrw {
typename FREE_TYPE = RESOURCE_TYPE>
class AutoResource {
public:
/// @brief type of the resource
typedef RESOURCE_TYPE Type;
/// @brief Construct from an allocated resource.
/// The resource is freed if necessary.
/// AutoResource takes over ownership of the resource.
@@ -218,7 +220,11 @@ namespace mrw {
return reset(other.release());
}
/// @brief Get the resource.
operator T* const() const throw(std::bad_exception) {
operator const T*() const throw(std::bad_exception) {
return _res;
}
/// @brief Get the resource.
operator T*() throw(std::bad_exception) {
return _res;
}
/// @brief find out, if a value is set
@@ -227,7 +233,11 @@ namespace mrw {
return _res!=0;
}
/// @brief Access the AutoPtr like a normal pointer.
T*const operator->() {return _res;}
const T* operator->() const {return _res;}
/// @brief Access the AutoPtr like a normal pointer.
T* operator->() {return _res;}
/// @brief Dereference the AutoPtr like a normal pointer.
const T& operator*() const {return *_res;}
/// @brief Dereference the AutoPtr like a normal pointer.
T& operator*() {return *_res;}
/// @brief get the resetted resource for resetting it.
@@ -308,7 +318,11 @@ namespace mrw {
return reset(other.release());
}
/// @brief Get the resource.
operator T* const() const throw(std::bad_exception) {
operator const T*() const throw(std::bad_exception) {
return _res;
}
/// @brief Get the resource.
operator T*() throw(std::bad_exception) {
return _res;
}
/// @brief find out, if a value is set
@@ -317,7 +331,11 @@ namespace mrw {
return _res!=0;
}
/// @brief Access the AutoPtrAry like a normal pointer.
T*const operator->() {return _res;}
const T* operator->() const {return _res;}
/// @brief Access the AutoPtrAry like a normal pointer.
T* operator->() {return _res;}
/// @brief Dereference the AutoPtrAry like a normal pointer.
const T& operator*() const {return *_res;}
/// @brief Dereference the AutoPtrAry like a normal pointer.
T& operator*() {return *_res;}
/// @brief get the resetted resource for resetting it.

View File

@@ -47,6 +47,12 @@ namespace std {
explicit shared_ptr(): boost::shared_ptr<T>() {}
explicit shared_ptr(T* p): boost::shared_ptr<T>(p) {}
};
// auto_ptr is deprecated in favour of unique_ptr, simulate unique_ptr
template <typename T> class unique_ptr: public std::auto_ptr<T> {
public:
explicit unique_ptr(): auto_ptr<T>() {}
explicit unique_ptr(T* p): auto_ptr<T>(p) {}
};
};
# endif
# endif

View File

@@ -76,6 +76,24 @@ template <typename T, typename A>
return copy;
}
/* @brief push a char* to a dequeue of string
@code
std::dequeue<std::string> test;
test<<"Hello"<<"World";
@endcode
@param l a dequeue of string values (that can be constructed from char*)
@param o a value to be inserted into dequeue @c l
@pre \#include <mrw/dequeue.hxx> */
template <typename T, typename A>
std::deque<T, A>& operator<<(std::deque<T, A>& l,
const char *const o)
throw(std::bad_exception) {
l.push_back(T(o));
return l;
}
/** @brief extract the first value of a deque
@code

View File

@@ -434,9 +434,10 @@ while (!exec.finished()) res+=exec.read().first;
bool _finished;
bool _finish;
std::auto_ptr<mrw::Pipe> _stdIn, _stdOut, _stdErr;
std::shared_ptr<mrw::Pipe> _stdIn, _stdOut, _stdErr;
std::string _input;
int _num0, _num1, _num2, _lastPid, _pid;
ssize_t _num0, _num1, _num2;
int _lastPid, _pid;
};
//============================================================================

View File

@@ -42,7 +42,7 @@
#else
# define LOG4CXX_CVS
# define MRW_LOG4CXX_LOCATION \
::log4cxx::spi::LocationInfo(_file.c_str(), _name.c_str(), _line)
::log4cxx::spi::LocationInfo(_file.c_str(), _name.c_str(), (int)_line)
#define MRW_LEVEL_DEBUG ::log4cxx::Level::getDebug()
#define MRW_LEVEL_INFO ::log4cxx::Level::getInfo()
#define MRW_LEVEL_WARN ::log4cxx::Level::getWarn()

View File

@@ -65,7 +65,7 @@ namespace mrw {
}
return const_cast<basic_split&>(s);
}
template <typename T> basic_split& operator<<(T t) {
template <typename T> basic_split& operator<<(const T& t) {
if (!_os)
throw std::runtime_error("wrong use of split, it is an io"
" manipulator and must be used within"

View File

@@ -65,7 +65,7 @@
@param l a list of values
@param o a value to be inserted into list @c l
@pre #include <mrw/list.hxx>
@pre \#include <mrw/list.hxx>
*/
template <typename T, typename A>
std::list<T, A>& operator<<(std::list<T, A>& l, const T& o)
@@ -84,7 +84,7 @@ template <typename T, typename A>
@param l a list of values
@param o a value to be inserted into list @c l
@pre #include <mrw/list.hxx>
@pre \#include <mrw/list.hxx>
*/
template <typename T, typename A>
std::list<T, A> operator<<(const std::list<T, A>& l, const T& o)
@@ -105,8 +105,8 @@ template <typename T, typename A>
@param o a value to be inserted into list @c l
@pre \#include <mrw/list.hxx> */
template <typename T, typename A>
std::list<T, A> operator<<(std::list<T, A> l,
const char *const o)
std::list<T, A>& operator<<(std::list<T, A>& l,
const char *const o)
throw(std::bad_exception) {
l.push_back(T(o));
return l;

View File

@@ -78,6 +78,24 @@ template <typename T, class C, typename A>
return copy;
}
/* @brief push a char* to a multiset of string
@code
std::multiset<std::string> test;
test<<"Hello"<<"World";
@endcode
@param l a multiset of string values (that can be constructed from char*)
@param o a value to be inserted into multiset @c l
@pre \#include <mrw/multiset.hxx> */
template <typename T, class C, typename A>
std::multiset<T, C, A>& operator<<(std::multiset<T, C, A>& l,
const char *const o)
throw(std::bad_exception) {
l.push_back(T(o));
return l;
}
/** @brief extract the first value of a multiset
@code

View File

@@ -48,7 +48,7 @@
@throw mrw::invalid_argument, if element is already in set
@param l a set of values
@param o a value to be inserted into set @c l
@pre #include <mrw/set.hxx>
@pre \#include <mrw/set.hxx>
*/
template <typename T, class C, typename A>
std::set<T, C, A>& operator<<(std::set<T, C, A>& l, const T& o)
@@ -71,7 +71,7 @@ template <typename T, class C, typename A>
@throw mrw::invalid_argument, if element is already in set
@param l a set of values
@param o a value to be inserted into set @c l
@pre #include <mrw/set.hxx>
@pre \#include <mrw/set.hxx>
*/
template <typename T, class C, typename A>
std::set<T, C, A> operator<<(const std::set<T, C, A>& l, const T& o)
@@ -84,6 +84,24 @@ template <typename T, class C, typename A>
return copy;
}
/* @brief push a char* to a set of string
@code
std::set<std::string> test;
test<<"Hello"<<"World";
@endcode
@param l a set of string values (that can be constructed from char*)
@param o a value to be inserted into set @c l
@pre \#include <mrw/set.hxx> */
template <typename T, class C, typename A>
std::set<T, C, A>& operator<<(std::set<T, C, A>& l,
const char *const o)
throw(std::bad_exception) {
l.push_back(T(o));
return l;
}
/** @brief extract the first value of a set
@code

View File

@@ -34,6 +34,8 @@ namespace mrw {
};
class SmartPointerParent {
public:
virtual ~SmartPointerParent() {}
protected:
template<class TYPE>
PointerCounter* getCounter(TYPE& sp) throw() {
@@ -102,7 +104,7 @@ namespace mrw {
_cnt(0), _ptr(dynamic_cast<TYPE*>(getPointer(o))) {
if (_ptr) _cnt = getCounter(o)->incr();
}
~SmartPointer() throw() {
virtual ~SmartPointer() throw() {
drop();
}
SmartPointer& operator=(const SmartPointer<TYPE>& o) throw() {
@@ -133,10 +135,10 @@ namespace mrw {
const TYPE& operator*() const throw() {
return *_ptr;
}
TYPE* const operator->() throw() {
TYPE* operator->() throw() {
return _ptr;
}
const TYPE* const operator->() const throw() {
const TYPE* operator->() const throw() {
return _ptr;
}
operator bool() throw() {

View File

@@ -304,6 +304,22 @@ template <typename T> std::string& operator<<(std::string& s, const T& o)
return s+=mrw::string(o);
}
/** @brief append any value to a string
@code
std::string()<<"length is: "<<i<<"mm";
@endcode
@param s the string, where o is appended
@param o the value to append to @c s
@pre \#include <mrw/string.hxx>
@pre T must support operator<< to a stream
*/
template <typename T> std::string operator<<(const std::string& s, const T& o)
throw(std::bad_exception) {
return s+=mrw::string(o);
}
/** @brief extract any value from a string
@code

View File

@@ -50,12 +50,50 @@
@pre \#include <mrw/vector.hxx>
*/
template <typename T, typename A>
std::vector<T, A> operator<<(std::vector<T, A> l, const T& o)
std::vector<T, A>& operator<<(std::vector<T, A>& l, const T& o)
throw(std::bad_exception) {
l.push_back(o);
return l;
}
/** @brief push a value to a constant vector
Makes a copy and returns the copy.
@code
std::vector<int>()<<1<<2<<3<<4<<5<<6<<7<<8;
@endcode
@param l a vector of values
@param o a value to be inserted into vector @c l
@pre \#include <mrw/vector.hxx>
*/
template <typename T, typename A>
std::vector<T, A> operator<<(const std::vector<T, A>& l, const T& o)
throw(std::bad_exception) {
std::vector<T, A> copy(l);
copy.push_back(o);
return ;
}
/* @brief push a char* to a vector of string
@code
std::vector<std::string> test;
test<<"Hello"<<"World";
@endcode
@param l a vector of string values (that can be constructed from char*)
@param o a value to be inserted into vector @c l
@pre \#include <mrw/vector.hxx> */
template <typename T, typename A>
std::vector<T, A>& operator<<(std::vector<T, A>& l,
const char *const o)
throw(std::bad_exception) {
l.push_back(T(o));
return l;
}
/** @brief extract the first value of a vector
@code

View File

@@ -79,7 +79,7 @@ namespace mrw {
if (res) {
/* Now put back any stripped dots. */
if (p==name) return static_cast<const char*>(res);
std::string add_dots('.', p-name);
std::string add_dots(p-name, '.');
return add_dots+=static_cast<const char*>(res);
}
return name;
@@ -97,22 +97,27 @@ mrw::StackTrace::StackTrace() throw(std::bad_exception) {
_trace.push_back(ba[i]);
}
// crash ...?
// # elif defined(__GNUG__)
// {
// # define PUSH(i) \
// (__builtin_frame_address(i)!=0 ? \
// (_trace.push_back(__builtin_return_address(i)), true) : false)
// PUSH(0) && PUSH(1) && PUSH(2) && PUSH(3) && PUSH(4) && PUSH(5) &&
// PUSH(6) && PUSH(7) && PUSH(8) && PUSH(9) && PUSH(10) && PUSH(11) &&
// PUSH(12) && PUSH(13) && PUSH(14) && PUSH(15) && PUSH(16) && PUSH(17)
// && PUSH(18) && PUSH(19) && PUSH(20) && PUSH(21) && PUSH(22) &&
// PUSH(23) && PUSH(24) && PUSH(25) && PUSH(26) && PUSH(27) && PUSH(28)
// && PUSH(29) && PUSH(30) && PUSH(31) && PUSH(32) && PUSH(33) &&
// PUSH(34) && PUSH(35) && PUSH(36) && PUSH(37) && PUSH(38) && PUSH(39)
// && PUSH(40) && PUSH(41) && PUSH(42) && PUSH(43) && PUSH(44) &&
// PUSH(45) && PUSH(46) && PUSH(47) && PUSH(48) && PUSH(49);
// # undef PUSH
// }
# elif defined(__GNUG__)
{
# define __MRW_PUSH(i) \
(__builtin_frame_address(i)!=0 && __builtin_return_address(i)!=0? \
(_trace.push_back(__builtin_return_address(i)), true) : false)
__MRW_PUSH(0) && __MRW_PUSH(1) && __MRW_PUSH(2) && __MRW_PUSH(3)
&& __MRW_PUSH(4) && __MRW_PUSH(5) && __MRW_PUSH(6) && __MRW_PUSH(7)
&& __MRW_PUSH(8) && __MRW_PUSH(9) && __MRW_PUSH(10) && __MRW_PUSH(11)
&& __MRW_PUSH(12) && __MRW_PUSH(13) && __MRW_PUSH(14) && __MRW_PUSH(15)
&& __MRW_PUSH(16) && __MRW_PUSH(17) && __MRW_PUSH(18) && __MRW_PUSH(19)
&& __MRW_PUSH(20) && __MRW_PUSH(21) && __MRW_PUSH(22) && __MRW_PUSH(23)
&& __MRW_PUSH(24) && __MRW_PUSH(25) && __MRW_PUSH(26) && __MRW_PUSH(27)
&& __MRW_PUSH(28) && __MRW_PUSH(29) && __MRW_PUSH(30) && __MRW_PUSH(31)
&& __MRW_PUSH(32) && __MRW_PUSH(33) && __MRW_PUSH(34) && __MRW_PUSH(35)
&& __MRW_PUSH(36) && __MRW_PUSH(37) && __MRW_PUSH(38) && __MRW_PUSH(39)
&& __MRW_PUSH(40) && __MRW_PUSH(41) && __MRW_PUSH(42) && __MRW_PUSH(43)
&& __MRW_PUSH(44) && __MRW_PUSH(45) && __MRW_PUSH(46) && __MRW_PUSH(47)
&& __MRW_PUSH(48) && __MRW_PUSH(49);
# undef __MRW_PUSH
}
# else
# warning "You need GNU gcc or GNU glibc to be able to use mrw::StackTrace"
# endif
@@ -161,11 +166,10 @@ mrw::StackTrace::~StackTrace() throw() {
//----------------------------------------------------------------------------
mrw::StackTrace::operator std::string() const throw(std::bad_exception) {
std::stringstream s;
bool first(true);
unsigned int fusz(0), adsz(0); //lisz(0), fisz(0)
std::string::size_type fusz(0), adsz(0); //lisz(0), fisz(0)
std::list<CodePos> l;
for (AddressTrace::const_reverse_iterator it(_trace.rbegin());
it!=_trace.rend(); ++it, first=false) {
it!=_trace.rend(); ++it) {
CodePos c(translate(*it));
if (((std::stringstream&)(std::stringstream()<<c.address)).str().size()
> adsz)
@@ -175,8 +179,8 @@ mrw::StackTrace::operator std::string() const throw(std::bad_exception) {
l.push_back(c);
}
for (std::list<CodePos>::iterator it(l.begin()); it!=l.end(); ++it)
s<<'['<<std::setw(adsz)<<it->address<<"] "
<<it->function<<std::setw(fusz-it->function.size()+1)<<' '
s<<'['<<std::setw((int)adsz)<<it->address<<"] "
<<it->function<<std::setw(int(fusz-it->function.size()+1))<<' '
<<it->file<<':'<<it->line<<std::endl;
return s.str();
}
@@ -343,7 +347,7 @@ mrw::StackTrace::BinFiles mrw::StackTrace::filename()
// added check: no names in brackets: [lib], because there are
// [heap], [stack] and [vdso] that cannot be loaded
// question: should only files with ending '.so' be loaded?
if (lib.size() && lib[0]!='[' && lib[lib.size()-1]!=']' && addr>0)
if (lib.size() && lib[0]!='[' && lib[lib.size()-1]!=']' && addr!=0)
res<<BinFiles::value_type(lib, addr);
}
} catch (...) {} // ignore non matching lines