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