//////////////////////////////////////////////////////////////////////////////// // main_dn.cpp // Implmentation for s11nconvert utility, to convert data between the various // Serializers. // Author: stephan@s11n.net // License: Public Domain //////////////////////////////////////////////////////////////////////////////// #include #include #include // auto_ptr #ifndef WIN32 # include // isatty() #endif // !WIN32 #include // CERR #include // s11nlite framework #include // utility code for s11n::io #include // s11n_CONFIG_HAVE_ZFSTREAM #include "argv_parser.hpp" #if s11n_CONFIG_HAVE_ZFSTREAM # include #endif #if s11n_CONFIG_ENABLE_PLUGINS # include #endif // DLLS_WORKIE is a temporary workaround for no DLL support in 1.1 #define DLLS_WORKIE (0) bool s11nc_verbose = false; #define VERBOSE if( s11nc_verbose ) CERR void show_version_info() { std::cout << s11n_S11N_LIBRARY_VERSION << "\n"; if( s11nc_verbose) { std::cout << "Linked against s11n version " << s11n::library_version() << "\n" << "s11nconvert is a tool to convert data between the formats supported by libs11n.\n" << "License: " << s11n_PACKAGE_LICENSE << "\n" << "This software comes with NO WARRANTY of any type.\n" << "Find out more about s11n at http://s11n.net" << std::endl; } } void show_help() { show_version_info(); std::ostream & os = std::cout; os << "\nCommand-line options:\n\n"; #define HOP(A,H) os << "\t" << A << ":\n\t\t" << H << "\n"; HOP("-?, --help", "Shows help text on stdout and exits with code 0." ); HOP("-f,--file FILENAME", "Sets input file name. The name '-' means stdin." ); HOP("-K, --known-serializers", "Listed known/loaded Serializers (format handlers)."); HOP("-o, --output FILENAME", "Sets output filename. The name '-' means stdout." ); HOP("-s, --format SERIALIZER", "Sets the output Serializer (i.e., output format)." ); HOP("-S SERIALIZER", "Forces the specified input Serializer to be used (very rarely needed)." ); HOP("-v, --verbose", "Enables verbose mode: additional info will go to stderr." ); HOP("-V, --version", "Shows version number on stdout and exits with code 0. Use -v to output more info." ); #if s11n_CONFIG_ENABLE_PLUGINS HOP("-dl DLL", "Opens DLL, which may be an absolute path or a name findable using the s11n::plugin::path(). Causes app to exit with an error if DLL is not found or cannot be opened." ); HOP("-DL DLL", "Identical to -dl except that a failed DLL load is not fatal." ); #endif #if s11n_CONFIG_HAVE_ZFSTREAM HOP("-z","Compress output files with gzip. Works only on files, not stdout." ); HOP("-bz","As for the -z option, but applies to bzip2 compression. -z and -bz may not be used together." ); #endif // zfstream? #undef HOP os << "\nAll arguments may be in any of these forms:\n" << "\t-ARG VALUE (an empty value is assumed to be a boolean 1)\n" << "\t-ARG=VALUE (quote the value if it contains spaces)\n" << "The number of leading dashes for an argument is absolutely irrelevant. " << "When an argument is specified more than once, only the last one set takes effect.\n"; os << "\nSeveral options from s11nconvert 1.0.x are currently not available, " << "but will be re-added eventually.\n" << "\nYou can get more detailed help in the s11nconvert man page.\n"; os << std::endl; } enum { // Reminder: these entries have explicit values so that // we can publish them in the man page. If this enum // changes, UPDATE THE MAN PAGE. ErrorNoOutputSerializer = 1, ErrorFileNotFound = 2, ErrorNoInputFile = 3, ErrorLoadNodeFailed = 4, ErrorSaving = 5, ErrorForcedSerializer = 6, ErrorUsageError = 7, ErrorNoOutputSerializers = 8, ErrorException = 9 }; int load_dlls( int argc, char **argv ) { if( argc < 2 ) return 0; std::string arg; std::string foo; int mode = 0; // 1 == tolerant, 2 == intolerant for( int i = 1; i < argc; ++i ) { mode = 0; arg = argv[i]; if( "-DL" == arg ) mode = 1; // tolerant else if( "-dl" == arg ) mode = 2; // intolerant else continue; #if ! s11n_CONFIG_ENABLE_PLUGINS throw std::runtime_error( "-dl/-DL are not supported because your libs11n was built without plugins support." ); #else if( argc == ++i ) { throw std::runtime_error( "-dl/-DL parameters require a following argument (filename or DLL class name)" ); } arg = argv[i]; foo = s11n::plugin::open( arg ); if( foo.empty() ) { std::ostringstream errmsg; errmsg << "DLL error: '"< SerList; SerList serlist; s11n::io::serializer_list( serlist, !s11nc_verbose ); SerList::const_iterator cit = serlist.begin(), cet = serlist.end(); for( ; cet != cit; ++cit ) { known_ser += (*cit) + (s11nc_verbose ? "\n" : " "); } if( known_ser.empty() ) { ERR << "No data formats loaded!\n" << "This means we couldn't find any built-in Serializers, " << "which is probably inidicitive of a problem in your local s11n installation.\n" << "Make sure that your s11nconvert is not linking against an older, internally incompatible libs11n " << "by using 'ldd s11nconvert'.\n" ; return ErrorNoOutputSerializers; } if( NTR::is_set( argn, "known-serializers" ) || NTR::is_set( argn, "K" ) ) { std::cout << known_ser << std::endl; return 0; } //////////////////////////////////////////////////////////////////////// if( NTR::is_set( argn, "version" ) || NTR::is_set( argn, "V" ) ) { show_version_info(); return 0; } if( NTR::is_set( argn, "help" ) || NTR::is_set( argn, "?" ) ) { show_help(); return 0; } #if s11n_CONFIG_HAVE_ZFSTREAM if( NTR::is_set( argn, "z" ) && NTR::is_set( argn, "bz" ) ) { ERR << "-z and -bz may not be used together." << std::endl; return ErrorUsageError; } #endif // s11n_CONFIG_HAVE_ZFSTREAM std::string fmt = NTR::get( argn, "s", NTR::get( argn, "format", std::string() ) ); if( fmt.empty() ) { ERR << "No output format (serializer) specified. " << "Try using [-s or --format] with one of:\n" << known_ser << "\n" << "Use -? or --help to see the full list of options.\n"; return ErrorNoOutputSerializer; } typedef std::auto_ptr APSER; APSER ser = APSER( s11nlite::create_serializer( fmt ) ); if( ! ser.get() ) { ERR << "No Serializer found for name '"< NAP; NAP innode; std::string forcedinser = NTR::get( argn, "S", std::string() ); if( ! forcedinser.empty() ) { VERBOSE << "Forcing input serializer: " << forcedinser << "\n"; s11nlite::serializer_interface * forceser = s11nlite::create_serializer( forcedinser ); if( 0 == forceser ) { ERR << "Could not load forced input serializer '"<deserialize( ifname ) : forceser->deserialize( *is ) ); } else { innode = NAP( use_infile ? s11nlite::load_node( ifname ) : s11nlite::load_node( *is ) ); } if( ! innode.get() ) { ERR << "Error loading node tree from input stream!\n"; return ErrorLoadNodeFailed; } // And FINALLY... we get down to the real work... // these couple lines almost now don't seem worth all the hassle ;) bool workie = use_ofile ? ser->serialize( *innode, ofname ) : ser->serialize( *innode, *os ); if( ! workie ) { ERR << "Error saving output!\n"; return ErrorSaving; } return 0; #undef ERR }; int main( int argc, char **argv ) { try { return do_everything( argc, argv ); } catch( std::exception const & ex ) { CERR << "Exception caught: " << ex.what() << '\n'; return ErrorException; } return 0; }