37#include <openbabel/babelconfig.h>
44#define strncasecmp _strnicmp
49#include <openbabel/obconversion.h>
50#include <openbabel/plugin.h>
53using namespace OpenBabel;
55void DoOption(
const char* p, OBConversion& Conv, OBConversion::Option_type typ,
56 int& arg,
int argc,
char* argv[]);
61static char* program_name;
63int main(
int argc,
char* argv[]) {
64 OBConversion Conv(&cin, &cout);
66 OBFormat* pInFormat =
nullptr;
67 OBFormat* pOutFormat =
nullptr;
69 vector<string> FileList, OutputFileList;
70 string OutputFileName;
73 bool gotInType =
false, gotOutType =
false;
74 bool SplitOrBatch =
false;
85 string::size_type pos;
87 pos = pn.find(
".exe");
88 if (pos != string::npos) argv[0][pos] =
'\0';
90 pos = pn.find_last_of(
"/\\");
91 if (pos == string::npos)
92 program_name = argv[0];
94 program_name = argv[0] + pos + 1;
98 for (arg = 1; arg < argc; ++arg) {
100 if (argv[arg][0] ==
'-') {
101 char opchar[2] =
"?";
102 opchar[0] = argv[arg][1];
105 cout << program_name <<
": part of OpenMD " << OPENMD_VERSION_MAJOR
106 <<
"." << OPENMD_VERSION_MINOR <<
"." << OPENMD_VERSION_TINY
107 <<
" and Open Babel " << BABEL_VERSION <<
" -- " << __DATE__
108 <<
" -- " << __TIME__ << endl;
114 iext = argv[arg] + 2;
118 if (strncasecmp(iext,
"MIME", 4) == 0) {
121 pInFormat = Conv.FormatFromMIME(iext);
125 pInFormat = Conv.FindFormat(iext);
127 if (pInFormat == NULL) {
128 cerr << program_name <<
": cannot read input format!" << endl;
136 oext = argv[arg] + 2;
140 if (strncasecmp(oext,
"MIME", 4) == 0) {
143 pOutFormat = Conv.FormatFromMIME(oext);
145 pOutFormat = Conv.FindFormat(oext);
147 if (pOutFormat ==
nullptr) {
148 cerr << program_name <<
": cannot write output format!" << endl;
155 OutputFileName = argv[arg] + 2;
156 if (OutputFileName.empty())
163 const char* param =
nullptr;
164 if (argc > arg + 1) param = argv[arg + 2];
170 if ((OBPlugin::GetPlugin(
"plugins", argv[arg + 1]) &&
171 (plugin = OBPlugin::GetPlugin(argv[arg + 1], param))) ||
172 (plugin = OBPlugin::GetPlugin(
nullptr, argv[arg + 1]))) {
175 plugin->Display(txt,
"verbose", argv[arg + 1]);
176 cout <<
"One of the " << plugin->TypeID() <<
'\n' << txt << endl;
181 OBPlugin::List(argv[arg + 1], param);
186 if (isalnum(argv[arg][2]) || arg == argc - 2) {
187 if (strncasecmp(argv[arg] + 2,
"all", 3)) {
188 OBFormat* pFormat = (arg == argc - 2) ?
189 Conv.FindFormat(argv[arg + 1]) :
190 Conv.FindFormat(argv[arg] + 2);
192 cout << argv[arg] + 2 <<
" " << pFormat->Description() << endl;
193 if (pFormat->Flags() & NOTWRITABLE)
194 cout <<
" This format is Read-only" << endl;
195 if (pFormat->Flags() & NOTREADABLE)
196 cout <<
" This format is Write-only" << endl;
198 if (strlen(pFormat->SpecificationURL()))
199 cout <<
"Specification at: " << pFormat->SpecificationURL()
202 cout <<
"Format type: " << argv[arg] + 2
203 <<
" was not recognized" << endl;
205 OBPlugin::List(
"formats",
"verbose");
215 char* nam = argv[arg] + 2;
216 if (!strcasecmp(nam,
"help"))
224 while (arg < argc - 1 && *argv[arg + 1] !=
'-') {
234 OBConversion apiConv;
235 OBFormat* pAPI = OBConversion::FindFormat(
"obapi");
237 apiConv.SetOutFormat(pAPI);
238 apiConv.AddOption(nam + 1, OBConversion::GENOPTIONS,
240 apiConv.Write(
nullptr, &std::cout);
244 Conv.AddOption(nam, OBConversion::GENOPTIONS, txt.c_str());
254 DoOption(p, Conv, OBConversion::INOPTIONS, arg, argc, argv);
259 DoOption(p, Conv, OBConversion::OUTOPTIONS, arg, argc, argv);
268 if (!*p) p = argv[++arg];
269 Conv.AddOption(opchar, OBConversion::GENOPTIONS, p);
275 FileList.push_back(argv[arg]);
280 DoOption(p, Conv, OBConversion::GENOPTIONS, arg, argc, argv);
284 FileList.push_back(argv[arg]);
292 string formatName(program_name);
293 pos = formatName.find_first_of(
"2");
294 if (pos != string::npos) {
296 string tmpExt = formatName.substr(0, pos);
297 pInFormat = Conv.FindFormat(tmpExt.c_str());
298 if (pInFormat == NULL) {
299 cerr << program_name <<
": cannot read input format!" << endl;
308 string tmpExt = formatName.substr(pos + 1, string::npos);
309 pOutFormat = Conv.FindFormat(tmpExt.c_str());
310 if (pOutFormat == NULL) {
311 cerr << program_name <<
": cannot write output format!" << endl;
322 if (FileList.empty()) {
323 cerr <<
"No output file or format spec!" << endl;
326 OutputFileName = FileList.back();
330#if defined(_WIN32) && defined(USING_DYNAMIC_LIBS)
332 vector<string> tempFileList(FileList);
334 vector<string>::iterator itr;
335 for (itr = tempFileList.begin(); itr != tempFileList.end(); ++itr) {
336 if ((*itr)[0] ==
'-')
337 FileList.push_back(*itr);
339 DLHandler::findFiles(FileList, *itr);
344 if (FileList.empty()) {
345 cerr <<
"No input file or format spec or possibly a misplaced option.\n"
346 "Most options must come after the input files. (-i -o -O -m can "
358 pOutFormat = Conv.FormatFromExt(OutputFileName.c_str(), outGzip);
359 if (OutputFileName.empty() || pOutFormat ==
nullptr) {
360 cerr <<
"Missing or unknown output file or format spec or possibly a "
363 "Options, other than -i -o -O -m, must come after the input "
371 if (!Conv.SetInFormat(pInFormat))
373 cerr <<
"Invalid input format" << endl;
377 if (!Conv.SetOutFormat(pOutFormat, outGzip)) {
378 cerr <<
"Invalid output format" << endl;
385 if (OutputFileName.empty()) {
386 OutputFileName =
"*.";
387 OutputFileName += oext;
389 string::size_type pos = OutputFileName.rfind(
".gz");
390 if (pos == string::npos)
391 pos = OutputFileName.rfind(
'.');
393 pos = OutputFileName.rfind(
'.', pos - 1);
394 if (pos == string::npos)
395 OutputFileName +=
'*';
397 OutputFileName.insert(pos,
"*");
401 int count = Conv.FullConvert(FileList, OutputFileName, OutputFileList);
403 Conv.ReportNumberConverted(count);
405 if (OutputFileList.size() > 1) {
406 clog << OutputFileList.size() <<
" files output. The first is "
407 << OutputFileList[0] << endl;
410 std::string messageSummary = obErrorLog.GetMessageSummary();
411 if (messageSummary.size()) { clog << messageSummary << endl; }
415 cout <<
"Press any key to finish" << endl;
422void DoOption(
const char* p, OBConversion& Conv, OBConversion::Option_type typ,
423 int& arg,
int argc,
char* argv[]) {
434 while (arg < argc - 1 && *argv[arg + 1] !=
'-') {
436 if (!txt.empty()) txt +=
' ';
439 Conv.AddOption(ch, typ, txt.c_str());
443 cout << program_name <<
": part of OpenMD " << OPENMD_VERSION_MAJOR <<
"."
444 << OPENMD_VERSION_MINOR <<
"." << OPENMD_VERSION_TINY
445 <<
" and OpenBabel " << BABEL_VERSION <<
" -- " << __DATE__ <<
" -- "
447 cout <<
"Usage: " << program_name
448 <<
" [-i<input-type>] <name> [-o<output-type>] <name>" << endl;
449 cout <<
"Try -H option for more information." << endl;
453 cout <<
"Press any key to finish" << endl;
460 cout <<
"Open Babel converts chemical structures from one file format to "
464 cout <<
"Usage: " << endl;
466 <<
"[-i<input-type>] <infilename> [-o<output-type>] -O<outfilename> "
469 cout <<
"The extension of a file decides the format, unless it is overridden"
471 cout <<
" by -i or -o options, e.g. -icml, or -o smi" << endl;
472 cout <<
"See below for available format-types, which are the same as the "
474 cout <<
"file extensions and are case independent." << endl;
476 <<
"If no input or output file is given stdin or stdout are used instead."
480 <<
"More than one input file can be specified and their names can contain"
482 cout <<
"wildcard chars (* and ?). The format of each file can be different "
485 cout <<
"the -i option has been used, when they are all the same." << endl;
486 cout <<
"By default, the molecules are aggregated in the output file,"
488 cout <<
" but see -m option, Splitting, below.\n" << endl;
490 cout <<
"Options, other than -i -o -O -m, must come after the input files.\n"
492 cout << OBConversion::Description();
493 cout <<
"-H Outputs this help text" << endl;
494 cout <<
"-Hxxx (xxx is file format ID e.g. -Hcml) gives format info" << endl;
495 cout <<
"-Hall Outputs details of all formats" << endl;
496 cout <<
"-V Outputs version number" << endl;
497 cout <<
"-L <category> Lists plugin classes of this category, e.g. <formats>"
499 cout <<
" Use just -L for a list of plugin categories." << endl;
500 cout <<
" Use -L <ID> e.g. -L sdf for details of a format or other plugin."
502 cout <<
"-m Produces multiple output files, to allow:" << endl;
503 cout <<
" Splitting: e.g. " << program_name
504 <<
" infile.mol -O new.smi -m" << endl;
505 cout <<
" puts each molecule into new1.smi new2.smi etc" << endl;
506 cout <<
" Batch conversion: e.g. " << program_name <<
" *.mol -osmi -m"
508 cout <<
" converts each input file to a .smi file" << endl;
510 cout <<
" In Windows these can also be done using the forms" << endl;
511 cout <<
" " << program_name <<
" infile.mol -O new*.smi and "
512 << program_name <<
" *.mol -O *.smi respectively.\n"
516 OBFormat* pDefault = OBConversion::GetDefaultFormat();
518 cout << pDefault->TargetClassDescription();
521 OBFormat* pAPI = OBConversion::FindFormat(
"obapi");
522 if (pAPI) cout << pAPI->Description();
524 cout <<
"To see a list of recognized file formats use\n babel -L formats "
527 <<
"To see details and specific options for a particular format, e.g "