#1024. Thank you, Thomas for this very useful contribution.

This commit is contained in:
Robin Mills 2015-01-11 17:24:13 +00:00
parent ec79072f7d
commit faf51171d0
12 changed files with 383 additions and 113 deletions

View File

@ -49,6 +49,9 @@
/* Define to 1 if you have the <libintl.h> header file. */
#undef HAVE_LIBINTL_H
/* Define to 1 if you have the <regex.h> header file. */
#define HAVE_REGEX 1
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#undef HAVE_MALLOC

View File

@ -65,7 +65,7 @@ endif
CXXCPP = @CXXCPP@
# Preprocessor flags
CPPFLAGS = -I../src -I../include/ -I../include/exiv2 @CPPFLAGS@ -DEXV_LOCALEDIR=\"$(localedir)\"
CPPFLAGS = -I../src -I../include/ -I../include/exiv2 @CPPFLAGS@ -I/usr/include -DEXV_LOCALEDIR=\"$(localedir)\"
ifeq ($(COMMERCIAL_VERSION),yes)
CPPFLAGS += -DEXV_COMMERCIAL_VERSION=1
endif

View File

@ -56,7 +56,7 @@ AM_ICONV
# Checks for header files.
# ---------------------------------------------------------------------------
AC_HEADER_STDC
AC_CHECK_HEADERS([libintl.h locale.h malloc.h stdint.h stdlib.h string.h unistd.h sys/mman.h utime.h])
AC_CHECK_HEADERS([libintl.h locale.h malloc.h stdint.h stdlib.h string.h unistd.h sys/mman.h utime.h regex.h])
# ---------------------------------------------------------------------------
# Checks for typedefs, structures, and compiler characteristics.

View File

@ -68,4 +68,6 @@
#include "xmp.hpp"
#include "xmpsidecar.hpp"
#include <vector>
#endif // #ifndef EXIV2_HPP_

View File

@ -17,6 +17,10 @@
// stdint.h was introduced with DevStudio 2010
#define EXV_HAVE_STDINT_H 1
#endif
#if _MSC_VER >= 1900
#define MSDEV_2014 1
#elif _MSC_VER >= 1800
#define MSDEV_2013 1
#if _MSC_VER >= 1700
#define MSDEV_2012 1
#elif _MSC_VER >= 1600
@ -33,6 +37,9 @@
#define HAVE_NTOHLL 1
#endif
/* Define to 1 if you have the <regex.h> header file. */
// #define EXV_HAVE_REGEX 1
/* Define to 1 if you have the <process.h> header file. */
#define EXV_HAVE_PROCESS_H 1

View File

@ -17,7 +17,11 @@
// stdint.h was introduced with DevStudio 2010
#define EXV_HAVE_STDINT_H 1
#endif
#if _MSC_VER >= 1700
#if _MSC_VER >= 1900
#define MSDEV_2014 1
#elif _MSC_VER >= 1800
#define MSDEV_2013 1
#elif _MSC_VER >= 1700
#define MSDEV_2012 1
#elif _MSC_VER >= 1600
#define MSDEV_2010 1
@ -33,6 +37,9 @@
#define HAVE_NTOHLL 1
#endif
/* Define to 1 if you have the <regex.h> header file. */
// #define EXV_HAVE_REGEX 1
/* Define to 1 if you have the <process.h> header file. */
#define EXV_HAVE_PROCESS_H 1

View File

