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 (void) 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("This application was written by somebody who wants to remain anonymous.") );
00619 }
00620 if (about)
00621 {
00622 if (!about->customAuthorTextEnabled ())
00623 {
00624 if (about->bugAddress().isEmpty() || about->bugAddress() == "submit@bugs.kde.org" )
00625 printQ( i18n( "Please use http://bugs.kde.org to report bugs.\n" ) );
00626 else {
00627 if( about->authors().count() == 1 && about->authors().first().emailAddress() == about->bugAddress() )
00628 printQ( i18n( "Please report bugs to %1.\n" ).arg( about->authors().first().emailAddress() ) );
00629 else
00630 printQ( i18n( "Please report bugs to %1.\n" ).arg(about->bugAddress()) );
00631 }
00632 }
00633 else
00634 {
00635 printQ(about->customAuthorPlainText());
00636 }
00637 }
00638 exit(0);
00639 } else {
00640 if ((option[0] == 'n') && (option[1] == 'o'))
00641 {
00642 option += 2;
00643 enabled = false;
00644 }
00645 findOption(orig, option, i, enabled, inOptions);
00646 }
00647 }
00648 else
00649 {
00650
00651 if (!allowArgs)
00652 {
00653 if (ignoreUnknown)
00654 continue;
00655 enable_i18n();
00656 usage( i18n("Unexpected argument '%1'.").arg(QString::fromLocal8Bit(argv[i])));
00657 }
00658 else
00659 {
00660 appOptions->addArgument(argv[i]);
00661 if (everythingAfterArgIsArgs)
00662 inOptions = false;
00663 }
00664 }
00665 }
00666 parsed = true;
00667 }
00668
00674 int *
00675 KCmdLineArgs::qt_argc()
00676 {
00677 if (!argsList)
00678 KApplication::addCmdLineOptions();
00679
00680 static int qt_argc = -1;
00681 if( qt_argc != -1 )
00682 return &qt_argc;
00683
00684 KCmdLineArgs *args = parsedArgs("qt");
00685 assert(args);
00686 if (!argv)
00687 {
00688 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
00689 fprintf(stderr, "Application has not called KCmdLineArgs::init(...).\n\n");
00690
00691 assert( 0 );
00692 exit(255);
00693 }
00694
00695 assert(argc >= (args->count()+1));
00696 qt_argc = args->count() +1;
00697 return &qt_argc;
00698 }
00699
00705 char ***
00706 KCmdLineArgs::qt_argv()
00707 {
00708 if (!argsList)
00709 KApplication::addCmdLineOptions();
00710
00711 static char** qt_argv;
00712 if( qt_argv != NULL )
00713 return &qt_argv;
00714
00715 KCmdLineArgs *args = parsedArgs("qt");
00716 assert(args);
00717 if (!argv)
00718 {
00719 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
00720 fprintf(stderr, "Application has not called KCmdLineArgs::init(...).\n\n");
00721
00722 assert( 0 );
00723 exit(255);
00724 }
00725
00726 qt_argv = new char*[ args->count() + 2 ];
00727 qt_argv[ 0 ] = qstrdup( appName());
00728 int i = 0;
00729 for(; i < args->count(); i++)
00730 {
00731 qt_argv[i+1] = qstrdup((char *) args->arg(i));
00732 }
00733 qt_argv[i+1] = 0;
00734
00735 return &qt_argv;
00736 }
00737
00738 void
00739 KCmdLineArgs::enable_i18n()
00740 {
00741
00742 if (KGlobal::_locale)
00743 return;
00744
00745 if (!KGlobal::_instance) {
00746 KInstance *instance = new KInstance(about);
00747 (void) instance->config();
00748
00749 }
00750 }
00751
00752 void
00753 KCmdLineArgs::usage(const QString &error)
00754 {
00755 assert(KGlobal::_locale);
00756 QCString localError = error.local8Bit();
00757 if (localError[error.length()-1] == '\n')
00758 localError = localError.left(error.length()-1);
00759 fprintf(stderr, "%s: %s\n", argv[0], localError.data());
00760
00761 QString tmp = i18n("Use --help to get a list of available command line options.");
00762 localError = tmp.local8Bit();
00763 fprintf(stderr, "%s: %s\n", argv[0], localError.data());
00764 exit(254);
00765 }
00766
00767 void
00768 KCmdLineArgs::usage(const char *id)
00769 {
00770 enable_i18n();
00771 assert(argsList != 0);
00772
00773
00774 QString optionFormatString = " %1 %2\n";
00775 QString optionFormatStringDef = " %1 %2 [%3]\n";
00776 QString optionHeaderString = i18n("\n%1:\n");
00777 QString tmp;
00778 QString usage;
00779
00780 KCmdLineArgs *args = argsList->last();
00781
00782 if (!(args->id) && (args->options) &&
00783 (args->options->name) && (args->options->name[0] != '+'))
00784 {
00785 usage = i18n("[options] ")+usage;
00786 }
00787
00788 while(args)
00789 {
00790 if (args->name)
00791 {
00792 usage = i18n("[%1-options]").arg(args->name)+" "+usage;
00793 }
00794 args = argsList->prev();
00795 }
00796
00797 KCmdLineArgs *appOptions = argsList->last();
00798 if (!appOptions->id)
00799 {
00800 const KCmdLineOptions *option = appOptions->options;
00801 while(option && option->name)
00802 {
00803 if (option->name[0] == '+')
00804 usage = usage + (option->name+1) + " ";
00805 else if ( option->name[0] == '!' && option->name[1] == '+' )
00806 usage = usage + (option->name+2) + " ";
00807
00808 option++;
00809 }
00810 }
00811
00812 printQ(i18n("Usage: %1 %2\n").arg(argv[0]).arg(usage));
00813 printQ("\n"+about->shortDescription()+"\n");
00814
00815 printQ(optionHeaderString.arg(i18n("Generic options")));
00816 printQ(optionFormatString.arg("--help", -25).arg(i18n("Show help about options")));
00817
00818 args = argsList->first();
00819 while(args)
00820 {
00821 if (args->name && args->id)
00822 {
00823 QString option = QString("--help-%1").arg(args->id);
00824 QString desc = i18n("Show %1 specific options").arg(args->name);
00825
00826 printQ(optionFormatString.arg(option, -25).arg(desc));
00827 }
00828 args = argsList->next();
00829 }
00830
00831 printQ(optionFormatString.arg("--help-all",-25).arg(i18n("Show all options")));
00832 printQ(optionFormatString.arg("--author",-25).arg(i18n("Show author information")));
00833 printQ(optionFormatString.arg("-v, --version",-25).arg(i18n("Show version information")));
00834 printQ(optionFormatString.arg("--license",-25).arg(i18n("Show license information")));
00835 printQ(optionFormatString.arg("--", -25).arg(i18n("End of options")));
00836
00837 args = argsList->first();
00838
00839 bool showAll = id && (::qstrcmp(id, "all") == 0);
00840
00841 if (!showAll)
00842 {
00843 while(args)
00844 {
00845 if (!id && !args->id) break;
00846 if (id && (::qstrcmp(args->id, id) == 0)) break;
00847 args = argsList->next();
00848 }
00849 }
00850
00851 while(args)
00852 {
00853 bool hasArgs = false;
00854 bool hasOptions = false;
00855 QString optionsHeader;
00856 if (args->name)
00857 optionsHeader = optionHeaderString.arg(i18n("%1 options").arg(QString::fromLatin1(args->name)));
00858 else
00859 optionsHeader = i18n("\nOptions:\n");
00860
00861 while (args)
00862 {
00863 const KCmdLineOptions *option = args->options;
00864 QCString opt = "";
00865
00866 while(option && option->name)
00867 {
00868 QString description;
00869 QString descriptionRest;
00870 QStringList dl;
00871
00872
00873 if (option->name[0] == ':')
00874 {
00875 if (option->description)
00876 {
00877 optionsHeader = "\n"+i18n(option->description);
00878 if (!optionsHeader.endsWith("\n"))
00879 optionsHeader.append("\n");
00880 hasOptions = false;
00881 }
00882 option++;
00883 continue;
00884 }
00885
00886
00887 if (option->name[0] == 0)
00888 {
00889 if (option->description)
00890 {
00891 QString tmp = "\n"+i18n(option->description);
00892 if (!tmp.endsWith("\n"))
00893 tmp.append("\n");
00894 printQ(tmp);
00895 }
00896 option++;
00897 continue;
00898 }
00899
00900
00901 if (option->description)
00902 {
00903 description = i18n(option->description);
00904 dl = QStringList::split("\n", description, true);
00905 description = dl.first();
00906 dl.remove( dl.begin() );
00907 }
00908 QCString name = option->name;
00909 if (name[0] == '!')
00910 name = name.mid(1);
00911
00912 if (name[0] == '+')
00913 {
00914 if (!hasArgs)
00915 {
00916 printQ(i18n("\nArguments:\n"));
00917 hasArgs = true;
00918 }
00919
00920 name = name.mid(1);
00921 if ((name[0] == '[') && (name[name.length()-1] == ']'))
00922 name = name.mid(1, name.length()-2);
00923 printQ(optionFormatString.arg(name, -25)
00924 .arg(description));
00925 }
00926 else
00927 {
00928 if (!hasOptions)
00929 {
00930 printQ(optionsHeader);
00931 hasOptions = true;
00932 }
00933
00934 if ((name.length() == 1) || (name[1] == ' '))
00935 name = "-"+name;
00936 else
00937 name = "--"+name;
00938 if (!option->description)
00939 {
00940 opt = name + ", ";
00941 }
00942 else
00943 {
00944 opt = opt + name;
00945 if (!option->def)
00946 {
00947 printQ(optionFormatString.arg(opt, -25)
00948 .arg(description));
00949 }
00950 else
00951 {
00952 printQ(optionFormatStringDef.arg(opt, -25)
00953 .arg(description).arg(option->def));
00954 }
00955 opt = "";
00956 }
00957 }
00958 for(QStringList::Iterator it = dl.begin();
00959 it != dl.end();
00960 ++it)
00961 {
00962 printQ(optionFormatString.arg("", -25).arg(*it));
00963 }
00964
00965 option++;
00966 }
00967 args = argsList->next();
00968 if (!args || args->name || !args->id) break;
00969 }
00970 if (!showAll) break;
00971 }
00972
00973 exit(254);
00974 }
00975
00976
00977
00978
00979
00985 KCmdLineArgs::KCmdLineArgs( const KCmdLineOptions *_options,
00986 const char *_name, const char *_id)
00987 : options(_options), name(_name), id(_id)
00988 {
00989 parsedOptionList = 0;
00990 parsedArgList = 0;
00991 isQt = (::qstrcmp(id, "qt") == 0);
00992 }
00993
00997 KCmdLineArgs::~KCmdLineArgs()
00998 {
00999 delete parsedOptionList;
01000 delete parsedArgList;
01001 if (argsList)
01002 argsList->removeRef(this);
01003 }
01004
01005 void
01006 KCmdLineArgs::clear()
01007 {
01008 delete parsedArgList;
01009 parsedArgList = 0;
01010 delete parsedOptionList;
01011 parsedOptionList = 0;
01012 }
01013
01014 void
01015 KCmdLineArgs::reset()
01016 {
01017 if ( argsList ) {
01018 argsList->setAutoDelete( true );
01019 argsList->clear();
01020 delete argsList;
01021 argsList = 0;
01022 }
01023 parsed = false;
01024 }
01025
01026 void
01027 KCmdLineArgs::save( QDataStream &ds) const
01028 {
01029 uint count = 0;
01030 if (parsedOptionList)
01031 parsedOptionList->save( ds );
01032 else
01033 ds << count;
01034
01035 if (parsedArgList)
01036 parsedArgList->save( ds );
01037 else
01038 ds << count;
01039 }
01040
01041 void
01042 KCmdLineArgs::load( QDataStream &ds)
01043 {
01044 if (!parsedOptionList) parsedOptionList = new KCmdLineParsedOptions;
01045 if (!parsedArgList) parsedArgList = new KCmdLineParsedArgs;
01046
01047 parsedOptionList->load( ds );
01048 parsedArgList->load( ds );
01049
01050 if (parsedOptionList->count() == 0)
01051 {
01052 delete parsedOptionList;
01053 parsedOptionList = 0;
01054 }
01055 if (parsedArgList->count() == 0)
01056 {
01057 delete parsedArgList;
01058 parsedArgList = 0;
01059 }
01060 }
01061
01062 void
01063 KCmdLineArgs::setOption(const QCString &opt, bool enabled)
01064 {
01065 if (isQt)
01066 {
01067
01068 QCString arg = "-";
01069 if( !enabled )
01070 arg += "no";
01071 arg += opt;
01072 addArgument(arg);
01073 }
01074 if (!parsedOptionList) {
01075 parsedOptionList = new KCmdLineParsedOptions;
01076 parsedOptionList->setAutoDelete(true);
01077 }
01078
01079 if (enabled)
01080 parsedOptionList->replace( opt, new QCString("t") );
01081 else
01082 parsedOptionList->replace( opt, new QCString("f") );
01083 }
01084
01085 void
01086 KCmdLineArgs::setOption(const QCString &opt, const char *value)
01087 {
01088 if (isQt)
01089 {
01090
01091 QCString arg = "-";
01092 arg += opt;
01093 addArgument(arg);
01094 addArgument(value);
01095
01096 #ifdef Q_WS_X11
01097
01098 if (arg == "-display")
01099 {
01100 setenv(DISPLAY, value, true);
01101 }
01102 #endif
01103 }
01104 if (!parsedOptionList) {
01105 parsedOptionList = new KCmdLineParsedOptions;
01106 parsedOptionList->setAutoDelete(true);
01107 }
01108
01109 parsedOptionList->insert( opt, new QCString(value) );
01110 }
01111
01112 QCString
01113 KCmdLineArgs::getOption(const char *_opt) const
01114 {
01115 QCString *value = 0;
01116 if (parsedOptionList)
01117 {
01118 value = parsedOptionList->find(_opt);
01119 }
01120
01121 if (value)
01122 return (*value);
01123
01124
01125 const char *opt_name;
01126 const char *def;
01127 bool dummy = true;
01128 QCString opt = _opt;
01129 int result = ::findOption( options, opt, opt_name, def, dummy) & ~4;
01130
01131 if (result != 3)
01132 {
01133 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
01134 fprintf(stderr, "Application requests for getOption(\"%s\") but the \"%s\" option\n",
01135 _opt, _opt);
01136 fprintf(stderr, "has never been specified via addCmdLineOptions( ... )\n\n");
01137
01138 assert( 0 );
01139 exit(255);
01140 }
01141 return QCString(def);
01142 }
01143
01144 QCStringList
01145 KCmdLineArgs::getOptionList(const char *_opt) const
01146 {
01147 QCStringList result;
01148 if (!parsedOptionList)
01149 return result;
01150
01151 while(true)
01152 {
01153 QCString *value = parsedOptionList->take(_opt);
01154 if (!value)
01155 break;
01156 result.prepend(*value);
01157 delete value;
01158 }
01159
01160
01161
01162
01163
01164
01165 for(QCStringList::ConstIterator it=result.begin();
01166 it != result.end();
01167 ++it)
01168 {
01169 parsedOptionList->insert(_opt, new QCString(*it));
01170 }
01171 return result;
01172 }
01173
01174 bool
01175 KCmdLineArgs::isSet(const char *_opt) const
01176 {
01177
01178 const char *opt_name;
01179 const char *def;
01180 bool dummy = true;
01181 QCString opt = _opt;
01182 int result = ::findOption( options, opt, opt_name, def, dummy) & ~4;
01183
01184 if (result == 0)
01185 {
01186 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
01187 fprintf(stderr, "Application requests for isSet(\"%s\") but the \"%s\" option\n",
01188 _opt, _opt);
01189 fprintf(stderr, "has never been specified via addCmdLineOptions( ... )\n\n");
01190
01191 assert( 0 );
01192 exit(255);
01193 }
01194
01195 QCString *value = 0;
01196 if (parsedOptionList)
01197 {
01198 value = parsedOptionList->find(opt);
01199 }
01200
01201 if (value)
01202 {
01203 if (result == 3)
01204 return true;
01205 else
01206 return ((*value)[0] == 't');
01207 }
01208
01209 if (result == 3)
01210 return false;
01211
01212
01213
01214 return (result == 2);
01215 }
01216
01217 int
01218 KCmdLineArgs::count() const
01219 {
01220 if (!parsedArgList)
01221 return 0;
01222 return parsedArgList->count();
01223 }
01224
01225 const char *
01226 KCmdLineArgs::arg(int n) const
01227 {
01228 if (!parsedArgList || (n >= (int) parsedArgList->count()))
01229 {
01230 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs): Argument out of bounds\n");
01231 fprintf(stderr, "Application requests for arg(%d) without checking count() first.\n",
01232 n);
01233
01234 assert( 0 );
01235 exit(255);
01236 }
01237
01238 return parsedArgList->at(n);
01239 }
01240
01241 KURL
01242 KCmdLineArgs::url(int n) const
01243 {
01244 return makeURL( arg(n) );
01245 }
01246
01247 KURL KCmdLineArgs::makeURL(const char *_urlArg)
01248 {
01249 QString urlArg = QFile::decodeName(_urlArg);
01250 if (!QDir::isRelativePath(urlArg))
01251 {
01252 KURL result;
01253 result.setPath(urlArg);
01254 return result;
01255 }
01256
01257 if ( !KURL::isRelativeURL(urlArg) )
01258 return KURL(urlArg);
01259
01260 KURL result;
01261 result.setPath( cwd()+"/"+urlArg );
01262 result.cleanPath();
01263 return result;
01264 }
01265
01266 void
01267 KCmdLineArgs::addArgument(const char *argument)
01268 {
01269 if (!parsedArgList)
01270 parsedArgList = new KCmdLineParsedArgs;
01271
01272 parsedArgList->append(argument);
01273 }
01274
01275 static const KCmdLineOptions kde_tempfile_option[] =
01276 {
01277 { "tempfile", I18N_NOOP("The files/URLs opened by the application will be deleted after use"), 0},
01278 KCmdLineLastOption
01279 };
01280
01281 void
01282 KCmdLineArgs::addTempFileOption()
01283 {
01284 KCmdLineArgs::addCmdLineOptions( kde_tempfile_option, "KDE-tempfile", "kde-tempfile" );
01285 }
01286
01287 bool KCmdLineArgs::isTempFileSet()
01288 {
01289 KCmdLineArgs* args = KCmdLineArgs::parsedArgs( "kde-tempfile" );
01290 if ( args )
01291 return args->isSet( "tempfile" );
01292 return false;
01293 }