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 }
00306
00307 KCmdLineArgs *KCmdLineArgs::parsedArgs(const char *id)
00308 {
00309 KCmdLineArgs *args = argsList ? argsList->first() : 0;
00310 while(args)
00311 {
00312 if ((id && ::qstrcmp(args->id, id) == 0) || (!id && !args->id))
00313 {
00314 if (!parsed)
00315 parseAllArgs();
00316 return args;
00317 }
00318 args = argsList->next();
00319 }
00320
00321 return args;
00322 }
00323
00324 void KCmdLineArgs::removeArgs(const char *id)
00325 {
00326 KCmdLineArgs *args = argsList ? argsList->first() : 0;
00327 while(args)
00328 {
00329 if (args->id && id && ::qstrcmp(args->id, id) == 0)
00330 {
00331 if (!parsed)
00332 parseAllArgs();
00333 break;
00334 }
00335 args = argsList->next();
00336 }
00337
00338 if (args)
00339 delete args;
00340 }
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 static int
00352 findOption(const KCmdLineOptions *options, QCString &opt,
00353 const char *&opt_name, const char *&def, bool &enabled)
00354 {
00355 int result;
00356 bool inverse;
00357 int len = opt.length();
00358 while(options && options->name)
00359 {
00360 result = 0;
00361 inverse = false;
00362 opt_name = options->name;
00363 if ((opt_name[0] == ':') || (opt_name[0] == 0))
00364 {
00365 options++;
00366 continue;
00367 }
00368
00369 if (opt_name[0] == '!')
00370 {
00371 opt_name++;
00372 result = 4;
00373 }
00374 if ((opt_name[0] == 'n') && (opt_name[1] == 'o'))
00375 {
00376 opt_name += 2;
00377 inverse = true;
00378 }
00379 if (strncmp(opt.data(), opt_name, len) == 0)
00380 {
00381 opt_name += len;
00382 if (!opt_name[0])
00383 {
00384 if (inverse)
00385 return result+2;
00386
00387 if (!options->description)
00388 {
00389 options++;
00390 if (!options->name)
00391 return result+0;
00392 QCString nextOption = options->name;
00393 int p = nextOption.find(' ');
00394 if (p > 0)
00395 nextOption = nextOption.left(p);
00396 if (strncmp(nextOption.data(), "no", 2) == 0)
00397 {
00398 nextOption = nextOption.mid(2);
00399 enabled = !enabled;
00400 }
00401 result = findOption(options, nextOption, opt_name, def, enabled);
00402 assert(result);
00403 opt = nextOption;
00404 return result;
00405 }
00406
00407 return 1;
00408 }
00409 if (opt_name[0] == ' ')
00410 {
00411 opt_name++;
00412 def = options->def;
00413 return result+3;
00414 }
00415 }
00416
00417 options++;
00418 }
00419 return 0;
00420 }
00421
00422
00423 void
00424 KCmdLineArgs::findOption(const char *_opt, QCString opt, int &i, bool _enabled, bool &moreOptions)
00425 {
00426 KCmdLineArgs *args = argsList->first();
00427 const char *opt_name;
00428 const char *def;
00429 QCString argument;
00430 int j = opt.find('=');
00431 if (j != -1)
00432 {
00433 argument = opt.mid(j+1);
00434 opt = opt.left(j);
00435 }
00436
00437 bool enabled = true;
00438 int result = 0;
00439 while (args)
00440 {
00441 enabled = _enabled;
00442 result = ::findOption(args->options, opt, opt_name, def, enabled);
00443 if (result) break;
00444 args = argsList->next();
00445 }
00446 if (!args && (_opt[0] == '-') && _opt[1] && (_opt[1] != '-'))
00447 {
00448
00449
00450 int p = 1;
00451 while (true)
00452 {
00453 QCString singleCharOption = " ";
00454 singleCharOption[0] = _opt[p];
00455 args = argsList->first();
00456 while (args)
00457 {
00458 enabled = _enabled;
00459 result = ::findOption(args->options, singleCharOption, opt_name, def, enabled);
00460 if (result) break;
00461 args = argsList->next();
00462 }
00463 if (!args)
00464 break;
00465
00466 p++;
00467 if (result == 1)
00468 {
00469 args->setOption(singleCharOption, enabled);
00470 if (_opt[p])
00471 continue;
00472 else
00473 return;
00474 }
00475 else if (result == 3)
00476 {
00477 if (argument.isEmpty())
00478 {
00479 argument = _opt+p;
00480 }
00481 args->setOption(singleCharOption, argument);
00482 return;
00483 }
00484 break;
00485 }
00486 args = 0;
00487 result = 0;
00488 }
00489
00490 if (!args || !result)
00491 {
00492 if (ignoreUnknown)
00493 return;
00494 enable_i18n();
00495 usage( i18n("Unknown option '%1'.").arg(QString::fromLocal8Bit(_opt)));
00496 }
00497
00498 if ((result & 4) != 0)
00499 {
00500 result &= ~4;
00501 moreOptions = false;
00502 }
00503
00504 if (result == 3)
00505 {
00506 if (!enabled)
00507 {
00508 if (ignoreUnknown)
00509 return;
00510 enable_i18n();
00511 usage( i18n("Unknown option '%1'.").arg(QString::fromLocal8Bit(_opt)));
00512 }
00513 if (argument.isEmpty())
00514 {
00515 i++;
00516 if (i >= argc)
00517 {
00518 enable_i18n();
00519 usage( i18n("'%1' missing.").arg( opt_name));
00520 }
00521 argument = argv[i];
00522 }
00523 args->setOption(opt, argument);
00524 }
00525 else
00526 {
00527 args->setOption(opt, enabled);
00528 }
00529 }
00530
00531 void
00532 KCmdLineArgs::printQ(const QString &msg)
00533 {
00534 QCString localMsg = msg.local8Bit();
00535 fprintf(stdout, "%s", localMsg.data());
00536 }
00537
00538 void
00539 KCmdLineArgs::parseAllArgs()
00540 {
00541 bool allowArgs = false;
00542 bool inOptions = true;
00543 bool everythingAfterArgIsArgs = false;
00544 KCmdLineArgs *appOptions = argsList->last();
00545 if (!appOptions->id)
00546 {
00547 const KCmdLineOptions *option = appOptions->options;
00548 while(option && option->name)
00549 {
00550 if (option->name[0] == '+')
00551 allowArgs = true;
00552 if ( option->name[0] == '!' && option->name[1] == '+' )
00553 {
00554 allowArgs = true;
00555 everythingAfterArgIsArgs = true;
00556 }
00557 option++;
00558 }
00559 }
00560 for(int i = 1; i < argc; i++)
00561 {
00562 if (!argv[i])
00563 continue;
00564
00565 if ((argv[i][0] == '-') && argv[i][1] && inOptions)
00566 {
00567 bool enabled = true;
00568 const char *option = &argv[i][1];
00569 const char *orig = argv[i];
00570 if (option[0] == '-')
00571 {
00572 option++;
00573 argv[i]++;
00574 if (!option[0])
00575 {
00576 inOptions = false;
00577 continue;
00578 }
00579 }
00580 if (::qstrcmp(option, "help") == 0)
00581 {
00582 usage(0);
00583 }
00584 else if (strncmp(option, "help-",5) == 0)
00585 {
00586 usage(option+5);
00587 }
00588 else if ( (::qstrcmp(option, "version") == 0) ||
00589 (::qstrcmp(option, "v") == 0))
00590 {
00591 printQ( QString("Qt: %1\n").arg(qVersion()));
00592 printQ( QString("KDE: %1\n").arg(KDE_VERSION_STRING));
00593 printQ( QString("%1: %2\n").
00594 arg(about->programName()).arg(about->version()));
00595 exit(0);
00596 } else if ( (::qstrcmp(option, "license") == 0) )
00597 {
00598 enable_i18n();
00599 printQ( about->license() );
00600 printQ( "\n" );
00601 exit(0);
00602 } else if ( ::qstrcmp( option, "author") == 0 ) {
00603 enable_i18n();
00604 if ( about ) {
00605 const QValueList<KAboutPerson> authors = about->authors();
00606 if ( !authors.isEmpty() ) {
00607 QString authorlist;
00608 for (QValueList<KAboutPerson>::ConstIterator it = authors.begin(); it != authors.end(); ++it ) {
00609 QString email;
00610 if ( !(*it).emailAddress().isEmpty() )
00611 email = " <" + (*it).emailAddress() + ">";
00612 authorlist += QString(" ") + (*it).name() + email + "\n";
00613 }
00614 printQ( i18n("the 2nd argument is a list of name+address, one on each line","%1 was written by\n%2").arg ( QString(about->programName()) ).arg( authorlist ) );
00615 }
00616 } else {
00617 printQ( i18n("%1 was written by somebody who wants to remain anonymous.").arg(about->programName()) );
00618 }
00619 if (!about->bugAddress().isEmpty())
00620 {
00621 if (about->bugAddress() == "submit@bugs.kde.org")
00622 printQ( i18n( "Please use http://bugs.kde.org to report bugs, do not mail the authors directly.\n" ) );
00623 else
00624 printQ( i18n( "Please use %1 to report bugs, do not mail the authors directly.\n" ).arg(about->bugAddress()) );
00625 }
00626 exit(0);
00627 } else {
00628 if ((option[0] == 'n') && (option[1] == 'o'))
00629 {
00630 option += 2;
00631 enabled = false;
00632 }
00633 findOption(orig, option, i, enabled, inOptions);
00634 }
00635 }
00636 else
00637 {
00638
00639 if (!allowArgs)
00640 {
00641 if (ignoreUnknown)
00642 continue;
00643 enable_i18n();
00644 usage( i18n("Unexpected argument '%1'.").arg(QString::fromLocal8Bit(argv[i])));
00645 }
00646 else
00647 {
00648 appOptions->addArgument(argv[i]);
00649 if (everythingAfterArgIsArgs)
00650 inOptions = false;
00651 }
00652 }
00653 }
00654 parsed = true;
00655 }
00656
00662 int *
00663 KCmdLineArgs::qt_argc()
00664 {
00665 if (!argsList)
00666 KApplication::addCmdLineOptions();
00667
00668 static int qt_argc = -1;
00669 if( qt_argc != -1 )
00670 return &qt_argc;
00671
00672 KCmdLineArgs *args = parsedArgs("qt");
00673 assert(args);
00674 if (!argv)
00675 {
00676 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
00677 fprintf(stderr, "Application has not called KCmdLineArgs::init(...).\n\n");
00678
00679 assert( 0 );
00680 exit(255);
00681 }
00682
00683 assert(argc >= (args->count()+1));
00684 qt_argc = args->count() +1;
00685 return &qt_argc;
00686 }
00687
00693 char ***
00694 KCmdLineArgs::qt_argv()
00695 {
00696 if (!argsList)
00697 KApplication::addCmdLineOptions();
00698
00699 static char** qt_argv;
00700 if( qt_argv != NULL )
00701 return &qt_argv;
00702
00703 KCmdLineArgs *args = parsedArgs("qt");
00704 assert(args);
00705 if (!argv)
00706 {
00707 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
00708 fprintf(stderr, "Application has not called KCmdLineArgs::init(...).\n\n");
00709
00710 assert( 0 );
00711 exit(255);
00712 }
00713
00714 qt_argv = new char*[ args->count() + 2 ];
00715 qt_argv[ 0 ] = qstrdup( appName());
00716 int i = 0;
00717 for(; i < args->count(); i++)
00718 {
00719 qt_argv[i+1] = qstrdup((char *) args->arg(i));
00720 }
00721 qt_argv[i+1] = 0;
00722
00723 return &qt_argv;
00724 }
00725
00726 void
00727 KCmdLineArgs::enable_i18n()
00728 {
00729
00730 if (KGlobal::_locale)
00731 return;
00732
00733 if (!KGlobal::_instance) {
00734 KInstance *instance = new KInstance(about);
00735 (void) instance->config();
00736
00737 }
00738 }
00739
00740 void
00741 KCmdLineArgs::usage(const QString &error)
00742 {
00743 assert(KGlobal::_locale);
00744 QCString localError = error.local8Bit();
00745 if (localError[error.length()-1] == '\n')
00746 localError = localError.left(error.length()-1);
00747 fprintf(stderr, "%s: %s\n", argv[0], localError.data());
00748
00749 QString tmp = i18n("Use --help to get a list of available command line options.");
00750 localError = tmp.local8Bit();
00751 fprintf(stderr, "%s: %s\n", argv[0], localError.data());
00752 exit(254);
00753 }
00754
00755 void
00756 KCmdLineArgs::usage(const char *id)
00757 {
00758 enable_i18n();
00759 assert(argsList != 0);
00760
00761
00762 QString optionFormatString = " %1 %2\n";
00763 QString optionFormatStringDef = " %1 %2 [%3]\n";
00764 QString optionHeaderString = i18n("\n%1:\n");
00765 QString tmp;
00766 QString usage;
00767
00768 KCmdLineArgs *args = argsList->last();
00769
00770 if (!(args->id) && (args->options) &&
00771 (args->options->name) && (args->options->name[0] != '+'))
00772 {
00773 usage = i18n("[options] ")+usage;
00774 }
00775
00776 while(args)
00777 {
00778 if (args->name)
00779 {
00780 usage = i18n("[%1-options]").arg(args->name)+" "+usage;
00781 }
00782 args = argsList->prev();
00783 }
00784
00785 KCmdLineArgs *appOptions = argsList->last();
00786 if (!appOptions->id)
00787 {
00788 const KCmdLineOptions *option = appOptions->options;
00789 while(option && option->name)
00790 {
00791 if (option->name[0] == '+')
00792 usage = usage + (option->name+1) + " ";
00793 else if ( option->name[0] == '!' && option->name[1] == '+' )
00794 usage = usage + (option->name+2) + " ";
00795
00796 option++;
00797 }
00798 }
00799
00800 printQ(i18n("Usage: %1 %2\n").arg(argv[0]).arg(usage));
00801 printQ("\n"+about->shortDescription()+"\n");
00802
00803 printQ(optionHeaderString.arg(i18n("Generic options")));
00804 printQ(optionFormatString.arg("--help", -25).arg(i18n("Show help about options")));
00805
00806 args = argsList->first();
00807 while(args)
00808 {
00809 if (args->name && args->id)
00810 {
00811 QString option = QString("--help-%1").arg(args->id);
00812 QString desc = i18n("Show %1 specific options").arg(args->name);
00813
00814 printQ(optionFormatString.arg(option, -25).arg(desc));
00815 }
00816 args = argsList->next();
00817 }
00818
00819 printQ(optionFormatString.arg("--help-all",-25).arg(i18n("Show all options")));
00820 printQ(optionFormatString.arg("--author",-25).arg(i18n("Show author information")));
00821 printQ(optionFormatString.arg("-v, --version",-25).arg(i18n("Show version information")));
00822 printQ(optionFormatString.arg("--license",-25).arg(i18n("Show license information")));
00823 printQ(optionFormatString.arg("--", -25).arg(i18n("End of options")));
00824
00825 args = argsList->first();
00826
00827 bool showAll = id && (::qstrcmp(id, "all") == 0);
00828
00829 if (!showAll)
00830 {
00831 while(args)
00832 {
00833 if (!id && !args->id) break;
00834 if (id && (::qstrcmp(args->id, id) == 0)) break;
00835 args = argsList->next();
00836 }
00837 }
00838
00839 while(args)
00840 {
00841 bool hasArgs = false;
00842 bool hasOptions = false;
00843 QString optionsHeader;
00844 if (args->name)
00845 optionsHeader = optionHeaderString.arg(i18n("%1 options").arg(QString::fromLatin1(args->name)));
00846 else
00847 optionsHeader = i18n("\nOptions:\n");
00848
00849 while (args)
00850 {
00851 const KCmdLineOptions *option = args->options;
00852 QCString opt = "";
00853
00854 while(option && option->name)
00855 {
00856 QString description;
00857 QString descriptionRest;
00858 QStringList dl;
00859
00860
00861 if (option->name[0] == ':')
00862 {
00863 if (option->description)
00864 {
00865 optionsHeader = "\n"+i18n(option->description);
00866 if (!optionsHeader.endsWith("\n"))
00867 optionsHeader.append("\n");
00868 hasOptions = false;
00869 }
00870 option++;
00871 continue;
00872 }
00873
00874
00875 if (option->name[0] == 0)
00876 {
00877 if (option->description)
00878 {
00879 QString tmp = "\n"+i18n(option->description);
00880 if (!tmp.endsWith("\n"))
00881 tmp.append("\n");
00882 printQ(tmp);
00883 }
00884 option++;
00885 continue;
00886 }
00887
00888
00889 if (option->description)
00890 {
00891 description = i18n(option->description);
00892 dl = QStringList::split("\n", description, true);
00893 description = dl.first();
00894 dl.remove( dl.begin() );
00895 }
00896 QCString name = option->name;
00897 if (name[0] == '!')
00898 name = name.mid(1);
00899
00900 if (name[0] == '+')
00901 {
00902 if (!hasArgs)
00903 {
00904 printQ(i18n("\nArguments:\n"));
00905 hasArgs = true;
00906 }
00907
00908 name = name.mid(1);
00909 if ((name[0] == '[') && (name[name.length()-1] == ']'))
00910 name = name.mid(1, name.length()-2);
00911 printQ(optionFormatString.arg(name, -25)
00912 .arg(description));
00913 }
00914 else
00915 {
00916 if (!hasOptions)
00917 {
00918 printQ(optionsHeader);
00919 hasOptions = true;
00920 }
00921
00922 if ((name.length() == 1) || (name[1] == ' '))
00923 name = "-"+name;
00924 else
00925 name = "--"+name;
00926 if (!option->description)
00927 {
00928 opt = name + ", ";
00929 }
00930 else
00931 {
00932 opt = opt + name;
00933 if (!option->def)
00934 {
00935 printQ(optionFormatString.arg(opt, -25)
00936 .arg(description));
00937 }
00938 else
00939 {
00940 printQ(optionFormatStringDef.arg(opt, -25)
00941 .arg(description).arg(option->def));
00942 }
00943 opt = "";
00944 }
00945 }
00946 for(QStringList::Iterator it = dl.begin();
00947 it != dl.end();
00948 ++it)
00949 {
00950 printQ(optionFormatString.arg("", -25).arg(*it));
00951 }
00952
00953 option++;
00954 }
00955 args = argsList->next();
00956 if (!args || args->name || !args->id) break;
00957 }
00958 if (!showAll) break;
00959 }
00960
00961 exit(254);
00962 }
00963
00964
00965
00966
00967
00973 KCmdLineArgs::KCmdLineArgs( const KCmdLineOptions *_options,
00974 const char *_name, const char *_id)
00975 : options(_options), name(_name), id(_id)
00976 {
00977 parsedOptionList = 0;
00978 parsedArgList = 0;
00979 isQt = (::qstrcmp(id, "qt") == 0);
00980 }
00981
00985 KCmdLineArgs::~KCmdLineArgs()
00986 {
00987 delete parsedOptionList;
00988 delete parsedArgList;
00989 if (argsList)
00990 argsList->removeRef(this);
00991 }
00992
00993 void
00994 KCmdLineArgs::clear()
00995 {
00996 delete parsedArgList;
00997 parsedArgList = 0;
00998 delete parsedOptionList;
00999 parsedOptionList = 0;
01000 }
01001
01002 void
01003 KCmdLineArgs::reset()
01004 {
01005 if ( argsList ) {
01006 argsList->setAutoDelete( true );
01007 argsList->clear();
01008 delete argsList;
01009 argsList = 0;
01010 }
01011 parsed = false;
01012 }
01013
01014 void
01015 KCmdLineArgs::save( QDataStream &ds) const
01016 {
01017 uint count = 0;
01018 if (parsedOptionList)
01019 parsedOptionList->save( ds );
01020 else
01021 ds << count;
01022
01023 if (parsedArgList)
01024 parsedArgList->save( ds );
01025 else
01026 ds << count;
01027 }
01028
01029 void
01030 KCmdLineArgs::load( QDataStream &ds)
01031 {
01032 if (!parsedOptionList) parsedOptionList = new KCmdLineParsedOptions;
01033 if (!parsedArgList) parsedArgList = new KCmdLineParsedArgs;
01034
01035 parsedOptionList->load( ds );
01036 parsedArgList->load( ds );
01037
01038 if (parsedOptionList->count() == 0)
01039 {
01040 delete parsedOptionList;
01041 parsedOptionList = 0;
01042 }
01043 if (parsedArgList->count() == 0)
01044 {
01045 delete parsedArgList;
01046 parsedArgList = 0;
01047 }
01048 }
01049
01050 void
01051 KCmdLineArgs::setOption(const QCString &opt, bool enabled)
01052 {
01053 if (isQt)
01054 {
01055
01056 QCString arg = "-";
01057 if( !enabled )
01058 arg += "no";
01059 arg += opt;
01060 addArgument(arg);
01061 }
01062 if (!parsedOptionList) {
01063 parsedOptionList = new KCmdLineParsedOptions;
01064 parsedOptionList->setAutoDelete(true);
01065 }
01066
01067 if (enabled)
01068 parsedOptionList->replace( opt, new QCString("t") );
01069 else
01070 parsedOptionList->replace( opt, new QCString("f") );
01071 }
01072
01073 void
01074 KCmdLineArgs::setOption(const QCString &opt, const char *value)
01075 {
01076 if (isQt)
01077 {
01078
01079 QCString arg = "-";
01080 arg += opt;
01081 addArgument(arg);
01082 addArgument(value);
01083
01084 #ifdef Q_WS_X11
01085
01086 if (arg == "-display")
01087 {
01088 setenv(DISPLAY, value, true);
01089 }
01090 #endif
01091 }
01092 if (!parsedOptionList) {
01093 parsedOptionList = new KCmdLineParsedOptions;
01094 parsedOptionList->setAutoDelete(true);
01095 }
01096
01097 parsedOptionList->insert( opt, new QCString(value) );
01098 }
01099
01100 QCString
01101 KCmdLineArgs::getOption(const char *_opt) const
01102 {
01103 QCString *value = 0;
01104 if (parsedOptionList)
01105 {
01106 value = parsedOptionList->find(_opt);
01107 }
01108
01109 if (value)
01110 return (*value);
01111
01112
01113 const char *opt_name;
01114 const char *def;
01115 bool dummy = true;
01116 QCString opt = _opt;
01117 int result = ::findOption( options, opt, opt_name, def, dummy) & ~4;
01118
01119 if (result != 3)
01120 {
01121 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
01122 fprintf(stderr, "Application requests for getOption(\"%s\") but the \"%s\" option\n",
01123 _opt, _opt);
01124 fprintf(stderr, "has never been specified via addCmdLineOptions( ... )\n\n");
01125
01126 assert( 0 );
01127 exit(255);
01128 }
01129 return QCString(def);
01130 }
01131
01132 QCStringList
01133 KCmdLineArgs::getOptionList(const char *_opt) const
01134 {
01135 QCStringList result;
01136 if (!parsedOptionList)
01137 return result;
01138
01139 while(true)
01140 {
01141 QCString *value = parsedOptionList->take(_opt);
01142 if (!value)
01143 break;
01144 result.prepend(*value);
01145 delete value;
01146 }
01147
01148
01149
01150
01151
01152
01153 for(QCStringList::ConstIterator it=result.begin();
01154 it != result.end();
01155 ++it)
01156 {
01157 parsedOptionList->insert(_opt, new QCString(*it));
01158 }
01159 return result;
01160 }
01161
01162 bool
01163 KCmdLineArgs::isSet(const char *_opt) const
01164 {
01165
01166 const char *opt_name;
01167 const char *def;
01168 bool dummy = true;
01169 QCString opt = _opt;
01170 int result = ::findOption( options, opt, opt_name, def, dummy) & ~4;
01171
01172 if (result == 0)
01173 {
01174 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
01175 fprintf(stderr, "Application requests for isSet(\"%s\") but the \"%s\" option\n",
01176 _opt, _opt);
01177 fprintf(stderr, "has never been specified via addCmdLineOptions( ... )\n\n");
01178
01179 assert( 0 );
01180 exit(255);
01181 }
01182
01183 QCString *value = 0;
01184 if (parsedOptionList)
01185 {
01186 value = parsedOptionList->find(opt);
01187 }
01188
01189 if (value)
01190 {
01191 if (result == 3)
01192 return true;
01193 else
01194 return ((*value)[0] == 't');
01195 }
01196
01197 if (result == 3)
01198 return false;
01199
01200
01201
01202 return (result == 2);
01203 }
01204
01205 int
01206 KCmdLineArgs::count() const
01207 {
01208 if (!parsedArgList)
01209 return 0;
01210 return parsedArgList->count();
01211 }
01212
01213 const char *
01214 KCmdLineArgs::arg(int n) const
01215 {
01216 if (!parsedArgList || (n >= (int) parsedArgList->count()))
01217 {
01218 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs): Argument out of bounds\n");
01219 fprintf(stderr, "Application requests for arg(%d) without checking count() first.\n",
01220 n);
01221
01222 assert( 0 );
01223 exit(255);
01224 }
01225
01226 return parsedArgList->at(n);
01227 }
01228
01229 KURL
01230 KCmdLineArgs::url(int n) const
01231 {
01232 return makeURL( arg(n) );
01233 }
01234
01235 KURL KCmdLineArgs::makeURL(const char *_urlArg)
01236 {
01237 QString urlArg = QFile::decodeName(_urlArg);
01238 if (!QDir::isRelativePath(urlArg))
01239 {
01240 KURL result;
01241 result.setPath(urlArg);
01242 return result;
01243 }
01244
01245 if ( !KURL::isRelativeURL(urlArg) )
01246 return KURL(urlArg);
01247
01248 KURL result;
01249 result.setPath( cwd()+"/"+urlArg );
01250 result.cleanPath();
01251 return result;
01252 }
01253
01254 void
01255 KCmdLineArgs::addArgument(const char *argument)
01256 {
01257 if (!parsedArgList)
01258 parsedArgList = new KCmdLineParsedArgs;
01259
01260 parsedArgList->append(argument);
01261 }
01262
01263 static const KCmdLineOptions kde_tempfile_option[] =
01264 {
01265 { "tempfile", I18N_NOOP("The files/URLs opened by the application will be deleted after use"), 0},
01266 KCmdLineLastOption
01267 };
01268
01269 void
01270 KCmdLineArgs::addTempFileOption()
01271 {
01272 KCmdLineArgs::addCmdLineOptions( kde_tempfile_option, "KDE-tempfile", "kde-tempfile" );
01273 }
01274
01275 bool KCmdLineArgs::isTempFileSet()
01276 {
01277 KCmdLineArgs* args = KCmdLineArgs::parsedArgs( "kde-tempfile" );
01278 if ( args )
01279 return args->isSet( "tempfile" );
01280 return false;
01281 }