@ -36,6 +36,13 @@
// included header files
// + standard includes
#include <string>
#include <vector>
#if EXV_HAVE_REGEX
#include <regex.h>
typedef std::vector<regex_t> exv_grep_keys_t ;
#else
typedef std::vector<std::string> exv_grep_keys_t ;
#endif
/*!
@brief %Exiv2 MAJOR version number of the library used at compile-time.
@ -180,7 +187,7 @@ namespace Exiv2 {
// dumpLibraryInfo is general purpose and not in the Exiv2 namespace
// used by exiv2 test suite to inspect libraries loaded at run-time
EXIV2API void dumpLibraryInfo(std::ostream& os);
EXIV2API void dumpLibraryInfo(std::ostream& os,const exv_grep_keys_t& keys);
#endif // VERSION_HPP_

View File

@ -559,10 +559,14 @@ namespace Action {
bool Print::grepTag(const std::string& key)
{
bool result=Params::instance().keys_.empty();
if (!result)
for (Params::Keys::const_iterator k = Params::instance().keys_.begin();
!result && k != Params::instance().keys_.end(); ++k) {
result = key.find(*k) != std::string::npos;
for (Params::Keys::const_iterator k = Params::instance().keys_.begin();
!result && k != Params::instance().keys_.end(); ++k)
{
#if EXV_HAVE_REGEX
result = regexec( &(*k), key.c_str(), 0, NULL, REG_NOTBOL | REG_NOTEOL) == 0 ;
#else
result = key.find(*k) != std::string::npos;
#endif
}
return result ;
}

View File

@ -3,7 +3,7 @@
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
.TH EXIV2 1 "Nov 11, 2012"
.TH EXIV2 1 "Jan 10, 2015"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
@ -129,7 +129,7 @@ Show the program version and exit.
When \fB\-V\fP is combined with \fB\-v\fP (Verbose version), build information
is printed to standard output along with a list of shared libraries which
have been loaded into memory. Verbose version is supported on Windows
(both MSVC and Cygwin builds), MacOSX and Linux and is provided
(MSVC, Cygwin and MinGW builds), MacOSX and Linux and is provided
for test and debugging.
.TP
.B \-v
@ -152,8 +152,21 @@ Show large binary values (default is to suppress them).
Show unknown tags (default is to suppress tags which don't have a name).
.TP
.B \-g \fIkey\fP
Only output info for this Exiv2 key (grep). Multiple \fB\-g\fP options
can be used to grep info for several keys.
Only output info for this Exiv2 key (grep).
.br
Multiple \fB\-g\fP options
can be used to grep info for several keys. This option uses the system
regular expression engine: see man 3 regex. Platforms which do not support
regex use key for a substring match. You can determine the availability of regex
using the command: exiv2 -v -V -g have_regex
.nf
exiv2 \-g Date \-pt R.jpg
Exif.Image.DateTime Ascii 20 2012:08:07 16:01:05
Exif.Photo.DateTimeOriginal Ascii 20 2011:09:18 16:25:48
Exif.Photo.DateTimeDigitized Ascii 20 2011:09:18 16:25:48
.fi
.TP
.B \-n \fIenc\fP
Charset to use to decode Exif Unicode user comments. \fIenc\fP is
@ -294,19 +307,6 @@ with the 'print' option \fB\-pp\fP.
X : Extract metadata to an XMP sidecar file <file>.xmp. The remaining
extract targets determine what metadata to extract to the sidecar
file. Possible are Exif, IPTC and XMP and the default is all of these.
.TP
.B \-g \fImatch\fP
Report only keys which match. This is sub-string match and not grep, although
the \fB\-g\fP option is intended to help you remember this as grep. The match is case-sensitive.
.br
.sp 1
.nf
exiv2 \-g Date \-pt R.jpg
Exif.Image.DateTime Ascii 20 2012:08:07 16:01:05
Exif.Photo.DateTimeOriginal Ascii 20 2011:09:18 16:25:48
Exif.Photo.DateTimeDigitized Ascii 20 2011:09:18 16:25:48
.fi
.sp 1
.TP
.B \-r \fIfmt\fP

View File

@ -48,6 +48,10 @@ EXIV2_RCSID("@(#) $Id$")
#include <cassert>
#include <cctype>
#if EXV_HAVE_REGEX
#include <regex.h>
#endif
#if defined(__MINGW32__) || defined(__MINGW64__)
# ifndef __MINGW__
# define __MINGW__
@ -149,7 +153,7 @@ int main(int argc, char* const argv[])
return 0;
}
if (params.version_) {
params.version(params.verbose_);
params.version(params.verbose_);
return 0;
}
@ -210,8 +214,9 @@ void Params::version(bool verbose,std::ostream& os) const
{
bool b64 = sizeof(void*)==8;
const char* sBuild = b64 ? "(64 bit build)" : "(32 bit build)" ;
os << EXV_PACKAGE_STRING << " " << Exiv2::versionNumberHexString() << " " << sBuild << "\n"
<< _("Copyright (C) 2004-2013 Andreas Huggel.\n")
os << EXV_PACKAGE_STRING << " " << Exiv2::versionNumberHexString() << " " << sBuild << "\n";
if ( Params::instance().keys_.empty() ) {
os << _("Copyright (C) 2004-2013 Andreas Huggel.\n")
<< "\n"
<< _("This program is free software; you can redistribute it and/or\n"
"modify it under the terms of the GNU General Public License\n"
@ -227,8 +232,9 @@ void Params::version(bool verbose,std::ostream& os) const
"License along with this program; if not, write to the Free\n"
"Software Foundation, Inc., 51 Franklin Street, Fifth Floor,\n"
"Boston, MA 02110-1301 USA\n");
}
if ( verbose ) dumpLibraryInfo(os);
if ( verbose ) dumpLibraryInfo(os,Params::instance().keys_);
}
void Params::usage(std::ostream& os) const
@ -352,7 +358,7 @@ int Params::option(int opt, const std::string& optarg, int optopt)
case 'u': unknown_ = false; break;
case 'f': force_ = true; fileExistsPolicy_ = overwritePolicy; break;
case 'F': force_ = true; fileExistsPolicy_ = renamePolicy; break;
case 'g': keys_.push_back(optarg); printMode_ = pmList; break;
case 'g': rc = evalKey(optarg); printMode_ = pmList; break;
case 'n': charset_ = optarg; break;
case 'r': rc = evalRename(opt, optarg); break;
case 't': rc = evalRename(opt, optarg); break;
@ -410,6 +416,37 @@ int Params::setLogLevel(const std::string& optarg)
return rc;
} // Params::setLogLevel
int Params::evalKey( const std::string& optarg)
{
int result=0;
#if EXV_HAVE_REGEX
// try to compile a reg-exp from the input argument and store it in the vector
const size_t i = keys_.size();
keys_.resize(i + 1);
regex_t *pRegex = &keys_[i];
int errcode = regcomp( pRegex, optarg.c_str(), REG_NOSUB);
// there was an error compiling the regexp
if( errcode ) {
size_t length = regerror (errcode, pRegex, NULL, 0);
char *buffer = new char[ length];
regerror (errcode, pRegex, buffer, length);
std::cerr << progname()
<< ": " << _("Option") << " -g: "
<< _("Invalid regexp") << " \"" << optarg << "\": " << buffer << "\n";
// free the memory and drop the regexp
delete[] buffer;
regfree( pRegex);
keys_.resize(i);
result=1;
}
#else
keys_.push_back(optarg);
#endif
return result;
} // Params::evalKey
int Params::evalRename(int opt, const std::string& optarg)
{
int rc = 0;
@ -1036,29 +1073,29 @@ namespace {
catch (const Exiv2::AnyError& error) {
std::cerr << _("-M option") << " " << error << "\n";
return false;
}
}
} // parseCmdLines
#if defined(_MSC_VER) || defined(__MINGW__)
#if defined(_MSC_VER) || defined(__MINGW__)
static std::string formatArg(const char* arg)
{
std::string result = "";
char b = ' ' ;
char e = '\\'; std::string E = std::string("\\");
char q = '\''; std::string Q = std::string("'" );
bool qt = false;
char* a = (char*) arg;
while ( *a ) {
if ( *a == b || *a == e || *a == q ) qt = true;
if ( *a == q ) result += E;
if ( *a == e ) result += E;
result += std::string(a,1);
a++ ;
}
if (qt) result = Q + result + Q;
std::string result = "";
char b = ' ' ;
char e = '\\'; std::string E = std::string("\\");
char q = '\''; std::string Q = std::string("'" );
bool qt = false;
char* a = (char*) arg;
while ( *a ) {
if ( *a == b || *a == e || *a == q ) qt = true;
if ( *a == q ) result += E;
if ( *a == e ) result += E;
result += std::string(a,1);
a++ ;
}
if (qt) result = Q + result + Q;
return result;
}
return result;
}
#endif
bool parseLine(ModifyCmd& modifyCmd, const std::string& line, int num)
@ -1076,9 +1113,9 @@ namespace {
if ( cmdStart == std::string::npos
|| cmdEnd == std::string::npos
|| keyStart == std::string::npos) {
std::string cmdLine ;
#if defined(_MSC_VER) || defined(__MINGW__)
for ( int i = 1 ; i < __argc ; i++ ) { cmdLine += std::string(" ") + formatArg(__argv[i]) ; }
std::string cmdLine ;
#if defined(_MSC_VER) || defined(__MINGW__)
for ( int i = 1 ; i < __argc ; i++ ) { cmdLine += std::string(" ") + formatArg(__argv[i]) ; }
#endif
throw Exiv2::Error(1, Exiv2::toString(num)
+ ": " + _("Invalid command line:") + cmdLine);

View File

@ -40,6 +40,10 @@
#include <set>
#include <iostream>
#if EXV_HAVE_REGEX
#include <regex.h>
#endif
// *****************************************************************************
// class definitions
@ -125,7 +129,7 @@ public:
//! Container for preview image numbers
typedef std::set<int> PreviewNumbers;
//! Container for keys
typedef std::vector<std::string> Keys;
typedef exv_grep_keys_t Keys;
/*!
@brief Controls all access to the global Params instance.
@ -261,6 +265,7 @@ private:
//! @name Helpers
//@{
int setLogLevel(const std::string& optarg);
int evalKey( const std::string& optarg);
int evalRename(int opt, const std::string& optarg);
int evalAdjust(const std::string& optarg);
int evalYodAdjust(const Yod& yod, const std::string& optarg);

View File

@ -62,8 +62,9 @@ EXIV2_RCSID("@(#) $Id$")
// + standard includes
#include <iomanip>
#include <sstream>
#include <string>
#include <vector>
#include <stdio.h>
namespace Exiv2 {
int versionNumber()
@ -97,9 +98,6 @@ namespace Exiv2 {
}
} // namespace Exiv2
#include <string>
#include <vector>
#include <stdio.h>
using namespace std;
typedef vector<string> string_v;
typedef string_v::iterator string_i;
@ -146,49 +144,73 @@ typedef string_v::iterator string_i;
#endif
#endif
EXIV2API void dumpLibraryInfo(std::ostream& os)
static void output(std::ostream& os,const exv_grep_keys_t& keys,const char* name,const std::string& value)
{
string_v libs; // libs[0] == executable
int bits = 8*sizeof(void*);
#if defined(_DEBUG) || defined(DEBUG)
int debug=1;
bool bPrint = keys.empty();
for( exv_grep_keys_t::const_iterator k = keys.begin();
!bPrint && k != keys.end() ; ++k
) {
#if EXV_HAVE_REGEX
bPrint = ( 0 == regexec( &(*k), name , 0, NULL, REG_NOTBOL | REG_NOTEOL)
|| 0 == regexec( &(*k), value.c_str(), 0, NULL, REG_NOTBOL | REG_NOTEOL)
);
#else
int debug=0;
bPrint = std::string(name).find(*k) != std::string::npos || value.find(*k) != std::string::npos;
#endif
}
if ( bPrint ) os << name << "=" << value << endl;
}
static void output(std::ostream& os,const exv_grep_keys_t& keys,const char* name,int value)
{
std::ostringstream stringStream;
stringStream << value;
output(os,keys,name,stringStream.str());
}
void dumpLibraryInfo(std::ostream& os,const exv_grep_keys_t& keys)
{
string_v libs; // libs[0] == executable
int bits = 8*sizeof(void*);
#if defined(_DEBUG) || defined(DEBUG)
int debug=1;
#else
int debug=0;
#endif
#if defined(DLL_EXPORT) || defined(EXV_HAVE_DLL)
int dll=1;
#if defined(DLL_EXPORT) || defined(EXV_HAVE_DLL)
int dll=1;
#else
int dll=0;
int dll=0;
#endif
const char* compiler =
#if defined(_MSC_VER)
"MSVC" ;
const char* compiler =
#if defined(_MSC_VER)
"MSVC" ;
#ifndef __VERSION__
char version[20];
sprintf(version,"%d.%02d",(_MSC_VER-600)/100,_MSC_VER%100);
char version[20];
sprintf(version,"%d.%02d",(_MSC_VER-600)/100,_MSC_VER%100);
#define __VERSION__ version
#endif
#elif defined(__clang__)
"Clang" ;
"Clang" ;
#elif defined(__GNUG__)
"G++" ;
"G++" ;
#elif defined(__GNUC__)
"GCC" ;
"GCC" ;
#elif defined(__SUNPRO_CC)
"CC (oracle)";
"CC (oracle)";
#elif defined (__SUNPRO_C)
"cc (oracle)";
"cc (oracle)";
#else
"unknown" ;
"unknown" ;
#endif
#if defined(__SUNPRO_CC) || defined (__SUNPRO_C)
#define __oracle__
#define __oracle__
#endif
#ifndef __VERSION__
@ -199,23 +221,170 @@ EXIV2API void dumpLibraryInfo(std::ostream& os)
#endif
#endif
const char* platform =
const char* platform =
#if defined(__CYGWIN__)
"cygwin";
"cygwin";
#elif defined(_MSC_VER)
"windows";
"windows";
#elif defined(__APPLE__)
"apple";
"apple";
#elif defined(__MINGW64__)
"mingw64";
"mingw64";
#elif defined(__MINGW32__)
"mingw32";
"mingw32";
#elif defined(__linux__)
"linux";
"linux";
#else
"unknown";
"unknown";
#endif
int have_regex =0;
int have_gmtime_r =0;
int have_inttypes =0;
int have_libintl =0;
int have_lensdata =0;
int have_iconv =0;
int have_memory =0;
int have_memset =0;
int have_lstat =0;
int have_stdbool =0;
int have_stdint =0;
int have_stdlib =0;
int have_strlib =0;
int have_strchr =0;
int have_strerror =0;
int have_strerror_r =0;
int have_strings_h =0;
int have_strtol =0;
int have_mmap =0;
int have_munmap =0;
int have_sys_stat =0;
int have_timegm =0;
int have_unistd_h =0;
int have_sys_mman =0;
int have_libz =0;
int have_xmptoolkit =0;
int have_bool =0;
int have_strings =0;
int have_sys_types =0;
int have_unistd =0;
#if EXV_HAVE_DECL_STRERROR_R
have_strerror_r=1;
#endif
#if EXV_HAVE_GMTIME_R
have_gmtime_r=1;
#endif
#if EXV_HAVE_INTTYPES_H
have_inttypes=1;
#endif
#if EXV_HAVE_LIBINTL_H
have_libintl=1;
#endif
#if EXV_HAVE_LENSDATA
have_lensdata=1;
#endif
#if EXV_HAVE_ICONV
have_iconv=1;
#endif
#if EXV_HAVE_LIBINTL_H
have_libintl=1;
#endif
#if EXV_HAVE_REGEX
have_regex=1;
#endif
#if EXV_HAVE_MEMORY_H
have_memory=1;
#endif
#if EXV_HAVE_MEMSET
have_memset=1;
#endif
#if EXV_HAVE_LSTAT
have_lstat=1;
#endif
#if EXV_HAVE_STDBOOL_H
have_stdbool=1;
#endif
#if EXV_HAVE_STDINT_H
have_stdint=1;
#endif
#if EXV_HAVE_STDLIB_H
have_stdlib=1;
#endif
#if EXV_HAVE_STRCHR
have_strchr=1;
#endif
#if EXV_HAVE_STRERROR
have_strerror=1;
#endif
#if EXV_HAVE_STRERROR_R
have_strerror_r=1;
#endif
#if EXV_HAVE_STRINGS_H
have_strings=1;
#endif
#if EXV_HAVE_STRTOL
have_strtol=1;
#endif
#if EXV_HAVE_MMAP
have_mmap=1;
#endif
#if EXV_HAVE_MUNMAP
have_munmap=1;
#endif
#if EXV_HAVE_SYS_STAT_H
have_sys_stat=1;
#endif
#if EXV_HAVE_SYS_TYPES_H
have_sys_types=1;
#endif
#if EXV_HAVE_TIMEGM
have_timegm=1;
#endif
#if EXV_HAVE_UNISTD_H
have_unistd=1;
#endif
#if EXV_HAVE_SYS_MMAN_H
have_sys_mman=1;
#endif
#if HAVE_LIBZ
have_libz=1;
#endif
#if EXV_HAVE_XMP_TOOLKIT
have_xmptoolkit=1;
#endif
#if EXV_HAVE__BOOL
have_bool=1;
#endif
#if defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW__)
// enumerate loaded libraries and determine path to executable
HMODULE handles[200];
@ -261,34 +430,63 @@ EXIV2API void dumpLibraryInfo(std::ostream& os)
pl = pl->next;
}
#endif
os << "exiv2=" << Exiv2::versionString() << endl;
os << "platform=" << platform << endl;
os << "compiler=" << compiler << endl;
os << "bits=" << bits << endl;
os << "dll=" << dll << endl;
os << "debug=" << debug << endl;
os << "version=" << __VERSION__ << endl;
os << "date=" << __DATE__ << endl;
os << "time=" << __TIME__ << endl;
os << "svn=" << SVN_VERSION << endl;
os << "ssh=" << EXV_USE_SSH << endl;
output(os,keys,"exiv2",Exiv2::versionString());
output(os,keys,"platform" , platform );
output(os,keys,"compiler" , compiler );
output(os,keys,"bits" , bits );
output(os,keys,"dll" , dll );
output(os,keys,"debug" , debug );
output(os,keys,"version" , __VERSION__);
output(os,keys,"date" , __DATE__ );
output(os,keys,"time" , __TIME__ );
output(os,keys,"svn" , SVN_VERSION);
output(os,keys,"ssh" , EXV_USE_SSH);
#if EXV_USE_CURL == 1
curl_version_info_data* vinfo = curl_version_info(CURLVERSION_NOW);
os << "curlversion=" << vinfo->version << endl;
os << "curlprotocols=";
for (int i = 0; vinfo->protocols[i]; i++)
os << vinfo->protocols[i] << " ";
os << endl;
#else
os << "curl=" << EXV_USE_CURL << endl;
#endif
os << "id=" << "$Id$" << endl;
if ( libs.begin() != libs.end() ) {
os << "executable=" << *libs.begin() << endl;
for ( string_i lib = libs.begin()+1 ; lib != libs.end() ; lib++ )
os << "library=" << *lib << endl;
std::string curl_protocols;
curl_version_info_data* vinfo = curl_version_info(CURLVERSION_NOW);
for (int i = 0; vinfo->protocols[i]; i++) {
curl_protocols += vinfo->protocols[i];
curl_protocols += " " ;
}
output(os,keys,"curlprotocols=" ,curl_protocols);
#else
output(os,keys,"curl=" , EXV_USE_CURL);
#endif
output(os,keys,"id" , "$Id$");
if ( libs.begin() != libs.end() ) {
output(os,keys,"executable" ,*libs.begin());
for ( string_i lib = libs.begin()+1 ; lib != libs.end() ; lib++ )
output(os,keys,"library",*lib);
}
output(os,keys,"have_regex" ,have_regex );
output(os,keys,"have_strerror_r",have_strerror_r);
output(os,keys,"have_gmtime_r" ,have_gmtime_r );
output(os,keys,"have_inttypes" ,have_inttypes );
output(os,keys,"have_libintl" ,have_libintl );
output(os,keys,"have_lensdata" ,have_lensdata );
output(os,keys,"have_iconv" ,have_iconv );
output(os,keys,"have_memory" ,have_memory );
output(os,keys,"have_memset" ,have_memset );
output(os,keys,"have_lstat" ,have_lstat );
output(os,keys,"have_stdbool" ,have_stdbool );
output(os,keys,"have_stdint" ,have_stdint );
output(os,keys,"have_stdlib" ,have_stdlib );
output(os,keys,"have_strlib" ,have_strlib );
output(os,keys,"have_strchr" ,have_strchr );
output(os,keys,"have_strerror" ,have_strerror );
output(os,keys,"have_strerror_r",have_strerror_r);
output(os,keys,"have_strings_h" ,have_strings_h );
output(os,keys,"have_strtol" ,have_strtol );
output(os,keys,"have_mmap" ,have_mmap );
output(os,keys,"have_munmap" ,have_munmap );
output(os,keys,"have_sys_stat" ,have_sys_stat );
output(os,keys,"have_timegm" ,have_timegm );
output(os,keys,"have_unistd_h" ,have_unistd_h );
output(os,keys,"have_sys_mman" ,have_sys_mman );
output(os,keys,"have_libz" ,have_libz );
output(os,keys,"have_xmptoolkit",have_xmptoolkit);
output(os,keys,"have_bool" ,have_bool );
#if defined(__linux__)
dlclose(ph);