00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
00066
00067
00068
00069
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
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
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;
00223
00224 if (id && args->id && (::qstrcmp(id, args->id) == 0))
00225 return;
00226
00227 if (afterId && args->id && (::qstrcmp(afterId, args->id) == 0))
00228 pos = i+1;
00229 }
00230
00231 assert( parsed == false );
00232
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
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
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
00345
00346
00347
00348
00349
00350
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
00450
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;
00466
00467 p++;
00468 if (result == 1)
00469 {
00470 args->setOption(singleCharOption, enabled);
00471 if (_opt[p])
00472 continue;
00473 else
00474 return;
00475 }
00476 else if (result == 3)
00477 {
00478 if (argument.isEmpty())
00479 {
00480 argument = _opt+p;
00481 }
00482 args->setOption(singleCharOption, argument);
00483 return;
00484 }
00485 break;
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)
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
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();
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);
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();
00699
00700 static char** qt_argv;
00701 if( qt_argv != NULL )
00702 return &qt_argv;
00703
00704 KCmdLineArgs *args = parsedArgs("qt");
00705 assert(args);
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
00731 if (KGlobal::_locale)
00732 return;
00733
00734 if (!KGlobal::_instance) {
00735 KInstance *instance = new KInstance(about);
00736 (void) instance->config();
00737
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);
00761
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();
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
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
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
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
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
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
01080 QCString arg = "-";
01081 arg += opt;
01082 addArgument(arg);
01083 addArgument(value);
01084
01085 #ifdef Q_WS_X11
01086
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
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
01150
01151
01152
01153
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
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;
01200
01201
01202
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;
01244 }
01245
01246 if ( !KURL::isRelativeURL(urlArg) )
01247 return KURL(urlArg);
01248
01249 KURL result;
01250 result.setPath( cwd()+"/"+urlArg );
01251 result.cleanPath();
01252 return result;
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 }