# | Line 3 | Line 3 | Copyright (C) 1998-2001 by OpenEye Scientific Software | |
---|---|---|
3 | command-line handling. | |
4 | ||
5 | Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc. | |
6 | < | Some portions Copyright (C) 2001-2005 by Geoffrey R. Hutchison |
7 | < | Some portions Copyright (C) 2004-2005 by Chris Morley |
6 | > | Some portions Copyright (C) 2001-2006 by Geoffrey R. Hutchison |
7 | > | Some portions Copyright (C) 2004-2006 by Chris Morley |
8 | > | Some portions Copyright (C) 2008 by J. Daniel Gezelter |
9 | ||
10 | < | This file is part of the OOPSE and Open Babel projects. |
10 | > | This file is part of both the OOPSE and Open Babel projects. |
11 | For more information, see <http://oopse.org> and <http://openbabel.sourceforge.net/> | |
12 | ||
13 | This program is free software; you can redistribute it and/or modify | |
# | Line 20 | Line 21 | GNU General Public License for more details. | |
21 | ***********************************************************************/ | |
22 | ||
23 | #include "config.h" | |
24 | < | #if HAVE_IOSTREAM |
25 | < | #include <iostream> |
26 | < | #elif HAVE_IOSTREAM_H |
27 | < | #include <iostream.h> |
24 | > | |
25 | > | // used to set import/export for Cygwin DLLs |
26 | > | #ifdef WIN32 |
27 | > | #define USING_OBDLL |
28 | #endif | |
28 | – | #if HAVE_FSTREAM |
29 | – | #include <fstream> |
30 | – | #elif HAVE_FSTREAM_H |
31 | – | #include <fstream.h> |
32 | – | #endif |
33 | – | #if HAVE_SSTREAM |
34 | – | #include <sstream> |
35 | – | #elif |
36 | – | #include <sstream.h> |
37 | – | #endif |
29 | ||
30 | + | #include <openbabel/babelconfig.h> |
31 | + | |
32 | + | #include <iostream> |
33 | + | #include <fstream> |
34 | + | #include <sstream> |
35 | + | |
36 | #include <string> | |
37 | #include <map> | |
38 | #if HAVE_CONIO_H | |
39 | #include <conio.h> | |
40 | #endif | |
41 | + | #include <cstdlib> |
42 | ||
43 | #if !HAVE_STRNCASECMP | |
44 | extern "C" int strncasecmp(const char *s1, const char *s2, size_t n); | |
45 | #endif | |
46 | ||
47 | < | #include "openbabel/obconversion.hpp" |
50 | < | #include "brains/Register.hpp" |
47 | > | #include <openbabel/obconversion.h> |
48 | ||
49 | using namespace std; | |
50 | using namespace OpenBabel; | |
51 | < | using namespace oopse; |
52 | < | void DoOption(const char* p, OBConversion& Conv, OBConversion::Option_type typ, |
53 | < | int& arg, int argc, char *argv[]); |
51 | > | |
52 | > | void DoOption(const char* p, OBConversion& Conv, |
53 | > | OBConversion::Option_type typ, int& arg, int argc, |
54 | > | char *argv[]); |
55 | void usage(); | |
56 | void help(); | |
57 | ||
# | Line 62 | Line 60 | int main(int argc,char *argv[]) | |
60 | ||
61 | int main(int argc,char *argv[]) | |
62 | { | |
65 | – | registerOBFormats(); |
63 | OBConversion Conv(&cin, &cout); //default input and output are console | |
64 | < | |
68 | < | // string GenOptions; |
64 | > | |
65 | OBFormat* pInFormat = NULL; | |
66 | OBFormat* pOutFormat = NULL; | |
67 | vector<string> FileList, OutputFileList; | |
68 | string OutputFileName; | |
69 | < | // obMessageLevel filterLevel = obWarning; // 2 out of 5 |
74 | < | |
69 | > | |
70 | // Parse commandline | |
71 | bool gotInType = false, gotOutType = false; | |
72 | < | bool UseSavedOptions = false; |
73 | < | |
72 | > | bool SplitOrBatch=false; |
73 | > | |
74 | char *oext; | |
75 | char *iext; | |
76 | string inputExt; | |
77 | string outputExt; | |
78 | < | |
78 | > | |
79 | //Save name of program without its path (and .exe) | |
80 | string pn(argv[0]); | |
81 | < | unsigned int pos; |
81 | > | string::size_type pos; |
82 | #ifdef _WIN32 | |
83 | pos = pn.find(".exe"); | |
84 | if(pos!=string::npos) | |
# | Line 94 | Line 89 | int main(int argc,char *argv[]) | |
89 | program_name=argv[0]; | |
90 | else | |
91 | program_name=argv[0]+pos+1; | |
92 | < | |
92 | > | |
93 | const char* p; | |
94 | int arg; | |
95 | < | for (arg = 1; arg < argc; arg++) |
95 | > | for (arg = 1; arg < argc; ++arg) |
96 | { | |
97 | if (argv[arg]) | |
98 | { | |
# | Line 105 | Line 100 | int main(int argc,char *argv[]) | |
100 | { | |
101 | switch (argv[arg][1]) | |
102 | { | |
103 | < | |
103 | > | |
104 | case 'V': | |
105 | { | |
106 | < | cout << "atom2md: part of OOPSE " << |
107 | < | OOPSE_VERSION_MAJOR << "." << OOPSE_VERSION_MINOR << "." << |
108 | < | OOPSE_VERSION_TINY << " and Open Babel " << BABEL_VERSION << " -- " |
106 | > | cout << program_name << ": part of OOPSE " << |
107 | > | OOPSE_VERSION_MAJOR << "." << OOPSE_VERSION_MINOR << |
108 | > | "." << OOPSE_VERSION_TINY << |
109 | > | " and Open Babel " << BABEL_VERSION << " -- " |
110 | << __DATE__ << " -- " << __TIME__ << endl; | |
111 | exit(0); | |
112 | } | |
113 | < | |
113 | > | |
114 | case 'i': | |
115 | gotInType = true; | |
116 | iext = argv[arg] + 2; | |
117 | if(!*iext) | |
118 | < | iext = argv[++arg]; //space left after -i: use next argument |
119 | < | |
118 | > | iext = argv[++arg]; // space left after -i: use next |
119 | > | // argument |
120 | > | |
121 | if (strncasecmp(iext, "MIME", 4) == 0) | |
122 | { | |
123 | // get the MIME type from the next argument | |
# | Line 129 | Line 126 | int main(int argc,char *argv[]) | |
126 | } | |
127 | else | |
128 | { | |
129 | < | //The ID provided by the OBFormat class is used as the identifying file extension |
129 | > | // The ID provided by the OBFormat class is used as the |
130 | > | // identifying file extension |
131 | pInFormat = Conv.FindFormat(iext); | |
132 | } | |
133 | if(pInFormat==NULL) | |
134 | { | |
135 | < | cerr << program_name << ": cannot read input format!" << endl; |
135 | > | cerr << program_name << ": cannot read input format!" |
136 | > | << endl; |
137 | usage(); | |
138 | } | |
140 | – | inputExt = iext; |
139 | break; | |
140 | ||
141 | case 'o': | |
142 | gotOutType = true; | |
143 | oext = argv[arg] + 2; | |
144 | if(!*oext) | |
145 | < | oext = argv[++arg]; //space left after -i: use next argument |
146 | < | |
145 | > | oext = argv[++arg]; // space left after -i: use next |
146 | > | // argument |
147 | > | |
148 | if (strncasecmp(oext, "MIME", 4) == 0) | |
149 | { | |
150 | // get the MIME type from the next argument | |
# | Line 154 | Line 153 | int main(int argc,char *argv[]) | |
153 | } | |
154 | else | |
155 | pOutFormat = Conv.FindFormat(oext); | |
156 | < | |
156 | > | |
157 | if(pOutFormat==NULL) | |
158 | { | |
159 | < | cerr << program_name << ": cannot write output format!" << endl; |
159 | > | cerr << program_name << ": cannot write output format!" |
160 | > | << endl; |
161 | usage(); | |
162 | } | |
163 | < | outputExt = oext; |
164 | < | break; |
163 | > | break; |
164 | ||
165 | + | case 'F': |
166 | + | if(!Conv.SetOutFormat("fpt")) |
167 | + | cout << "FingerprintFormat needs to be loaded" << endl; |
168 | + | else |
169 | + | { |
170 | + | Conv.AddOption("F",OBConversion::OUTOPTIONS); |
171 | + | Conv.Write(NULL); |
172 | + | } |
173 | + | return 0; |
174 | + | |
175 | case '?': | |
176 | case 'H': | |
177 | if(isalnum(argv[arg][2])) | |
# | Line 199 | Line 208 | int main(int argc,char *argv[]) | |
208 | } | |
209 | else | |
210 | help(); | |
211 | < | exit(0); |
212 | < | |
213 | < | |
211 | > | exit(0); |
212 | > | |
213 | > | case '-': //long option --name text |
214 | > | { |
215 | > | //Do nothing if name is empty |
216 | > | //Option's text is the next arg provided it doesn't start with - |
217 | > | char* nam = argv[arg]+2; |
218 | > | if(*nam != '\0') |
219 | > | { |
220 | > | string txt; |
221 | > | int i; |
222 | > | for(i=0; i<Conv.GetOptionParams(nam, OBConversion::GENOPTIONS) |
223 | > | && arg<argc-1 && argv[arg+1];++i) //removed && *argv[arg+1]!='-' |
224 | > | { |
225 | > | if(!txt.empty()) txt+=' '; |
226 | > | txt += argv[++arg]; |
227 | > | } |
228 | > | if(*nam=='-') |
229 | > | { |
230 | > | // Is a API directive, e.g.---errorlevel |
231 | > | //Send to the pseudoformat "obapi" (without any leading -) |
232 | > | OBConversion apiConv; |
233 | > | OBFormat* pAPI= OBConversion::FindFormat("obapi"); |
234 | > | if(pAPI) |
235 | > | { |
236 | > | apiConv.SetOutFormat(pAPI); |
237 | > | apiConv.AddOption(nam+1, OBConversion::GENOPTIONS, txt.c_str()); |
238 | > | apiConv.Write(NULL, &std::cout); |
239 | > | } |
240 | > | } |
241 | > | else |
242 | > | // Is a long option name, e.g --addtotitle |
243 | > | Conv.AddOption(nam,OBConversion::GENOPTIONS,txt.c_str()); |
244 | > | } |
245 | > | } |
246 | > | break; |
247 | > | |
248 | > | case 'm': //multiple output files |
249 | > | SplitOrBatch=true; |
250 | > | break; |
251 | > | |
252 | > | case 'a': //single character input option |
253 | > | p = argv[arg]+2; |
254 | > | DoOption(p,Conv,OBConversion::INOPTIONS,arg,argc,argv); |
255 | > | break; |
256 | > | |
257 | > | case 'x': //single character output option |
258 | > | p = argv[arg]+2; |
259 | > | DoOption(p,Conv,OBConversion::OUTOPTIONS,arg,argc,argv); |
260 | > | break; |
261 | > | |
262 | default: //single character general option | |
263 | p = argv[arg]+1; | |
264 | DoOption(p,Conv,OBConversion::GENOPTIONS,arg,argc,argv); | |
# | Line 219 | Line 276 | int main(int argc,char *argv[]) | |
276 | } | |
277 | } | |
278 | ||
279 | < | //user didn't specify input and output format in commandline option |
280 | < | //try to parse it from program name (pdb2mdin means input format is pdb, output format is mdin) |
279 | > | // user didn't specify input and output format in commandline option |
280 | > | // try to parse it from program name (pdb2mdin means input format is pdb, |
281 | > | // output format is mdin) |
282 | > | |
283 | string formatName(program_name); | |
284 | pos = formatName.find_first_of("2"); | |
285 | if(pos!=string::npos) { | |
# | Line 238 | Line 297 | int main(int argc,char *argv[]) | |
297 | inputExt = tmpExt; | |
298 | } | |
299 | } | |
300 | < | |
300 | > | |
301 | if (!gotOutType) | |
302 | { | |
303 | string tmpExt = formatName.substr(pos+1, string::npos); | |
# | Line 254 | Line 313 | int main(int argc,char *argv[]) | |
313 | } | |
314 | } | |
315 | ||
316 | < | if(FileList.empty()) |
316 | > | if (!gotInType) |
317 | { | |
318 | < | cerr << "No input file or format spec!" <<endl; |
319 | < | usage(); |
318 | > | if(FileList.empty()) |
319 | > | { |
320 | > | cerr << "No input file or format spec!" <<endl; |
321 | > | usage(); |
322 | > | } |
323 | } | |
324 | ||
325 | < | if (OutputFileName.empty()) |
325 | > | if (!gotOutType) |
326 | { | |
327 | < | pos = FileList.front().rfind("."); |
328 | < | if(pos==string::npos) |
329 | < | OutputFileName = FileList.front()+ "." + outputExt; |
330 | < | else |
331 | < | OutputFileName = FileList.front().substr(0, pos) + "." + outputExt; |
327 | > | pOutFormat = Conv.FormatFromExt(OutputFileName.c_str()); |
328 | > | if(pOutFormat==NULL) |
329 | > | { |
330 | > | cerr << program_name << ": cannot write output format!" << endl; |
331 | > | usage(); |
332 | > | } |
333 | } | |
334 | ||
335 | < | Conv.SetInAndOutFormats(pInFormat,pOutFormat); |
335 | > | Conv.SetInAndOutFormats(pInFormat, pOutFormat); |
336 | ||
337 | < | |
338 | < | // send info message to clog -- don't mess up cerr or cout for user programs |
337 | > | if(SplitOrBatch) |
338 | > | { |
339 | > | //Put * into output file name before extension (or ext.gz) |
340 | > | if(OutputFileName.empty()) |
341 | > | { |
342 | > | OutputFileName = "*."; |
343 | > | OutputFileName += oext; |
344 | > | } |
345 | > | else |
346 | > | { |
347 | > | string::size_type pos = OutputFileName.rfind(".gz"); |
348 | > | if(pos==string::npos) |
349 | > | pos = OutputFileName.rfind('.'); |
350 | > | else |
351 | > | pos = OutputFileName.rfind('.',pos-1); |
352 | > | if(pos==string::npos) |
353 | > | OutputFileName += '*'; |
354 | > | else |
355 | > | OutputFileName.insert(pos,"*"); |
356 | > | } |
357 | > | } |
358 | > | |
359 | int count = Conv.FullConvert(FileList, OutputFileName, OutputFileList); | |
277 | – | if ( count == 1 ) |
278 | – | clog << count << " molecule converted" << endl; |
279 | – | else |
280 | – | clog << count << " molecules converted" << endl; |
360 | ||
361 | + | // send info message to clog -- don't mess up cerr or cout for user programs |
362 | + | //Get the last word on the first line of the description which should |
363 | + | //be "molecules", "reactions", etc and remove the s if only one object converted |
364 | + | std::string objectname(pOutFormat->TargetClassDescription()); |
365 | + | pos = objectname.find('\n'); |
366 | + | if(count==1) --pos; |
367 | + | objectname.erase(pos); |
368 | + | pos = objectname.rfind(' '); |
369 | + | if(pos==std::string::npos) |
370 | + | pos=0; |
371 | + | std::clog << count << objectname.substr(pos) << " converted" << endl; |
372 | if(OutputFileList.size()>1) | |
373 | { | |
374 | clog << OutputFileList.size() << " files output. The first is " << OutputFileList[0] <<endl; | |
375 | } | |
376 | ||
377 | + | std::string messageSummary = obErrorLog.GetMessageSummary(); |
378 | + | if (messageSummary.size()) |
379 | + | { |
380 | + | clog << messageSummary << endl; |
381 | + | } |
382 | + | |
383 | #ifdef _DEBUG | |
384 | //CM keep window open | |
385 | cout << "Press any key to finish" <<endl; | |
386 | getch(); | |
387 | #endif | |
292 | – | |
388 | return 0; | |
389 | } | |
390 | ||
391 | < | void DoOption(const char* p, OBConversion& Conv, OBConversion::Option_type typ, int& arg, int argc, char *argv[]) |
391 | > | void DoOption(const char* p, OBConversion& Conv, |
392 | > | OBConversion::Option_type typ, int& arg, int argc, char *argv[]) |
393 | { | |
394 | while(p && *p) //can have multiple single char options | |
395 | + | { |
396 | + | char ch[2]="?"; |
397 | + | *ch = *p++; |
398 | + | const char* txt=NULL; |
399 | + | //Get the option text if needed |
400 | + | int nParams = Conv.GetOptionParams(ch, typ); |
401 | + | if(nParams) |
402 | { | |
403 | < | char ch[2]="?"; |
404 | < | *ch = *p++; |
405 | < | const char* txt=NULL; |
406 | < | //Get the option text if needed |
407 | < | int nParams = Conv.GetOptionParams(ch, typ); |
408 | < | if(nParams) |
403 | > | if(*p) |
404 | > | { |
405 | > | txt = p; //use text immediately following the option letter |
406 | > | p=NULL; //no more single char options |
407 | > | } |
408 | > | else if(arg<argc-1) |
409 | > | { |
410 | > | txt = argv[++arg]; //use text from next arg |
411 | > | if(*txt=='-') |
412 | { | |
413 | < | if(*p) |
414 | < | { |
415 | < | txt = p; //use text immediately following the option letter |
310 | < | p=NULL; //no more single char options |
311 | < | } |
312 | < | else if(arg<argc-1) |
313 | < | { |
314 | < | txt = argv[++arg]; //use text from next arg |
315 | < | if(*txt=='-') |
316 | < | { |
317 | < | //...unless it is another option |
318 | < | cerr << "Option -" << ch << " takes a parameter" << endl; |
319 | < | exit(0); |
320 | < | } |
321 | < | } |
413 | > | //...unless it is another option |
414 | > | cerr << "Option -" << ch << " takes a parameter" << endl; |
415 | > | exit(0); |
416 | } | |
417 | < | Conv.AddOption(ch, typ, txt); |
417 | > | } |
418 | } | |
419 | + | Conv.AddOption(ch, typ, txt); |
420 | + | } |
421 | } | |
422 | ||
423 | void usage() | |
424 | { | |
425 | < | cout << "atom2md: part of OOPSE " << |
425 | > | cout << program_name << ": part of OOPSE " << |
426 | OOPSE_VERSION_MAJOR << "." << OOPSE_VERSION_MINOR << "." << | |
427 | < | OOPSE_VERSION_TINY << " and Open Babel " << BABEL_VERSION << " -- " |
427 | > | OOPSE_VERSION_TINY << " and OpenBabel " << BABEL_VERSION << " -- " |
428 | << __DATE__ << " -- " << __TIME__ << endl; | |
429 | cout << "Usage: " << program_name | |
430 | << " [-i<input-type>] <name> [-o<output-type>] <name>" << endl; | |
# | Line 345 | Line 441 | void help() | |
441 | ||
442 | void help() | |
443 | { | |
444 | < | cout << "Open Babel converts chemical structures from one file format to another"<< endl << endl; |
444 | > | cout << program_name << " converts chemical structures from one file format to another"<< endl << endl; |
445 | cout << "Usage: " << program_name << " <input spec> <output spec> [Options]" << endl << endl; | |
446 | cout << "Each spec can be a file whose extension decides the format." << endl; | |
447 | cout << "Optionally the format can be specified by preceding the file by" << endl; | |
# | Line 377 | Line 473 | void help() | |
473 | while(OBConversion::GetNextFormat(pos,str,pFormat)) | |
474 | { | |
475 | if((pFormat->Flags() & NOTWRITABLE) && (pFormat->Flags() & NOTREADABLE)) | |
476 | < | continue; |
476 | > | continue; |
477 | cout << " " << str << endl; | |
478 | } | |
479 | cout << "\nSee further specific info and options using -H<format-type>, e.g. -Hpdb" << endl; |
– | Removed lines |
+ | Added lines |
< | Changed lines |
> | Changed lines |