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