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