kdecore Library API Documentation

kcmdlineargs.cpp

00001 /* 00002 Copyright (C) 1999 Waldo Bastian <bastian@kde.org> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License version 2 as published by the Free Software Foundation. 00007 00008 This library is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00011 Library General Public License for more details. 00012 00013 You should have received a copy of the GNU Library General Public License 00014 along with this library; see the file COPYING.LIB. If not, write to 00015 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00016 Boston, MA 02111-1307, USA. 00017 */ 00018 00019 #include <config.h> 00020 00021 #include <sys/param.h> 00022 00023 #include <assert.h> 00024 #include <stdio.h> 00025 #include <stdlib.h> 00026 #include <string.h> 00027 #include <unistd.h> 00028 00029 #if HAVE_LIMITS_H 00030 #include <limits.h> 00031 #endif 00032 00033 #include <qfile.h> 00034 #include <qasciidict.h> 00035 #include <qstrlist.h> 00036 00037 #include "kcmdlineargs.h" 00038 #include <kaboutdata.h> 00039 #include <klocale.h> 00040 #include <kapplication.h> 00041 #include <kglobal.h> 00042 #include <kstringhandler.h> 00043 #include <kstaticdeleter.h> 00044 00045 #ifdef Q_WS_X11 00046 #define DISPLAY "DISPLAY" 00047 #elif defined(Q_WS_QWS) 00048 #define DISPLAY "QWS_DISPLAY" 00049 #endif 00050 00051 template class QAsciiDict<QCString>; 00052 template class QPtrList<KCmdLineArgs>; 00053 00054 class KCmdLineParsedOptions : public QAsciiDict<QCString> 00055 { 00056 public: 00057 KCmdLineParsedOptions() 00058 : QAsciiDict<QCString>( 7 ) { } 00059 00060 // WABA: Huh? 00061 // The compiler doesn't find KCmdLineParsedOptions::write(s) by itself ??? 00062 // WABA: No, because there is another write function that hides the 00063 // write function in the base class even though this function has a 00064 // different signature. (obscure C++ feature) 00065 QDataStream& save( QDataStream &s) const 00066 { return QGDict::write(s); } 00067 00068 QDataStream& load( QDataStream &s) 00069 { return QGDict::read(s); } 00070 00071 protected: 00072 virtual QDataStream& write( QDataStream &s, QPtrCollection::Item data) const 00073 { 00074 QCString *str = (QCString *) data; 00075 s << (*str); 00076 return s; 00077 } 00078 00079 virtual QDataStream& read( QDataStream &s, QPtrCollection::Item &item) 00080 { 00081 QCString *str = new QCString; 00082 s >> (*str); 00083 item = (void *)str; 00084 return s; 00085 } 00086 00087 }; 00088 00089 class KCmdLineParsedArgs : public QStrList 00090 { 00091 public: 00092 KCmdLineParsedArgs() 00093 : QStrList( true ) { } 00094 QDataStream& save( QDataStream &s) const 00095 { return QGList::write(s); } 00096 00097 QDataStream& load( QDataStream &s) 00098 { return QGList::read(s); } 00099 }; 00100 00101 00102 class KCmdLineArgsList: public QPtrList<KCmdLineArgs> 00103 { 00104 public: 00105 KCmdLineArgsList() { } 00106 }; 00107 00108 KCmdLineArgsList *KCmdLineArgs::argsList = 0; 00109 int KCmdLineArgs::argc = 0; 00110 char **KCmdLineArgs::argv = 0; 00111 char *KCmdLineArgs::mCwd = 0; 00112 static KStaticDeleter <char> mCwdd; 00113 const KAboutData *KCmdLineArgs::about = 0; 00114 bool KCmdLineArgs::parsed = false; 00115 bool KCmdLineArgs::ignoreUnknown = false; 00116 00117 // 00118 // Static functions 00119 // 00120 00121 void 00122 KCmdLineArgs::init(int _argc, char **_argv, const char *_appname, const char* programName, 00123 const char *_description, const char *_version, bool noKApp) 00124 { 00125 init(_argc, _argv, 00126 new KAboutData(_appname, programName, _version, _description), 00127 noKApp); 00128 } 00129 00130 void 00131 KCmdLineArgs::init(int _argc, char **_argv, const char *_appname, 00132 const char *_description, const char *_version, bool noKApp) 00133 { 00134 init(_argc, _argv, 00135 new KAboutData(_appname, _appname, _version, _description), 00136 noKApp); 00137 } 00138 00139 void 00140 KCmdLineArgs::initIgnore(int _argc, char **_argv, const char *_appname ) 00141 { 00142 init(_argc, _argv, 00143 new KAboutData(_appname, _appname, "unknown", "KDE Application", false)); 00144 ignoreUnknown = true; 00145 } 00146 00147 void 00148 KCmdLineArgs::init(const KAboutData* ab) 00149 { 00150 char **_argv = (char **) malloc(sizeof(char *)); 00151 _argv[0] = (char *) ab->appName(); 00152 init(1,_argv,ab, true); 00153 } 00154 00155 00156 void 00157 KCmdLineArgs::init(int _argc, char **_argv, const KAboutData *_about, bool noKApp) 00158 { 00159 argc = _argc; 00160 argv = _argv; 00161 00162 if (!argv) 00163 { 00164 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n"); 00165 fprintf(stderr, "Passing null-pointer to 'argv' is not allowed.\n\n"); 00166 00167 assert( 0 ); 00168 exit(255); 00169 } 00170 00171 // Strip path from argv[0] 00172 if (argc) { 00173 char *p = strrchr( argv[0], '/'); 00174 if (p) 00175 argv[0] = p+1; 00176 } 00177 00178 about = _about; 00179 parsed = false; 00180 mCwd = mCwdd.setObject(mCwd, new char [PATH_MAX+1], true); 00181 getcwd(mCwd, PATH_MAX); 00182 if (!noKApp) 00183 KApplication::addCmdLineOptions(); 00184 } 00185 00186 QString KCmdLineArgs::cwd() 00187 { 00188 return QFile::decodeName(QCString(mCwd)); 00189 } 00190 00191 const char * KCmdLineArgs::appName() 00192 { 00193 if (!argc) return 0; 00194 return argv[0]; 00195 } 00196 00197 void 00198 KCmdLineArgs::addCmdLineOptions( const KCmdLineOptions *options, const char *name, 00199 const char *id, const char *afterId) 00200 { 00201 if (!argsList) 00202 argsList = new KCmdLineArgsList(); 00203 00204 int pos = argsList->count(); 00205 00206 if (pos && id && argsList->last() && !argsList->last()->name) 00207 pos--; 00208 00209 KCmdLineArgs *args; 00210 int i = 0; 00211 for(args = argsList->first(); args; args = argsList->next(), i++) 00212 { 00213 if (!id && !args->id) 00214 return; // Options already present. 00215 00216 if (id && args->id && (::qstrcmp(id, args->id) == 0)) 00217 return; // Options already present. 00218 00219 if (afterId && args->id && (::qstrcmp(afterId, args->id) == 0)) 00220 pos = i+1; 00221 } 00222 00223 assert( parsed == false ); // You must add _ALL_ cmd line options 00224 // before accessing the arguments! 00225 args = new KCmdLineArgs(options, name, id); 00226 argsList->insert(pos, args); 00227 } 00228 00229 void 00230 KCmdLineArgs::saveAppArgs( QDataStream &ds) 00231 { 00232 if (!parsed) 00233 parseAllArgs(); 00234 00235 // Remove Qt and KDE options. 00236 removeArgs("qt"); 00237 removeArgs("kde"); 00238 00239 QCString qCwd = mCwd; 00240 ds << qCwd; 00241 00242 uint count = argsList ? argsList->count() : 0; 00243 ds << count; 00244 00245 if (!count) return; 00246 00247 KCmdLineArgs *args; 00248 for(args = argsList->first(); args; args = argsList->next()) 00249 { 00250 ds << QCString(args->id); 00251 args->save(ds); 00252 } 00253 } 00254 00255 void 00256 KCmdLineArgs::loadAppArgs( QDataStream &ds) 00257 { 00258 // Remove Qt and KDE options. 00259 removeArgs("qt"); 00260 removeArgs("kde"); 00261 00262 if (ds.atEnd()) 00263 return; 00264 00265 KCmdLineArgs *args; 00266 if ( argsList ) { 00267 for(args = argsList->first(); args; args = argsList->next()) 00268 { 00269 args->clear(); 00270 } 00271 } 00272 00273 QCString qCwd; 00274 ds >> qCwd; 00275 delete [] mCwd; 00276 00277 mCwd = mCwdd.setObject(mCwd, new char[qCwd.length()+1], true); 00278 strncpy(mCwd, qCwd.data(), qCwd.length()+1); 00279 00280 uint count; 00281 ds >> count; 00282 00283 while(count--) 00284 { 00285 QCString id; 00286 ds >> id; 00287 assert( argsList ); 00288 for(args = argsList->first(); args; args = argsList->next()) 00289 { 00290 if (args->id == id) 00291 { 00292 args->load(ds); 00293 break; 00294 } 00295 } 00296 } 00297 } 00298 00299 KCmdLineArgs *KCmdLineArgs::parsedArgs(const char *id) 00300 { 00301 KCmdLineArgs *args = argsList ? argsList->first() : 0; 00302 while(args) 00303 { 00304 if ((id && ::qstrcmp(args->id, id) == 0) || (!id && !args->id)) 00305 { 00306 if (!parsed) 00307 parseAllArgs(); 00308 return args; 00309 } 00310 args = argsList->next(); 00311 } 00312 00313 if (!args) 00314 { 00315 #ifndef NDEBUG 00316 fprintf(stderr, "WARNING (KCmdLineArgs):\n"); 00317 fprintf(stderr, "Application requests for parsedArgs(\"%s\") without a prior call\n", id?id:"null"); 00318 fprintf(stderr, "to addCmdLineOptions( ..., \"%s\"), or after a reset()\n\n", id?id:"null"); 00319 #endif 00320 } 00321 return args; 00322 } 00323 00324 void KCmdLineArgs::removeArgs(const char *id) 00325 { 00326 KCmdLineArgs *args = argsList ? argsList->first() : 0; 00327 while(args) 00328 { 00329 if (args->id && id && ::qstrcmp(args->id, id) == 0) 00330 { 00331 if (!parsed) 00332 parseAllArgs(); 00333 break; 00334 } 00335 args = argsList->next(); 00336 } 00337 00338 if (args) 00339 delete args; 00340 } 00341 00342 /* 00343 * @return: 00344 * 0 - option not found. 00345 * 1 - option found // -fork 00346 * 2 - inverse option found ('no') // -nofork 00347 * 3 - option + arg found // -fork now 00348 * 00349 * +4 - no more options follow // !fork 00350 */ 00351 static int 00352 findOption(const KCmdLineOptions *options, QCString &opt, 00353 const char *&opt_name, const char *&def, bool &enabled) 00354 { 00355 int result; 00356 bool inverse; 00357 int len = opt.length(); 00358 while(options && options->name) 00359 { 00360 result = 0; 00361 inverse = false; 00362 opt_name = options->name; 00363 if ((opt_name[0] == ':') || (opt_name[0] == 0)) 00364 { 00365 options++; 00366 continue; 00367 } 00368 00369 if (opt_name[0] == '!') 00370 { 00371 opt_name++; 00372 result = 4; 00373 } 00374 if ((opt_name[0] == 'n') && (opt_name[1] == 'o')) 00375 { 00376 opt_name += 2; 00377 inverse = true; 00378 } 00379 if (strncmp(opt.data(), opt_name, len) == 0) 00380 { 00381 opt_name += len; 00382 if (!opt_name[0]) 00383 { 00384 if (inverse) 00385 return result+2; 00386 00387 if (!options->description) 00388 { 00389 options++; 00390 if (!options->name) 00391 return result+0; 00392 QCString nextOption = options->name; 00393 int p = nextOption.find(' '); 00394 if (p > 0) 00395 nextOption = nextOption.left(p); 00396 if (strncmp(nextOption.data(), "no", 2) == 0) 00397 { 00398 nextOption = nextOption.mid(2); 00399 enabled = !enabled; 00400 } 00401 result = findOption(options, nextOption, opt_name, def, enabled); 00402 assert(result); 00403 opt = nextOption; 00404 return result; 00405 } 00406 00407 return 1; 00408 } 00409 if (opt_name[0] == ' ') 00410 { 00411 opt_name++; 00412 def = options->def; 00413 return result+3; 00414 } 00415 } 00416 00417 options++; 00418 } 00419 return 0; 00420 } 00421 00422 00423 void 00424 KCmdLineArgs::findOption(const char *_opt, QCString opt, int &i, bool _enabled, bool &moreOptions) 00425 { 00426 KCmdLineArgs *args = argsList->first(); 00427 const char *opt_name; 00428 const char *def; 00429 QCString argument; 00430 int j = opt.find('='); 00431 if (j != -1) 00432 { 00433 argument = opt.mid(j+1); 00434 opt = opt.left(j); 00435 } 00436 00437 bool enabled = true; 00438 int result = 0; 00439 while (args) 00440 { 00441 enabled = _enabled; 00442 result = ::findOption(args->options, opt, opt_name, def, enabled); 00443 if (result) break; 00444 args = argsList->next(); 00445 } 00446 if (!args && (_opt[0] == '-') && _opt[1] && (_opt[1] != '-')) 00447 { 00448 // Option not found check if it is a valid option 00449 // in the style of -Pprinter1 or ps -aux 00450 int p = 1; 00451 while (true) 00452 { 00453 QCString singleCharOption = " "; 00454 singleCharOption[0] = _opt[p]; 00455 args = argsList->first(); 00456 while (args) 00457 { 00458 enabled = _enabled; 00459 result = ::findOption(args->options, singleCharOption, opt_name, def, enabled); 00460 if (result) break; 00461 args = argsList->next(); 00462 } 00463 if (!args) 00464 break; // Unknown argument 00465 00466 p++; 00467 if (result == 1) // Single option 00468 { 00469 args->setOption(singleCharOption, enabled); 00470 if (_opt[p]) 00471 continue; // Next option 00472 else 00473 return; // Finished 00474 } 00475 else if (result == 3) // This option takes an argument 00476 { 00477 if (argument.isEmpty()) 00478 { 00479 argument = _opt+p; 00480 } 00481 args->setOption(singleCharOption, argument); 00482 return; 00483 } 00484 break; // Unknown argument 00485 } 00486 args = 0; 00487 result = 0; 00488 } 00489 00490 if (!args || !result) 00491 { 00492 if (ignoreUnknown) 00493 return; 00494 enable_i18n(); 00495 usage( i18n("Unknown option '%1'.").arg(_opt)); 00496 } 00497 00498 if ((result & 4) != 0) 00499 { 00500 result &= ~4; 00501 moreOptions = false; 00502 } 00503 00504 if (result == 3) // This option takes an argument 00505 { 00506 if (!enabled) 00507 { 00508 if (ignoreUnknown) 00509 return; 00510 enable_i18n(); 00511 usage( i18n("Unknown option '%1'.").arg(_opt)); 00512 } 00513 if (argument.isEmpty()) 00514 { 00515 i++; 00516 if (i >= argc) 00517 { 00518 enable_i18n(); 00519 usage( i18n("'%1' missing.").arg( opt_name)); 00520 } 00521 argument = argv[i]; 00522 } 00523 args->setOption(opt, argument); 00524 } 00525 else 00526 { 00527 args->setOption(opt, enabled); 00528 } 00529 } 00530 00531 void 00532 KCmdLineArgs::printQ(const QString &msg) 00533 { 00534 QCString localMsg = msg.local8Bit(); 00535 fprintf(stdout, "%s", localMsg.data()); 00536 } 00537 00538 void 00539 KCmdLineArgs::parseAllArgs() 00540 { 00541 bool allowArgs = false; 00542 bool inOptions = true; 00543 bool everythingAfterArgIsArgs = false; 00544 KCmdLineArgs *appOptions = argsList->last(); 00545 if (!appOptions->id) 00546 { 00547 const KCmdLineOptions *option = appOptions->options; 00548 while(option && option->name) 00549 { 00550 if (option->name[0] == '+') 00551 allowArgs = true; 00552 if ( option->name[0] == '!' && option->name[1] == '+' ) 00553 { 00554 allowArgs = true; 00555 everythingAfterArgIsArgs = true; 00556 } 00557 option++; 00558 } 00559 } 00560 for(int i = 1; i < argc; i++) 00561 { 00562 if (!argv[i]) 00563 continue; 00564 00565 if ((argv[i][0] == '-') && argv[i][1] && inOptions) 00566 { 00567 bool enabled = true; 00568 const char *option = &argv[i][1]; 00569 const char *orig = argv[i]; 00570 if (option[0] == '-') 00571 { 00572 option++; 00573 argv[i]++; 00574 if (!option[0]) 00575 { 00576 inOptions = false; 00577 continue; 00578 } 00579 } 00580 if (::qstrcmp(option, "help") == 0) 00581 { 00582 usage(0); 00583 } 00584 else if (strncmp(option, "help-",5) == 0) 00585 { 00586 usage(option+5); 00587 } 00588 else if ( (::qstrcmp(option, "version") == 0) || 00589 (::qstrcmp(option, "v") == 0)) 00590 { 00591 printQ( QString("Qt: %1\n").arg(qVersion())); 00592 printQ( QString("KDE: %1\n").arg(KDE_VERSION_STRING)); 00593 printQ( QString("%1: %2\n"). 00594 arg(about->programName()).arg(about->version())); 00595 exit(0); 00596 } else if ( (::qstrcmp(option, "license") == 0) ) 00597 { 00598 enable_i18n(); 00599 printQ( about->license() ); 00600 printQ( "\n" ); 00601 exit(0); 00602 } else if ( ::qstrcmp( option, "author") == 0 ) { 00603 enable_i18n(); 00604 if ( about ) { 00605 const QValueList<KAboutPerson> authors = about->authors(); 00606 if ( !authors.isEmpty() ) { 00607 QString authorlist; 00608 for (QValueList<KAboutPerson>::ConstIterator it = authors.begin(); it != authors.end(); ++it ) { 00609 QString email; 00610 if ( !(*it).emailAddress().isEmpty() ) 00611 email = " <" + (*it).emailAddress() + ">"; 00612 authorlist += QString(" ") + (*it).name() + email + "\n"; 00613 } 00614 printQ( i18n("the 2nd argument is a list of name+address, one on each line","%1 was written by\n%2").arg ( QString(about->programName()) ).arg( authorlist ) ); 00615 } 00616 } else { 00617 printQ( i18n("%1 was written by somebody who wants to remain anonymous.").arg(about->programName()) ); 00618 } 00619 if (!about->bugAddress().isEmpty()) 00620 { 00621 if (about->bugAddress() == "submit@bugs.kde.org") 00622 printQ( i18n( "Please use http://bugs.kde.org to report bugs, do not mail the authors directly.\n" ) ); 00623 else 00624 printQ( i18n( "Please use %1 to report bugs, do not mail the authors directly.\n" ).arg(about->bugAddress()) ); 00625 } 00626 exit(0); 00627 } else { 00628 if ((option[0] == 'n') && (option[1] == 'o')) 00629 { 00630 option += 2; 00631 enabled = false; 00632 } 00633 findOption(orig, option, i, enabled, inOptions); 00634 } 00635 } 00636 else 00637 { 00638 // Check whether appOptions allows these arguments 00639 if (!allowArgs) 00640 { 00641 if (ignoreUnknown) 00642 continue; 00643 enable_i18n(); 00644 usage( i18n("Unexpected argument '%1'.").arg( argv[i])); 00645 } 00646 else 00647 { 00648 appOptions->addArgument(argv[i]); 00649 if (everythingAfterArgIsArgs) 00650 inOptions = false; 00651 } 00652 } 00653 } 00654 parsed = true; 00655 } 00656 00662 int * 00663 KCmdLineArgs::qt_argc() 00664 { 00665 if (!argsList) 00666 KApplication::addCmdLineOptions(); // Lazy bastards! 00667 00668 KCmdLineArgs *args = parsedArgs("qt"); 00669 00670 assert(args); // No qt options have been added! 00671 if (!argv) 00672 { 00673 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n"); 00674 fprintf(stderr, "Application has not called KCmdLineArgs::init(...).\n\n"); 00675 00676 assert( 0 ); 00677 exit(255); 00678 } 00679 00680 assert(argc >= (args->count()+1)); 00681 argc = args->count() +1; 00682 return &argc; 00683 } 00684 00690 char *** 00691 KCmdLineArgs::qt_argv() 00692 { 00693 if (!argsList) 00694 KApplication::addCmdLineOptions(); // Lazy bastards! 00695 00696 KCmdLineArgs *args = parsedArgs("qt"); 00697 assert(args); // No qt options have been added! 00698 if (!argv) 00699 { 00700 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n"); 00701 fprintf(stderr, "Application has not called KCmdLineArgs::init(...).\n\n"); 00702 00703 assert( 0 ); 00704 exit(255); 00705 } 00706 00707 int i = 0; 00708 for(; i < args->count(); i++) 00709 { 00710 argv[i+1] = (char *) args->arg(i); 00711 } 00712 argv[i+1] = 0; 00713 00714 return &argv; 00715 } 00716 00717 void 00718 KCmdLineArgs::enable_i18n() 00719 { 00720 // called twice or too late 00721 if (KGlobal::_locale) 00722 return; 00723 00724 if (!KGlobal::_instance) { 00725 KInstance *instance = new KInstance(about); 00726 (void) instance->config(); 00727 // Don't delete instance! 00728 } 00729 } 00730 00731 void 00732 KCmdLineArgs::usage(const QString &error) 00733 { 00734 assert(KGlobal::_locale); 00735 QCString localError = error.local8Bit(); 00736 if (localError[error.length()-1] == '\n') 00737 localError = localError.left(error.length()-1); 00738 fprintf(stderr, "%s: %s\n", argv[0], localError.data()); 00739 00740 QString tmp = i18n("Use --help to get a list of available command line options."); 00741 localError = tmp.local8Bit(); 00742 fprintf(stderr, "%s: %s\n", argv[0], localError.data()); 00743 exit(254); 00744 } 00745 00746 void 00747 KCmdLineArgs::usage(const char *id) 00748 { 00749 enable_i18n(); 00750 assert(argsList != 0); // It's an error to call usage(...) without 00751 // having done addCmdLineOptions first! 00752 00753 QString optionFormatString = " %1 %2\n"; 00754 QString optionFormatStringDef = " %1 %2 [%3]\n"; 00755 QString optionHeaderString = i18n("\n%1:\n"); 00756 QString tmp; 00757 QString usage; 00758 00759 KCmdLineArgs *args = argsList->last(); 00760 00761 if (!(args->id) && (args->options) && 00762 (args->options->name) && (args->options->name[0] != '+')) 00763 { 00764 usage = i18n("[options] ")+usage; 00765 } 00766 00767 while(args) 00768 { 00769 if (args->name) 00770 { 00771 usage = i18n("[%1-options]").arg(args->name)+" "+usage; 00772 } 00773 args = argsList->prev(); 00774 } 00775 00776 KCmdLineArgs *appOptions = argsList->last(); 00777 if (!appOptions->id) 00778 { 00779 const KCmdLineOptions *option = appOptions->options; 00780 while(option && option->name) 00781 { 00782 if (option->name[0] == '+') 00783 usage = usage + (option->name+1) + " "; 00784 else if ( option->name[0] == '!' && option->name[1] == '+' ) 00785 usage = usage + (option->name+2) + " "; 00786 00787 option++; 00788 } 00789 } 00790 00791 printQ(i18n("Usage: %1 %2\n").arg(argv[0]).arg(usage)); 00792 printQ("\n"+about->shortDescription()+"\n"); 00793 00794 printQ(optionHeaderString.arg(i18n("Generic options"))); 00795 printQ(optionFormatString.arg("--help", -25).arg(i18n("Show help about options"))); 00796 00797 args = argsList->first(); 00798 while(args) 00799 { 00800 if (args->name && args->id) 00801 { 00802 QString option = QString("--help-%1").arg(args->id); 00803 QString desc = i18n("Show %1 specific options").arg(args->name); 00804 00805 printQ(optionFormatString.arg(option, -25).arg(desc)); 00806 } 00807 args = argsList->next(); 00808 } 00809 00810 printQ(optionFormatString.arg("--help-all",-25).arg(i18n("Show all options"))); 00811 printQ(optionFormatString.arg("--author",-25).arg(i18n("Show author information"))); 00812 printQ(optionFormatString.arg("-v, --version",-25).arg(i18n("Show version information"))); 00813 printQ(optionFormatString.arg("--license",-25).arg(i18n("Show license information"))); 00814 printQ(optionFormatString.arg("--", -25).arg(i18n("End of options"))); 00815 00816 args = argsList->first(); // Sets current to 1st. 00817 00818 bool showAll = id && (::qstrcmp(id, "all") == 0); 00819 00820 if (!showAll) 00821 { 00822 while(args) 00823 { 00824 if (!id && !args->id) break; 00825 if (id && (::qstrcmp(args->id, id) == 0)) break; 00826 args = argsList->next(); 00827 } 00828 } 00829 00830 while(args) 00831 { 00832 bool hasArgs = false; 00833 bool hasOptions = false; 00834 QString optionsHeader; 00835 if (args->name) 00836 optionsHeader = optionHeaderString.arg(i18n("%1 options").arg(QString::fromLatin1(args->name))); 00837 else 00838 optionsHeader = i18n("\nOptions:\n"); 00839 00840 while (args) 00841 { 00842 const KCmdLineOptions *option = args->options; 00843 QCString opt = ""; 00844 // 00845 while(option && option->name) 00846 { 00847 QString description; 00848 QString descriptionRest; 00849 QStringList dl; 00850 00851 // Option header 00852 if (option->name[0] == ':') 00853 { 00854 if (option->description) 00855 { 00856 optionsHeader = "\n"+i18n(option->description); 00857 if (!optionsHeader.endsWith("\n")) 00858 optionsHeader.append("\n"); 00859 hasOptions = false; 00860 } 00861 option++; 00862 continue; 00863 } 00864 00865 // Free-form comment 00866 if (option->name[0] == 0) 00867 { 00868 if (option->description) 00869 { 00870 QString tmp = "\n"+i18n(option->description); 00871 if (!tmp.endsWith("\n")) 00872 tmp.append("\n"); 00873 printQ(tmp); 00874 } 00875 option++; 00876 continue; 00877 } 00878 00879 // Options 00880 if (option->description) 00881 { 00882 description = i18n(option->description); 00883 dl = QStringList::split("\n", description, true); 00884 description = dl.first(); 00885 dl.remove( dl.begin() ); 00886 } 00887 QCString name = option->name; 00888 if (name[0] == '!') 00889 name = name.mid(1); 00890 00891 if (name[0] == '+') 00892 { 00893 if (!hasArgs) 00894 { 00895 printQ(i18n("\nArguments:\n")); 00896 hasArgs = true; 00897 } 00898 00899 name = name.mid(1); 00900 if ((name[0] == '[') && (name[name.length()-1] == ']')) 00901 name = name.mid(1, name.length()-2); 00902 printQ(optionFormatString.arg(name, -25) 00903 .arg(description)); 00904 } 00905 else 00906 { 00907 if (!hasOptions) 00908 { 00909 printQ(optionsHeader); 00910 hasOptions = true; 00911 } 00912 00913 if ((name.length() == 1) || (name[1] == ' ')) 00914 name = "-"+name; 00915 else 00916 name = "--"+name; 00917 if (!option->description) 00918 { 00919 opt = name + ", "; 00920 } 00921 else 00922 { 00923 opt = opt + name; 00924 if (!option->def) 00925 { 00926 printQ(optionFormatString.arg(opt, -25) 00927 .arg(description)); 00928 } 00929 else 00930 { 00931 printQ(optionFormatStringDef.arg(opt, -25) 00932 .arg(description).arg(option->def)); 00933 } 00934 opt = ""; 00935 } 00936 } 00937 for(QStringList::Iterator it = dl.begin(); 00938 it != dl.end(); 00939 ++it) 00940 { 00941 printQ(optionFormatString.arg("", -25).arg(*it)); 00942 } 00943 00944 option++; 00945 } 00946 args = argsList->next(); 00947 if (!args || args->name || !args->id) break; 00948 } 00949 if (!showAll) break; 00950 } 00951 00952 exit(254); 00953 } 00954 00955 // 00956 // Member functions 00957 // 00958 00964 KCmdLineArgs::KCmdLineArgs( const KCmdLineOptions *_options, 00965 const char *_name, const char *_id) 00966 : options(_options), name(_name), id(_id) 00967 { 00968 parsedOptionList = 0; 00969 parsedArgList = 0; 00970 isQt = (::qstrcmp(id, "qt") == 0); 00971 } 00972 00976 KCmdLineArgs::~KCmdLineArgs() 00977 { 00978 delete parsedOptionList; 00979 delete parsedArgList; 00980 if (argsList) 00981 argsList->removeRef(this); 00982 } 00983 00984 void 00985 KCmdLineArgs::clear() 00986 { 00987 delete parsedArgList; 00988 parsedArgList = 0; 00989 delete parsedOptionList; 00990 parsedOptionList = 0; 00991 } 00992 00993 void 00994 KCmdLineArgs::reset() 00995 { 00996 if ( argsList ) { 00997 argsList->setAutoDelete( true ); 00998 argsList->clear(); 00999 delete argsList; 01000 argsList = 0; 01001 } 01002 parsed = false; 01003 } 01004 01005 void 01006 KCmdLineArgs::save( QDataStream &ds) const 01007 { 01008 uint count = 0; 01009 if (parsedOptionList) 01010 parsedOptionList->save( ds ); 01011 else 01012 ds << count; 01013 01014 if (parsedArgList) 01015 parsedArgList->save( ds ); 01016 else 01017 ds << count; 01018 } 01019 01020 void 01021 KCmdLineArgs::load( QDataStream &ds) 01022 { 01023 if (!parsedOptionList) parsedOptionList = new KCmdLineParsedOptions; 01024 if (!parsedArgList) parsedArgList = new KCmdLineParsedArgs; 01025 01026 parsedOptionList->load( ds ); 01027 parsedArgList->load( ds ); 01028 01029 if (parsedOptionList->count() == 0) 01030 { 01031 delete parsedOptionList; 01032 parsedOptionList = 0; 01033 } 01034 if (parsedArgList->count() == 0) 01035 { 01036 delete parsedArgList; 01037 parsedArgList = 0; 01038 } 01039 } 01040 01041 void 01042 KCmdLineArgs::setOption(const QCString &opt, bool enabled) 01043 { 01044 if (isQt) 01045 { 01046 // Qt does it own parsing. 01047 QCString arg = "-"; 01048 if( !enabled ) 01049 arg += "no"; 01050 arg += opt; 01051 addArgument(arg); 01052 } 01053 if (!parsedOptionList) { 01054 parsedOptionList = new KCmdLineParsedOptions; 01055 parsedOptionList->setAutoDelete(true); 01056 } 01057 01058 if (enabled) 01059 parsedOptionList->replace( opt, new QCString("t") ); 01060 else 01061 parsedOptionList->replace( opt, new QCString("f") ); 01062 } 01063 01064 void 01065 KCmdLineArgs::setOption(const QCString &opt, const char *value) 01066 { 01067 if (isQt) 01068 { 01069 // Qt does it's own parsing. 01070 QCString arg = "-"; 01071 arg += opt; 01072 addArgument(arg); 01073 addArgument(value); 01074 01075 // Hack coming up! 01076 if (arg == "-display") 01077 { 01078 setenv(DISPLAY, value, true); 01079 } 01080 } 01081 if (!parsedOptionList) { 01082 parsedOptionList = new KCmdLineParsedOptions; 01083 parsedOptionList->setAutoDelete(true); 01084 } 01085 01086 parsedOptionList->insert( opt, new QCString(value) ); 01087 } 01088 01089 QCString 01090 KCmdLineArgs::getOption(const char *_opt) const 01091 { 01092 QCString *value = 0; 01093 if (parsedOptionList) 01094 { 01095 value = parsedOptionList->find(_opt); 01096 } 01097 01098 if (value) 01099 return (*value); 01100 01101 // Look up the default. 01102 const char *opt_name; 01103 const char *def; 01104 bool dummy = true; 01105 QCString opt = _opt; 01106 int result = ::findOption( options, opt, opt_name, def, dummy) & ~4; 01107 01108 if (result != 3) 01109 { 01110 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n"); 01111 fprintf(stderr, "Application requests for getOption(\"%s\") but the \"%s\" option\n", 01112 _opt, _opt); 01113 fprintf(stderr, "has never been specified via addCmdLineOptions( ... )\n\n"); 01114 01115 assert( 0 ); 01116 exit(255); 01117 } 01118 return QCString(def); 01119 } 01120 01121 QCStringList 01122 KCmdLineArgs::getOptionList(const char *_opt) const 01123 { 01124 QCStringList result; 01125 if (!parsedOptionList) 01126 return result; 01127 01128 while(true) 01129 { 01130 QCString *value = parsedOptionList->take(_opt); 01131 if (!value) 01132 break; 01133 result.prepend(*value); 01134 delete value; 01135 } 01136 01137 // Reinsert items in dictionary 01138 // WABA: This is rather silly, but I don't want to add restrictions 01139 // to the API like "you can only call this function once". 01140 // I can't access all items without taking them out of the list. 01141 // So taking them out and then putting them back is the only way. 01142 for(QCStringList::ConstIterator it=result.begin(); 01143 it != result.end(); 01144 ++it) 01145 { 01146 parsedOptionList->insert(_opt, new QCString(*it)); 01147 } 01148 return result; 01149 } 01150 01151 bool 01152 KCmdLineArgs::isSet(const char *_opt) const 01153 { 01154 // Look up the default. 01155 const char *opt_name; 01156 const char *def; 01157 bool dummy = true; 01158 QCString opt = _opt; 01159 int result = ::findOption( options, opt, opt_name, def, dummy) & ~4; 01160 01161 if (result == 0) 01162 { 01163 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n"); 01164 fprintf(stderr, "Application requests for isSet(\"%s\") but the \"%s\" option\n", 01165 _opt, _opt); 01166 fprintf(stderr, "has never been specified via addCmdLineOptions( ... )\n\n"); 01167 01168 assert( 0 ); 01169 exit(255); 01170 } 01171 01172 QCString *value = 0; 01173 if (parsedOptionList) 01174 { 01175 value = parsedOptionList->find(opt); 01176 } 01177 01178 if (value) 01179 { 01180 if (result == 3) 01181 return true; 01182 else 01183 return ((*value)[0] == 't'); 01184 } 01185 01186 if (result == 3) 01187 return false; // String option has 'false' as default. 01188 01189 // We return 'true' as default if the option was listed as '-nofork' 01190 // We return 'false' as default if the option was listed as '-fork' 01191 return (result == 2); 01192 } 01193 01194 int 01195 KCmdLineArgs::count() const 01196 { 01197 if (!parsedArgList) 01198 return 0; 01199 return parsedArgList->count(); 01200 } 01201 01202 const char * 01203 KCmdLineArgs::arg(int n) const 01204 { 01205 if (!parsedArgList || (n >= (int) parsedArgList->count())) 01206 { 01207 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs): Argument out of bounds\n"); 01208 fprintf(stderr, "Application requests for arg(%d) without checking count() first.\n", 01209 n); 01210 01211 assert( 0 ); 01212 exit(255); 01213 } 01214 01215 return parsedArgList->at(n); 01216 } 01217 01218 KURL 01219 KCmdLineArgs::url(int n) const 01220 { 01221 return makeURL( arg(n) ); 01222 } 01223 01224 KURL KCmdLineArgs::makeURL( const char *urlArg ) 01225 { 01226 if (*urlArg == '/') 01227 { 01228 KURL result; 01229 result.setPath(QFile::decodeName( urlArg)); 01230 return result; // Absolute path. 01231 } 01232 01233 if ( !KURL::isRelativeURL( QString::fromLocal8Bit(urlArg) ) ) 01234 return KURL(QString::fromLocal8Bit(urlArg)); // Argument is a URL 01235 01236 KURL result; 01237 result.setPath( cwd()+"/"+QFile::decodeName( urlArg )); 01238 result.cleanPath(); 01239 return result; // Relative path 01240 } 01241 01242 void 01243 KCmdLineArgs::addArgument(const char *argument) 01244 { 01245 if (!parsedArgList) 01246 parsedArgList = new KCmdLineParsedArgs; 01247 01248 parsedArgList->append(argument); 01249 }
KDE Logo
This file is part of the documentation for kdecore Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Oct 8 11:13:59 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003