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