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 #if HAVE_LIMITS_H
00030 #include <limits.h>
00031 #endif
00032
00033 #include <qfile.h>
00034 #include <qasciidict.h>
00035 #include <qstrlist.h>
00036
00037 #include "kcmdlineargs.h"
00038 #include <kaboutdata.h>
00039 #include <klocale.h>
00040 #include <kapplication.h>
00041 #include <kglobal.h>
00042 #include <kstringhandler.h>
00043 #include <kstaticdeleter.h>
00044
00045 #ifdef Q_WS_X11
00046 #define DISPLAY "DISPLAY"
00047 #elif defined(Q_WS_QWS)
00048 #define DISPLAY "QWS_DISPLAY"
00049 #endif
00050
00051 template class QAsciiDict<QCString>;
00052 template class QPtrList<KCmdLineArgs>;
00053
00054 class KCmdLineParsedOptions : public QAsciiDict<QCString>
00055 {
00056 public:
00057 KCmdLineParsedOptions()
00058 : QAsciiDict<QCString>( 7 ) { }
00059
00060
00061
00062
00063
00064
00065 QDataStream& save( QDataStream &s) const
00066 { return QGDict::write(s); }
00067
00068 QDataStream& load( QDataStream &s)
00069 { return QGDict::read(s); }
00070
00071 protected:
00072 virtual QDataStream& write( QDataStream &s, QPtrCollection::Item data) const
00073 {
00074 QCString *str = (QCString *) data;
00075 s << (*str);
00076 return s;
00077 }
00078
00079 virtual QDataStream& read( QDataStream &s, QPtrCollection::Item &item)
00080 {
00081 QCString *str = new QCString;
00082 s >> (*str);
00083 item = (void *)str;
00084 return s;
00085 }
00086
00087 };
00088
00089 class KCmdLineParsedArgs : public QStrList
00090 {
00091 public:
00092 KCmdLineParsedArgs()
00093 : QStrList( true ) { }
00094 QDataStream& save( QDataStream &s) const
00095 { return QGList::write(s); }
00096
00097 QDataStream& load( QDataStream &s)
00098 { return QGList::read(s); }
00099 };
00100
00101
00102 class KCmdLineArgsList: public QPtrList<KCmdLineArgs>
00103 {
00104 public:
00105 KCmdLineArgsList() { }
00106 };
00107
00108 KCmdLineArgsList *KCmdLineArgs::argsList = 0;
00109 int KCmdLineArgs::argc = 0;
00110 char **KCmdLineArgs::argv = 0;
00111 char *KCmdLineArgs::mCwd = 0;
00112 static KStaticDeleter <char> mCwdd;
00113 const KAboutData *KCmdLineArgs::about = 0;
00114 bool KCmdLineArgs::parsed = false;
00115 bool KCmdLineArgs::ignoreUnknown = false;
00116
00117
00118
00119
00120
00121 void
00122 KCmdLineArgs::init(int _argc, char **_argv, const char *_appname, const char* programName,
00123 const char *_description, const char *_version, bool noKApp)
00124 {
00125 init(_argc, _argv,
00126 new KAboutData(_appname, programName, _version, _description),
00127 noKApp);
00128 }
00129
00130 void
00131 KCmdLineArgs::init(int _argc, char **_argv, const char *_appname,
00132 const char *_description, const char *_version, bool noKApp)
00133 {
00134 init(_argc, _argv,
00135 new KAboutData(_appname, _appname, _version, _description),
00136 noKApp);
00137 }
00138
00139 void
00140 KCmdLineArgs::initIgnore(int _argc, char **_argv, const char *_appname )
00141 {
00142 init(_argc, _argv,
00143 new KAboutData(_appname, _appname, "unknown", "KDE Application", false));
00144 ignoreUnknown = true;
00145 }
00146
00147 void
00148 KCmdLineArgs::init(const KAboutData* ab)
00149 {
00150 char **_argv = (char **) malloc(sizeof(char *));
00151 _argv[0] = (char *) ab->appName();
00152 init(1,_argv,ab, true);
00153 }
00154
00155
00156 void
00157 KCmdLineArgs::init(int _argc, char **_argv, const KAboutData *_about, bool noKApp)
00158 {
00159 argc = _argc;
00160 argv = _argv;
00161
00162 if (!argv)
00163 {
00164 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
00165 fprintf(stderr, "Passing null-pointer to 'argv' is not allowed.\n\n");
00166
00167 assert( 0 );
00168 exit(255);
00169 }
00170
00171
00172 if (argc) {
00173 char *p = strrchr( argv[0], '/');
00174 if (p)
00175 argv[0] = p+1;
00176 }
00177
00178 about = _about;
00179 parsed = false;
00180 mCwd = mCwdd.setObject(mCwd, new char [PATH_MAX+1], true);
00181 getcwd(mCwd, PATH_MAX);
00182 if (!noKApp)
00183 KApplication::addCmdLineOptions();
00184 }
00185
00186 QString KCmdLineArgs::cwd()
00187 {
00188 return QFile::decodeName(QCString(mCwd));
00189 }
00190
00191 const char * KCmdLineArgs::appName()
00192 {
00193 if (!argc) return 0;
00194 return argv[0];
00195 }
00196
00197 void
00198 KCmdLineArgs::addCmdLineOptions( const KCmdLineOptions *options, const char *name,
00199 const char *id, const char *afterId)
00200 {
00201 if (!argsList)
00202 argsList = new KCmdLineArgsList();
00203
00204 int pos = argsList->count();
00205
00206 if (pos && id && argsList->last() && !argsList->last()->name)
00207 pos--;
00208
00209 KCmdLineArgs *args;
00210 int i = 0;
00211 for(args = argsList->first(); args; args = argsList->next(), i++)
00212 {
00213 if (!id && !args->id)
00214 return;
00215
00216 if (id && args->id && (::qstrcmp(id, args->id) == 0))
00217 return;
00218
00219 if (afterId && args->id && (::qstrcmp(afterId, args->id) == 0))
00220 pos = i+1;
00221 }
00222
00223 assert( parsed == false );
00224
00225 args = new KCmdLineArgs(options, name, id);
00226 argsList->insert(pos, args);
00227 }
00228
00229 void
00230 KCmdLineArgs::saveAppArgs( QDataStream &ds)
00231 {
00232 if (!parsed)
00233 parseAllArgs();
00234
00235
00236 removeArgs("qt");
00237 removeArgs("kde");
00238
00239 QCString qCwd = mCwd;
00240 ds << qCwd;
00241
00242 uint count = argsList ? argsList->count() : 0;
00243 ds << count;
00244
00245 if (!count) return;
00246
00247 KCmdLineArgs *args;
00248 for(args = argsList->first(); args; args = argsList->next())
00249 {
00250 ds << QCString(args->id);
00251 args->save(ds);
00252 }
00253 }
00254
00255 void
00256 KCmdLineArgs::loadAppArgs( QDataStream &ds)
00257 {
00258
00259 removeArgs("qt");
00260 removeArgs("kde");
00261
00262 if (ds.atEnd())
00263 return;
00264
00265 KCmdLineArgs *args;
00266 if ( argsList ) {
00267 for(args = argsList->first(); args; args = argsList->next())
00268 {
00269 args->clear();
00270 }
00271 }
00272
00273 QCString qCwd;
00274 ds >> qCwd;
00275 delete [] mCwd;
00276
00277 mCwd = mCwdd.setObject(mCwd, new char[qCwd.length()+1], true);
00278 strncpy(mCwd, qCwd.data(), qCwd.length()+1);
00279
00280 uint count;
00281 ds >> count;
00282
00283 while(count--)
00284 {
00285 QCString id;
00286 ds >> id;
00287 assert( argsList );
00288 for(args = argsList->first(); args; args = argsList->next())
00289 {
00290 if (args->id == id)
00291 {
00292 args->load(ds);
00293 break;
00294 }
00295 }
00296 }
00297 }
00298
00299 KCmdLineArgs *KCmdLineArgs::parsedArgs(const char *id)
00300 {
00301 KCmdLineArgs *args = argsList ? argsList->first() : 0;
00302 while(args)
00303 {
00304 if ((id && ::qstrcmp(args->id, id) == 0) || (!id && !args->id))
00305 {
00306 if (!parsed)
00307 parseAllArgs();
00308 return args;
00309 }
00310 args = argsList->next();
00311 }
00312
00313 if (!args)
00314 {
00315 #ifndef NDEBUG
00316 fprintf(stderr, "WARNING (KCmdLineArgs):\n");
00317 fprintf(stderr, "Application requests for parsedArgs(\"%s\") without a prior call\n", id?id:"null");
00318 fprintf(stderr, "to addCmdLineOptions( ..., \"%s\"), or after a reset()\n\n", id?id:"null");
00319 #endif
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 KCmdLineArgs *args = parsedArgs("qt");
00669
00670 assert(args);
00671 if (!argv)
00672 {
00673 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
00674 fprintf(stderr, "Application has not called KCmdLineArgs::init(...).\n\n");
00675
00676 assert( 0 );
00677 exit(255);
00678 }
00679
00680 assert(argc >= (args->count()+1));
00681 argc = args->count() +1;
00682 return &argc;
00683 }
00684
00690 char ***
00691 KCmdLineArgs::qt_argv()
00692 {
00693 if (!argsList)
00694 KApplication::addCmdLineOptions();
00695
00696 KCmdLineArgs *args = parsedArgs("qt");
00697 assert(args);
00698 if (!argv)
00699 {
00700 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
00701 fprintf(stderr, "Application has not called KCmdLineArgs::init(...).\n\n");
00702
00703 assert( 0 );
00704 exit(255);
00705 }
00706
00707 int i = 0;
00708 for(; i < args->count(); i++)
00709 {
00710 argv[i+1] = (char *) args->arg(i);
00711 }
00712 argv[i+1] = 0;
00713
00714 return &argv;
00715 }
00716
00717 void
00718 KCmdLineArgs::enable_i18n()
00719 {
00720
00721 if (KGlobal::_locale)
00722 return;
00723
00724 if (!KGlobal::_instance) {
00725 KInstance *instance = new KInstance(about);
00726 (void) instance->config();
00727
00728 }
00729 }
00730
00731 void
00732 KCmdLineArgs::usage(const QString &error)
00733 {
00734 assert(KGlobal::_locale);
00735 QCString localError = error.local8Bit();
00736 if (localError[error.length()-1] == '\n')
00737 localError = localError.left(error.length()-1);
00738 fprintf(stderr, "%s: %s\n", argv[0], localError.data());
00739
00740 QString tmp = i18n("Use --help to get a list of available command line options.");
00741 localError = tmp.local8Bit();
00742 fprintf(stderr, "%s: %s\n", argv[0], localError.data());
00743 exit(254);
00744 }
00745
00746 void
00747 KCmdLineArgs::usage(const char *id)
00748 {
00749 enable_i18n();
00750 assert(argsList != 0);
00751
00752
00753 QString optionFormatString = " %1 %2\n";
00754 QString optionFormatStringDef = " %1 %2 [%3]\n";
00755 QString optionHeaderString = i18n("\n%1:\n");
00756 QString tmp;
00757 QString usage;
00758
00759 KCmdLineArgs *args = argsList->last();
00760
00761 if (!(args->id) && (args->options) &&
00762 (args->options->name) && (args->options->name[0] != '+'))
00763 {
00764 usage = i18n("[options] ")+usage;
00765 }
00766
00767 while(args)
00768 {
00769 if (args->name)
00770 {
00771 usage = i18n("[%1-options]").arg(args->name)+" "+usage;
00772 }
00773 args = argsList->prev();
00774 }
00775
00776 KCmdLineArgs *appOptions = argsList->last();
00777 if (!appOptions->id)
00778 {
00779 const KCmdLineOptions *option = appOptions->options;
00780 while(option && option->name)
00781 {
00782 if (option->name[0] == '+')
00783 usage = usage + (option->name+1) + " ";
00784 else if ( option->name[0] == '!' && option->name[1] == '+' )
00785 usage = usage + (option->name+2) + " ";
00786
00787 option++;
00788 }
00789 }
00790
00791 printQ(i18n("Usage: %1 %2\n").arg(argv[0]).arg(usage));
00792 printQ("\n"+about->shortDescription()+"\n");
00793
00794 printQ(optionHeaderString.arg(i18n("Generic options")));
00795 printQ(optionFormatString.arg("--help", -25).arg(i18n("Show help about options")));
00796
00797 args = argsList->first();
00798 while(args)
00799 {
00800 if (args->name && args->id)
00801 {
00802 QString option = QString("--help-%1").arg(args->id);
00803 QString desc = i18n("Show %1 specific options").arg(args->name);
00804
00805 printQ(optionFormatString.arg(option, -25).arg(desc));
00806 }
00807 args = argsList->next();
00808 }
00809
00810 printQ(optionFormatString.arg("--help-all",-25).arg(i18n("Show all options")));
00811 printQ(optionFormatString.arg("--author",-25).arg(i18n("Show author information")));
00812 printQ(optionFormatString.arg("-v, --version",-25).arg(i18n("Show version information")));
00813 printQ(optionFormatString.arg("--license",-25).arg(i18n("Show license information")));
00814 printQ(optionFormatString.arg("--", -25).arg(i18n("End of options")));
00815
00816 args = argsList->first();
00817
00818 bool showAll = id && (::qstrcmp(id, "all") == 0);
00819
00820 if (!showAll)
00821 {
00822 while(args)
00823 {
00824 if (!id && !args->id) break;
00825 if (id && (::qstrcmp(args->id, id) == 0)) break;
00826 args = argsList->next();
00827 }
00828 }
00829
00830 while(args)
00831 {
00832 bool hasArgs = false;
00833 bool hasOptions = false;
00834 QString optionsHeader;
00835 if (args->name)
00836 optionsHeader = optionHeaderString.arg(i18n("%1 options").arg(QString::fromLatin1(args->name)));
00837 else
00838 optionsHeader = i18n("\nOptions:\n");
00839
00840 while (args)
00841 {
00842 const KCmdLineOptions *option = args->options;
00843 QCString opt = "";
00844
00845 while(option && option->name)
00846 {
00847 QString description;
00848 QString descriptionRest;
00849 QStringList dl;
00850
00851
00852 if (option->name[0] == ':')
00853 {
00854 if (option->description)
00855 {
00856 optionsHeader = "\n"+i18n(option->description);
00857 if (!optionsHeader.endsWith("\n"))
00858 optionsHeader.append("\n");
00859 hasOptions = false;
00860 }
00861 option++;
00862 continue;
00863 }
00864
00865
00866 if (option->name[0] == 0)
00867 {
00868 if (option->description)
00869 {
00870 QString tmp = "\n"+i18n(option->description);
00871 if (!tmp.endsWith("\n"))
00872 tmp.append("\n");
00873 printQ(tmp);
00874 }
00875 option++;
00876 continue;
00877 }
00878
00879
00880 if (option->description)
00881 {
00882 description = i18n(option->description);
00883 dl = QStringList::split("\n", description, true);
00884 description = dl.first();
00885 dl.remove( dl.begin() );
00886 }
00887 QCString name = option->name;
00888 if (name[0] == '!')
00889 name = name.mid(1);
00890
00891 if (name[0] == '+')
00892 {
00893 if (!hasArgs)
00894 {
00895 printQ(i18n("\nArguments:\n"));
00896 hasArgs = true;
00897 }
00898
00899 name = name.mid(1);
00900 if ((name[0] == '[') && (name[name.length()-1] == ']'))
00901 name = name.mid(1, name.length()-2);
00902 printQ(optionFormatString.arg(name, -25)
00903 .arg(description));
00904 }
00905 else
00906 {
00907 if (!hasOptions)
00908 {
00909 printQ(optionsHeader);
00910 hasOptions = true;
00911 }
00912
00913 if ((name.length() == 1) || (name[1] == ' '))
00914 name = "-"+name;
00915 else
00916 name = "--"+name;
00917 if (!option->description)
00918 {
00919 opt = name + ", ";
00920 }
00921 else
00922 {
00923 opt = opt + name;
00924 if (!option->def)
00925 {
00926 printQ(optionFormatString.arg(opt, -25)
00927 .arg(description));
00928 }
00929 else
00930 {
00931 printQ(optionFormatStringDef.arg(opt, -25)
00932 .arg(description).arg(option->def));
00933 }
00934 opt = "";
00935 }
00936 }
00937 for(QStringList::Iterator it = dl.begin();
00938 it != dl.end();
00939 ++it)
00940 {
00941 printQ(optionFormatString.arg("", -25).arg(*it));
00942 }
00943
00944 option++;
00945 }
00946 args = argsList->next();
00947 if (!args || args->name || !args->id) break;
00948 }
00949 if (!showAll) break;
00950 }
00951
00952 exit(254);
00953 }
00954
00955
00956
00957
00958
00964 KCmdLineArgs::KCmdLineArgs( const KCmdLineOptions *_options,
00965 const char *_name, const char *_id)
00966 : options(_options), name(_name), id(_id)
00967 {
00968 parsedOptionList = 0;
00969 parsedArgList = 0;
00970 isQt = (::qstrcmp(id, "qt") == 0);
00971 }
00972
00976 KCmdLineArgs::~KCmdLineArgs()
00977 {
00978 delete parsedOptionList;
00979 delete parsedArgList;
00980 if (argsList)
00981 argsList->removeRef(this);
00982 }
00983
00984 void
00985 KCmdLineArgs::clear()
00986 {
00987 delete parsedArgList;
00988 parsedArgList = 0;
00989 delete parsedOptionList;
00990 parsedOptionList = 0;
00991 }
00992
00993 void
00994 KCmdLineArgs::reset()
00995 {
00996 if ( argsList ) {
00997 argsList->setAutoDelete( true );
00998 argsList->clear();
00999 delete argsList;
01000 argsList = 0;
01001 }
01002 parsed = false;
01003 }
01004
01005 void
01006 KCmdLineArgs::save( QDataStream &ds) const
01007 {
01008 uint count = 0;
01009 if (parsedOptionList)
01010 parsedOptionList->save( ds );
01011 else
01012 ds << count;
01013
01014 if (parsedArgList)
01015 parsedArgList->save( ds );
01016 else
01017 ds << count;
01018 }
01019
01020 void
01021 KCmdLineArgs::load( QDataStream &ds)
01022 {
01023 if (!parsedOptionList) parsedOptionList = new KCmdLineParsedOptions;
01024 if (!parsedArgList) parsedArgList = new KCmdLineParsedArgs;
01025
01026 parsedOptionList->load( ds );
01027 parsedArgList->load( ds );
01028
01029 if (parsedOptionList->count() == 0)
01030 {
01031 delete parsedOptionList;
01032 parsedOptionList = 0;
01033 }
01034 if (parsedArgList->count() == 0)
01035 {
01036 delete parsedArgList;
01037 parsedArgList = 0;
01038 }
01039 }
01040
01041 void
01042 KCmdLineArgs::setOption(const QCString &opt, bool enabled)
01043 {
01044 if (isQt)
01045 {
01046
01047 QCString arg = "-";
01048 if( !enabled )
01049 arg += "no";
01050 arg += opt;
01051 addArgument(arg);
01052 }
01053 if (!parsedOptionList) {
01054 parsedOptionList = new KCmdLineParsedOptions;
01055 parsedOptionList->setAutoDelete(true);
01056 }
01057
01058 if (enabled)
01059 parsedOptionList->replace( opt, new QCString("t") );
01060 else
01061 parsedOptionList->replace( opt, new QCString("f") );
01062 }
01063
01064 void
01065 KCmdLineArgs::setOption(const QCString &opt, const char *value)
01066 {
01067 if (isQt)
01068 {
01069
01070 QCString arg = "-";
01071 arg += opt;
01072 addArgument(arg);
01073 addArgument(value);
01074
01075
01076 if (arg == "-display")
01077 {
01078 setenv(DISPLAY, value, true);
01079 }
01080 }
01081 if (!parsedOptionList) {
01082 parsedOptionList = new KCmdLineParsedOptions;
01083 parsedOptionList->setAutoDelete(true);
01084 }
01085
01086 parsedOptionList->insert( opt, new QCString(value) );
01087 }
01088
01089 QCString
01090 KCmdLineArgs::getOption(const char *_opt) const
01091 {
01092 QCString *value = 0;
01093 if (parsedOptionList)
01094 {
01095 value = parsedOptionList->find(_opt);
01096 }
01097
01098 if (value)
01099 return (*value);
01100
01101
01102 const char *opt_name;
01103 const char *def;
01104 bool dummy = true;
01105 QCString opt = _opt;
01106 int result = ::findOption( options, opt, opt_name, def, dummy) & ~4;
01107
01108 if (result != 3)
01109 {
01110 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
01111 fprintf(stderr, "Application requests for getOption(\"%s\") but the \"%s\" option\n",
01112 _opt, _opt);
01113 fprintf(stderr, "has never been specified via addCmdLineOptions( ... )\n\n");
01114
01115 assert( 0 );
01116 exit(255);
01117 }
01118 return QCString(def);
01119 }
01120
01121 QCStringList
01122 KCmdLineArgs::getOptionList(const char *_opt) const
01123 {
01124 QCStringList result;
01125 if (!parsedOptionList)
01126 return result;
01127
01128 while(true)
01129 {
01130 QCString *value = parsedOptionList->take(_opt);
01131 if (!value)
01132 break;
01133 result.prepend(*value);
01134 delete value;
01135 }
01136
01137
01138
01139
01140
01141
01142 for(QCStringList::ConstIterator it=result.begin();
01143 it != result.end();
01144 ++it)
01145 {
01146 parsedOptionList->insert(_opt, new QCString(*it));
01147 }
01148 return result;
01149 }
01150
01151 bool
01152 KCmdLineArgs::isSet(const char *_opt) const
01153 {
01154
01155 const char *opt_name;
01156 const char *def;
01157 bool dummy = true;
01158 QCString opt = _opt;
01159 int result = ::findOption( options, opt, opt_name, def, dummy) & ~4;
01160
01161 if (result == 0)
01162 {
01163 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
01164 fprintf(stderr, "Application requests for isSet(\"%s\") but the \"%s\" option\n",
01165 _opt, _opt);
01166 fprintf(stderr, "has never been specified via addCmdLineOptions( ... )\n\n");
01167
01168 assert( 0 );
01169 exit(255);
01170 }
01171
01172 QCString *value = 0;
01173 if (parsedOptionList)
01174 {
01175 value = parsedOptionList->find(opt);
01176 }
01177
01178 if (value)
01179 {
01180 if (result == 3)
01181 return true;
01182 else
01183 return ((*value)[0] == 't');
01184 }
01185
01186 if (result == 3)
01187 return false;
01188
01189
01190
01191 return (result == 2);
01192 }
01193
01194 int
01195 KCmdLineArgs::count() const
01196 {
01197 if (!parsedArgList)
01198 return 0;
01199 return parsedArgList->count();
01200 }
01201
01202 const char *
01203 KCmdLineArgs::arg(int n) const
01204 {
01205 if (!parsedArgList || (n >= (int) parsedArgList->count()))
01206 {
01207 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs): Argument out of bounds\n");
01208 fprintf(stderr, "Application requests for arg(%d) without checking count() first.\n",
01209 n);
01210
01211 assert( 0 );
01212 exit(255);
01213 }
01214
01215 return parsedArgList->at(n);
01216 }
01217
01218 KURL
01219 KCmdLineArgs::url(int n) const
01220 {
01221 return makeURL( arg(n) );
01222 }
01223
01224 KURL KCmdLineArgs::makeURL( const char *urlArg )
01225 {
01226 if (*urlArg == '/')
01227 {
01228 KURL result;
01229 result.setPath(QFile::decodeName( urlArg));
01230 return result;
01231 }
01232
01233 if ( !KURL::isRelativeURL( QString::fromLocal8Bit(urlArg) ) )
01234 return KURL(QString::fromLocal8Bit(urlArg));
01235
01236 KURL result;
01237 result.setPath( cwd()+"/"+QFile::decodeName( urlArg ));
01238 result.cleanPath();
01239 return result;
01240 }
01241
01242 void
01243 KCmdLineArgs::addArgument(const char *argument)
01244 {
01245 if (!parsedArgList)
01246 parsedArgList = new KCmdLineParsedArgs;
01247
01248 parsedArgList->append(argument);
01249 }