summaryrefslogtreecommitdiffstats
path: root/kdecore/kcmdlineargs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kdecore/kcmdlineargs.cpp')
-rw-r--r--kdecore/kcmdlineargs.cpp1298
1 files changed, 1298 insertions, 0 deletions
diff --git a/kdecore/kcmdlineargs.cpp b/kdecore/kcmdlineargs.cpp
new file mode 100644
index 000000000..c99903009
--- /dev/null
+++ b/kdecore/kcmdlineargs.cpp
@@ -0,0 +1,1298 @@
+/*
+ Copyright (C) 1999 Waldo Bastian <bastian@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config.h>
+
+#include <sys/param.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include <qdir.h>
+#include <qfile.h>
+#include <qasciidict.h>
+#include <qstrlist.h>
+
+#include "kcmdlineargs.h"
+#include <kaboutdata.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <kglobal.h>
+#include <kstringhandler.h>
+#include <kstaticdeleter.h>
+
+#ifdef Q_WS_X11
+#define DISPLAY "DISPLAY"
+#elif defined(Q_WS_QWS)
+#define DISPLAY "QWS_DISPLAY"
+#endif
+
+#ifdef Q_WS_WIN
+#include <win32_utils.h>
+#endif
+
+template class QAsciiDict<QCString>;
+template class QPtrList<KCmdLineArgs>;
+
+class KCmdLineParsedOptions : public QAsciiDict<QCString>
+{
+public:
+ KCmdLineParsedOptions()
+ : QAsciiDict<QCString>( 7 ) { }
+
+ // WABA: Huh?
+ // The compiler doesn't find KCmdLineParsedOptions::write(s) by itself ???
+ // WABA: No, because there is another write function that hides the
+ // write function in the base class even though this function has a
+ // different signature. (obscure C++ feature)
+ QDataStream& save( QDataStream &s) const
+ { return QGDict::write(s); }
+
+ QDataStream& load( QDataStream &s)
+ { return QGDict::read(s); }
+
+protected:
+ virtual QDataStream& write( QDataStream &s, QPtrCollection::Item data) const
+ {
+ QCString *str = (QCString *) data;
+ s << (*str);
+ return s;
+ }
+
+ virtual QDataStream& read( QDataStream &s, QPtrCollection::Item &item)
+ {
+ QCString *str = new QCString;
+ s >> (*str);
+ item = (void *)str;
+ return s;
+ }
+
+};
+
+class KCmdLineParsedArgs : public QStrList
+{
+public:
+ KCmdLineParsedArgs()
+ : QStrList( true ) { }
+ QDataStream& save( QDataStream &s) const
+ { return QGList::write(s); }
+
+ QDataStream& load( QDataStream &s)
+ { return QGList::read(s); }
+};
+
+
+class KCmdLineArgsList: public QPtrList<KCmdLineArgs>
+{
+public:
+ KCmdLineArgsList() { }
+};
+
+KCmdLineArgsList *KCmdLineArgs::argsList = 0;
+int KCmdLineArgs::argc = 0;
+char **KCmdLineArgs::argv = 0;
+char *KCmdLineArgs::mCwd = 0;
+static KStaticDeleter <char> mCwdd;
+const KAboutData *KCmdLineArgs::about = 0;
+bool KCmdLineArgs::parsed = false;
+bool KCmdLineArgs::ignoreUnknown = false;
+
+//
+// Static functions
+//
+
+void
+KCmdLineArgs::init(int _argc, char **_argv, const char *_appname, const char* programName,
+ const char *_description, const char *_version, bool noKApp)
+{
+ init(_argc, _argv,
+ new KAboutData(_appname, programName, _version, _description),
+ noKApp);
+}
+
+void
+KCmdLineArgs::init(int _argc, char **_argv, const char *_appname,
+ const char *_description, const char *_version, bool noKApp)
+{
+ init(_argc, _argv,
+ new KAboutData(_appname, _appname, _version, _description),
+ noKApp);
+}
+
+void
+KCmdLineArgs::initIgnore(int _argc, char **_argv, const char *_appname )
+{
+ init(_argc, _argv,
+ new KAboutData(_appname, _appname, "unknown", "KDE Application", false));
+ ignoreUnknown = true;
+}
+
+void
+KCmdLineArgs::init(const KAboutData* ab)
+{
+ char **_argv = (char **) malloc(sizeof(char *));
+ _argv[0] = (char *) ab->appName();
+ init(1,_argv,ab, true);
+}
+
+
+void
+KCmdLineArgs::init(int _argc, char **_argv, const KAboutData *_about, bool noKApp)
+{
+ argc = _argc;
+ argv = _argv;
+
+ if (!argv)
+ {
+ fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
+ fprintf(stderr, "Passing null-pointer to 'argv' is not allowed.\n\n");
+
+ assert( 0 );
+ exit(255);
+ }
+
+ // Strip path from argv[0]
+ if (argc) {
+ char *p = strrchr( argv[0], '/');
+ if (p)
+ argv[0] = p+1;
+ }
+
+ about = _about;
+ parsed = false;
+ mCwd = mCwdd.setObject(mCwd, new char [PATH_MAX+1], true);
+ (void) getcwd(mCwd, PATH_MAX);
+#ifdef Q_WS_WIN
+ win32_slashify(mCwd, PATH_MAX);
+#endif
+ if (!noKApp)
+ KApplication::addCmdLineOptions();
+}
+
+QString KCmdLineArgs::cwd()
+{
+ return QFile::decodeName(QCString(mCwd));
+}
+
+const char * KCmdLineArgs::appName()
+{
+ if (!argc) return 0;
+ return argv[0];
+}
+
+void
+KCmdLineArgs::addCmdLineOptions( const KCmdLineOptions *options, const char *name,
+ const char *id, const char *afterId)
+{
+ if (!argsList)
+ argsList = new KCmdLineArgsList();
+
+ int pos = argsList->count();
+
+ if (pos && id && argsList->last() && !argsList->last()->name)
+ pos--;
+
+ KCmdLineArgs *args;
+ int i = 0;
+ for(args = argsList->first(); args; args = argsList->next(), i++)
+ {
+ if (!id && !args->id)
+ return; // Options already present.
+
+ if (id && args->id && (::qstrcmp(id, args->id) == 0))
+ return; // Options already present.
+
+ if (afterId && args->id && (::qstrcmp(afterId, args->id) == 0))
+ pos = i+1;
+ }
+
+ assert( parsed == false ); // You must add _ALL_ cmd line options
+ // before accessing the arguments!
+ args = new KCmdLineArgs(options, name, id);
+ argsList->insert(pos, args);
+}
+
+void
+KCmdLineArgs::saveAppArgs( QDataStream &ds)
+{
+ if (!parsed)
+ parseAllArgs();
+
+ // Remove Qt and KDE options.
+ removeArgs("qt");
+ removeArgs("kde");
+
+ QCString qCwd = mCwd;
+ ds << qCwd;
+
+ uint count = argsList ? argsList->count() : 0;
+ ds << count;
+
+ if (!count) return;
+
+ KCmdLineArgs *args;
+ for(args = argsList->first(); args; args = argsList->next())
+ {
+ ds << QCString(args->id);
+ args->save(ds);
+ }
+}
+
+void
+KCmdLineArgs::loadAppArgs( QDataStream &ds)
+{
+ parsed = true; // don't reparse argc/argv!
+
+ // Remove Qt and KDE options.
+ removeArgs("qt");
+ removeArgs("kde");
+
+ KCmdLineArgs *args;
+ if ( argsList ) {
+ for(args = argsList->first(); args; args = argsList->next())
+ {
+ args->clear();
+ }
+ }
+
+ if (ds.atEnd())
+ return;
+
+ QCString qCwd;
+ ds >> qCwd;
+ delete [] mCwd;
+
+ mCwd = mCwdd.setObject(mCwd, new char[qCwd.length()+1], true);
+ strncpy(mCwd, qCwd.data(), qCwd.length()+1);
+
+ uint count;
+ ds >> count;
+
+ while(count--)
+ {
+ QCString id;
+ ds >> id;
+ assert( argsList );
+ for(args = argsList->first(); args; args = argsList->next())
+ {
+ if (args->id == id)
+ {
+ args->load(ds);
+ break;
+ }
+ }
+ }
+ parsed = true;
+}
+
+KCmdLineArgs *KCmdLineArgs::parsedArgs(const char *id)
+{
+ KCmdLineArgs *args = argsList ? argsList->first() : 0;
+ while(args)
+ {
+ if ((id && ::qstrcmp(args->id, id) == 0) || (!id && !args->id))
+ {
+ if (!parsed)
+ parseAllArgs();
+ return args;
+ }
+ args = argsList->next();
+ }
+
+ return args;
+}
+
+void KCmdLineArgs::removeArgs(const char *id)
+{
+ KCmdLineArgs *args = argsList ? argsList->first() : 0;
+ while(args)
+ {
+ if (args->id && id && ::qstrcmp(args->id, id) == 0)
+ {
+ if (!parsed)
+ parseAllArgs();
+ break;
+ }
+ args = argsList->next();
+ }
+
+ if (args)
+ delete args;
+}
+
+/*
+ * @return:
+ * 0 - option not found.
+ * 1 - option found // -fork
+ * 2 - inverse option found ('no') // -nofork
+ * 3 - option + arg found // -fork now
+ *
+ * +4 - no more options follow // !fork
+ */
+static int
+findOption(const KCmdLineOptions *options, QCString &opt,
+ const char *&opt_name, const char *&def, bool &enabled)
+{
+ int result;
+ bool inverse;
+ int len = opt.length();
+ while(options && options->name)
+ {
+ result = 0;
+ inverse = false;
+ opt_name = options->name;
+ if ((opt_name[0] == ':') || (opt_name[0] == 0))
+ {
+ options++;
+ continue;
+ }
+
+ if (opt_name[0] == '!')
+ {
+ opt_name++;
+ result = 4;
+ }
+ if ((opt_name[0] == 'n') && (opt_name[1] == 'o'))
+ {
+ opt_name += 2;
+ inverse = true;
+ }
+ if (strncmp(opt.data(), opt_name, len) == 0)
+ {
+ opt_name += len;
+ if (!opt_name[0])
+ {
+ if (inverse)
+ return result+2;
+
+ if (!options->description)
+ {
+ options++;
+ if (!options->name)
+ return result+0;
+ QCString nextOption = options->name;
+ int p = nextOption.find(' ');
+ if (p > 0)
+ nextOption = nextOption.left(p);
+ if (nextOption[0] == '!')
+ nextOption = nextOption.mid(1);
+ if (strncmp(nextOption.data(), "no", 2) == 0)
+ {
+ nextOption = nextOption.mid(2);
+ enabled = !enabled;
+ }
+ result = findOption(options, nextOption, opt_name, def, enabled);
+ assert(result);
+ opt = nextOption;
+ return result;
+ }
+
+ return 1;
+ }
+ if (opt_name[0] == ' ')
+ {
+ opt_name++;
+ def = options->def;
+ return result+3;
+ }
+ }
+
+ options++;
+ }
+ return 0;
+}
+
+
+void
+KCmdLineArgs::findOption(const char *_opt, QCString opt, int &i, bool _enabled, bool &moreOptions)
+{
+ KCmdLineArgs *args = argsList->first();
+ const char *opt_name;
+ const char *def;
+ QCString argument;
+ int j = opt.find('=');
+ if (j != -1)
+ {
+ argument = opt.mid(j+1);
+ opt = opt.left(j);
+ }
+
+ bool enabled = true;
+ int result = 0;
+ while (args)
+ {
+ enabled = _enabled;
+ result = ::findOption(args->options, opt, opt_name, def, enabled);
+ if (result) break;
+ args = argsList->next();
+ }
+ if (!args && (_opt[0] == '-') && _opt[1] && (_opt[1] != '-'))
+ {
+ // Option not found check if it is a valid option
+ // in the style of -Pprinter1 or ps -aux
+ int p = 1;
+ while (true)
+ {
+ QCString singleCharOption = " ";
+ singleCharOption[0] = _opt[p];
+ args = argsList->first();
+ while (args)
+ {
+ enabled = _enabled;
+ result = ::findOption(args->options, singleCharOption, opt_name, def, enabled);
+ if (result) break;
+ args = argsList->next();
+ }
+ if (!args)
+ break; // Unknown argument
+
+ p++;
+ if (result == 1) // Single option
+ {
+ args->setOption(singleCharOption, enabled);
+ if (_opt[p])
+ continue; // Next option
+ else
+ return; // Finished
+ }
+ else if (result == 3) // This option takes an argument
+ {
+ if (argument.isEmpty())
+ {
+ argument = _opt+p;
+ }
+ args->setOption(singleCharOption, argument);
+ return;
+ }
+ break; // Unknown argument
+ }
+ args = 0;
+ result = 0;
+ }
+
+ if (!args || !result)
+ {
+ if (ignoreUnknown)
+ return;
+ enable_i18n();
+ usage( i18n("Unknown option '%1'.").arg(QString::fromLocal8Bit(_opt)));
+ }
+
+ if ((result & 4) != 0)
+ {
+ result &= ~4;
+ moreOptions = false;
+ }
+
+ if (result == 3) // This option takes an argument
+ {
+ if (!enabled)
+ {
+ if (ignoreUnknown)
+ return;
+ enable_i18n();
+ usage( i18n("Unknown option '%1'.").arg(QString::fromLocal8Bit(_opt)));
+ }
+ if (argument.isEmpty())
+ {
+ i++;
+ if (i >= argc)
+ {
+ enable_i18n();
+ usage( i18n("'%1' missing.").arg( opt_name));
+ }
+ argument = argv[i];
+ }
+ args->setOption(opt, argument);
+ }
+ else
+ {
+ args->setOption(opt, enabled);
+ }
+}
+
+void
+KCmdLineArgs::printQ(const QString &msg)
+{
+ QCString localMsg = msg.local8Bit();
+ fprintf(stdout, "%s", localMsg.data());
+}
+
+void
+KCmdLineArgs::parseAllArgs()
+{
+ bool allowArgs = false;
+ bool inOptions = true;
+ bool everythingAfterArgIsArgs = false;
+ KCmdLineArgs *appOptions = argsList->last();
+ if (!appOptions->id)
+ {
+ const KCmdLineOptions *option = appOptions->options;
+ while(option && option->name)
+ {
+ if (option->name[0] == '+')
+ allowArgs = true;
+ if ( option->name[0] == '!' && option->name[1] == '+' )
+ {
+ allowArgs = true;
+ everythingAfterArgIsArgs = true;
+ }
+ option++;
+ }
+ }
+ for(int i = 1; i < argc; i++)
+ {
+ if (!argv[i])
+ continue;
+
+ if ((argv[i][0] == '-') && argv[i][1] && inOptions)
+ {
+ bool enabled = true;
+ const char *option = &argv[i][1];
+ const char *orig = argv[i];
+ if (option[0] == '-')
+ {
+ option++;
+ argv[i]++;
+ if (!option[0])
+ {
+ inOptions = false;
+ continue;
+ }
+ }
+ if (::qstrcmp(option, "help") == 0)
+ {
+ usage(0);
+ }
+ else if (strncmp(option, "help-",5) == 0)
+ {
+ usage(option+5);
+ }
+ else if ( (::qstrcmp(option, "version") == 0) ||
+ (::qstrcmp(option, "v") == 0))
+ {
+ printQ( QString("Qt: %1\n").arg(qVersion()));
+ printQ( QString("KDE: %1\n").arg(KDE_VERSION_STRING));
+ printQ( QString("%1: %2\n").
+ arg(about->programName()).arg(about->version()));
+ exit(0);
+ } else if ( (::qstrcmp(option, "license") == 0) )
+ {
+ enable_i18n();
+ printQ( about->license() );
+ printQ( "\n" );
+ exit(0);
+ } else if ( ::qstrcmp( option, "author") == 0 ) {
+ enable_i18n();
+ if ( about ) {
+ const QValueList<KAboutPerson> authors = about->authors();
+ if ( !authors.isEmpty() ) {
+ QString authorlist;
+ for (QValueList<KAboutPerson>::ConstIterator it = authors.begin(); it != authors.end(); ++it ) {
+ QString email;
+ if ( !(*it).emailAddress().isEmpty() )
+ email = " <" + (*it).emailAddress() + ">";
+ authorlist += QString(" ") + (*it).name() + email + "\n";
+ }
+ 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 ) );
+ }
+ } else {
+ printQ( i18n("This application was written by somebody who wants to remain anonymous.") );
+ }
+ if (about)
+ {
+ if (!about->customAuthorTextEnabled ())
+ {
+ if (about->bugAddress().isEmpty() || about->bugAddress() == "submit@bugs.kde.org" )
+ printQ( i18n( "Please use http://bugs.kde.org to report bugs.\n" ) );
+ else {
+ if( about->authors().count() == 1 && about->authors().first().emailAddress() == about->bugAddress() )
+ printQ( i18n( "Please report bugs to %1.\n" ).arg( about->authors().first().emailAddress() ) );
+ else
+ printQ( i18n( "Please report bugs to %1.\n" ).arg(about->bugAddress()) );
+ }
+ }
+ else
+ {
+ printQ(about->customAuthorPlainText());
+ }
+ }
+ exit(0);
+ } else {
+ if ((option[0] == 'n') && (option[1] == 'o'))
+ {
+ option += 2;
+ enabled = false;
+ }
+ findOption(orig, option, i, enabled, inOptions);
+ }
+ }
+ else
+ {
+ // Check whether appOptions allows these arguments
+ if (!allowArgs)
+ {
+ if (ignoreUnknown)
+ continue;
+ enable_i18n();
+ usage( i18n("Unexpected argument '%1'.").arg(QString::fromLocal8Bit(argv[i])));
+ }
+ else
+ {
+ appOptions->addArgument(argv[i]);
+ if (everythingAfterArgIsArgs)
+ inOptions = false;
+ }
+ }
+ }
+ parsed = true;
+}
+
+/**
+ * For KApplication only:
+ *
+ * Return argc
+ */
+int *
+KCmdLineArgs::qt_argc()
+{
+ if (!argsList)
+ KApplication::addCmdLineOptions(); // Lazy bastards!
+
+ static int qt_argc = -1;
+ if( qt_argc != -1 )
+ return &qt_argc;
+
+ KCmdLineArgs *args = parsedArgs("qt");
+ assert(args); // No qt options have been added!
+ if (!argv)
+ {
+ fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
+ fprintf(stderr, "Application has not called KCmdLineArgs::init(...).\n\n");
+
+ assert( 0 );
+ exit(255);
+ }
+
+ assert(argc >= (args->count()+1));
+ qt_argc = args->count() +1;
+ return &qt_argc;
+}
+
+/**
+ * For KApplication only:
+ *
+ * Return argv
+ */
+char ***
+KCmdLineArgs::qt_argv()
+{
+ if (!argsList)
+ KApplication::addCmdLineOptions(); // Lazy bastards!
+
+ static char** qt_argv;
+ if( qt_argv != NULL )
+ return &qt_argv;
+
+ KCmdLineArgs *args = parsedArgs("qt");
+ assert(args); // No qt options have been added!
+ if (!argv)
+ {
+ fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
+ fprintf(stderr, "Application has not called KCmdLineArgs::init(...).\n\n");
+
+ assert( 0 );
+ exit(255);
+ }
+
+ qt_argv = new char*[ args->count() + 2 ];
+ qt_argv[ 0 ] = qstrdup( appName());
+ int i = 0;
+ for(; i < args->count(); i++)
+ {
+ qt_argv[i+1] = qstrdup((char *) args->arg(i));
+ }
+ qt_argv[i+1] = 0;
+
+ return &qt_argv;
+}
+
+void
+KCmdLineArgs::enable_i18n()
+{
+ // called twice or too late
+ if (KGlobal::_locale)
+ return;
+
+ if (!KGlobal::_instance) {
+ KInstance *instance = new KInstance(about);
+ (void) instance->config();
+ // Don't delete instance!
+ }
+}
+
+void
+KCmdLineArgs::usage(const QString &error)
+{
+ assert(KGlobal::_locale);
+ QCString localError = error.local8Bit();
+ if (localError[error.length()-1] == '\n')
+ localError = localError.left(error.length()-1);
+ fprintf(stderr, "%s: %s\n", argv[0], localError.data());
+
+ QString tmp = i18n("Use --help to get a list of available command line options.");
+ localError = tmp.local8Bit();
+ fprintf(stderr, "%s: %s\n", argv[0], localError.data());
+ exit(254);
+}
+
+void
+KCmdLineArgs::usage(const char *id)
+{
+ enable_i18n();
+ assert(argsList != 0); // It's an error to call usage(...) without
+ // having done addCmdLineOptions first!
+
+ QString optionFormatString = " %1 %2\n";
+ QString optionFormatStringDef = " %1 %2 [%3]\n";
+ QString optionHeaderString = i18n("\n%1:\n");
+ QString tmp;
+ QString usage;
+
+ KCmdLineArgs *args = argsList->last();
+
+ if (!(args->id) && (args->options) &&
+ (args->options->name) && (args->options->name[0] != '+'))
+ {
+ usage = i18n("[options] ")+usage;
+ }
+
+ while(args)
+ {
+ if (args->name)
+ {
+ usage = i18n("[%1-options]").arg(args->name)+" "+usage;
+ }
+ args = argsList->prev();
+ }
+
+ KCmdLineArgs *appOptions = argsList->last();
+ if (!appOptions->id)
+ {
+ const KCmdLineOptions *option = appOptions->options;
+ while(option && option->name)
+ {
+ if (option->name[0] == '+')
+ usage = usage + (option->name+1) + " ";
+ else if ( option->name[0] == '!' && option->name[1] == '+' )
+ usage = usage + (option->name+2) + " ";
+
+ option++;
+ }
+ }
+
+ printQ(i18n("Usage: %1 %2\n").arg(argv[0]).arg(usage));
+ printQ("\n"+about->shortDescription()+"\n");
+
+ printQ(optionHeaderString.arg(i18n("Generic options")));
+ printQ(optionFormatString.arg("--help", -25).arg(i18n("Show help about options")));
+
+ args = argsList->first();
+ while(args)
+ {
+ if (args->name && args->id)
+ {
+ QString option = QString("--help-%1").arg(args->id);
+ QString desc = i18n("Show %1 specific options").arg(args->name);
+
+ printQ(optionFormatString.arg(option, -25).arg(desc));
+ }
+ args = argsList->next();
+ }
+
+ printQ(optionFormatString.arg("--help-all",-25).arg(i18n("Show all options")));
+ printQ(optionFormatString.arg("--author",-25).arg(i18n("Show author information")));
+ printQ(optionFormatString.arg("-v, --version",-25).arg(i18n("Show version information")));
+ printQ(optionFormatString.arg("--license",-25).arg(i18n("Show license information")));
+ printQ(optionFormatString.arg("--", -25).arg(i18n("End of options")));
+
+ args = argsList->first(); // Sets current to 1st.
+
+ bool showAll = id && (::qstrcmp(id, "all") == 0);
+
+ if (!showAll)
+ {
+ while(args)
+ {
+ if (!id && !args->id) break;
+ if (id && (::qstrcmp(args->id, id) == 0)) break;
+ args = argsList->next();
+ }
+ }
+
+ while(args)
+ {
+ bool hasArgs = false;
+ bool hasOptions = false;
+ QString optionsHeader;
+ if (args->name)
+ optionsHeader = optionHeaderString.arg(i18n("%1 options").arg(QString::fromLatin1(args->name)));
+ else
+ optionsHeader = i18n("\nOptions:\n");
+
+ while (args)
+ {
+ const KCmdLineOptions *option = args->options;
+ QCString opt = "";
+//
+ while(option && option->name)
+ {
+ QString description;
+ QString descriptionRest;
+ QStringList dl;
+
+ // Option header
+ if (option->name[0] == ':')
+ {
+ if (option->description)
+ {
+ optionsHeader = "\n"+i18n(option->description);
+ if (!optionsHeader.endsWith("\n"))
+ optionsHeader.append("\n");
+ hasOptions = false;
+ }
+ option++;
+ continue;
+ }
+
+ // Free-form comment
+ if (option->name[0] == 0)
+ {
+ if (option->description)
+ {
+ QString tmp = "\n"+i18n(option->description);
+ if (!tmp.endsWith("\n"))
+ tmp.append("\n");
+ printQ(tmp);
+ }
+ option++;
+ continue;
+ }
+
+ // Options
+ if (option->description)
+ {
+ description = i18n(option->description);
+ dl = QStringList::split("\n", description, true);
+ description = dl.first();
+ dl.remove( dl.begin() );
+ }
+ QCString name = option->name;
+ if (name[0] == '!')
+ name = name.mid(1);
+
+ if (name[0] == '+')
+ {
+ if (!hasArgs)
+ {
+ printQ(i18n("\nArguments:\n"));
+ hasArgs = true;
+ }
+
+ name = name.mid(1);
+ if ((name[0] == '[') && (name[name.length()-1] == ']'))
+ name = name.mid(1, name.length()-2);
+ printQ(optionFormatString.arg(name, -25)
+ .arg(description));
+ }
+ else
+ {
+ if (!hasOptions)
+ {
+ printQ(optionsHeader);
+ hasOptions = true;
+ }
+
+ if ((name.length() == 1) || (name[1] == ' '))
+ name = "-"+name;
+ else
+ name = "--"+name;
+ if (!option->description)
+ {
+ opt = name + ", ";
+ }
+ else
+ {
+ opt = opt + name;
+ if (!option->def)
+ {
+ printQ(optionFormatString.arg(opt, -25)
+ .arg(description));
+ }
+ else
+ {
+ printQ(optionFormatStringDef.arg(opt, -25)
+ .arg(description).arg(option->def));
+ }
+ opt = "";
+ }
+ }
+ for(QStringList::Iterator it = dl.begin();
+ it != dl.end();
+ ++it)
+ {
+ printQ(optionFormatString.arg("", -25).arg(*it));
+ }
+
+ option++;
+ }
+ args = argsList->next();
+ if (!args || args->name || !args->id) break;
+ }
+ if (!showAll) break;
+ }
+
+ exit(254);
+}
+
+//
+// Member functions
+//
+
+/**
+ * Constructor.
+ *
+ * The given arguments are assumed to be constants.
+ */
+KCmdLineArgs::KCmdLineArgs( const KCmdLineOptions *_options,
+ const char *_name, const char *_id)
+ : options(_options), name(_name), id(_id)
+{
+ parsedOptionList = 0;
+ parsedArgList = 0;
+ isQt = (::qstrcmp(id, "qt") == 0);
+}
+
+/**
+ * Destructor.
+ */
+KCmdLineArgs::~KCmdLineArgs()
+{
+ delete parsedOptionList;
+ delete parsedArgList;
+ if (argsList)
+ argsList->removeRef(this);
+}
+
+void
+KCmdLineArgs::clear()
+{
+ delete parsedArgList;
+ parsedArgList = 0;
+ delete parsedOptionList;
+ parsedOptionList = 0;
+}
+
+void
+KCmdLineArgs::reset()
+{
+ if ( argsList ) {
+ argsList->setAutoDelete( true );
+ argsList->clear();
+ delete argsList;
+ argsList = 0;
+ }
+ parsed = false;
+}
+
+void
+KCmdLineArgs::save( QDataStream &ds) const
+{
+ uint count = 0;
+ if (parsedOptionList)
+ parsedOptionList->save( ds );
+ else
+ ds << count;
+
+ if (parsedArgList)
+ parsedArgList->save( ds );
+ else
+ ds << count;
+}
+
+void
+KCmdLineArgs::load( QDataStream &ds)
+{
+ if (!parsedOptionList) parsedOptionList = new KCmdLineParsedOptions;
+ if (!parsedArgList) parsedArgList = new KCmdLineParsedArgs;
+
+ parsedOptionList->load( ds );
+ parsedArgList->load( ds );
+
+ if (parsedOptionList->count() == 0)
+ {
+ delete parsedOptionList;
+ parsedOptionList = 0;
+ }
+ if (parsedArgList->count() == 0)
+ {
+ delete parsedArgList;
+ parsedArgList = 0;
+ }
+}
+
+void
+KCmdLineArgs::setOption(const QCString &opt, bool enabled)
+{
+ if (isQt)
+ {
+ // Qt does it own parsing.
+ QCString arg = "-";
+ if( !enabled )
+ arg += "no";
+ arg += opt;
+ addArgument(arg);
+ }
+ if (!parsedOptionList) {
+ parsedOptionList = new KCmdLineParsedOptions;
+ parsedOptionList->setAutoDelete(true);
+ }
+
+ if (enabled)
+ parsedOptionList->replace( opt, new QCString("t") );
+ else
+ parsedOptionList->replace( opt, new QCString("f") );
+}
+
+void
+KCmdLineArgs::setOption(const QCString &opt, const char *value)
+{
+ if (isQt)
+ {
+ // Qt does it's own parsing.
+ QCString arg = "-";
+ arg += opt;
+ addArgument(arg);
+ addArgument(value);
+
+#ifdef Q_WS_X11
+ // Hack coming up!
+ if (arg == "-display")
+ {
+ setenv(DISPLAY, value, true);
+ }
+#endif
+ }
+ if (!parsedOptionList) {
+ parsedOptionList = new KCmdLineParsedOptions;
+ parsedOptionList->setAutoDelete(true);
+ }
+
+ parsedOptionList->insert( opt, new QCString(value) );
+}
+
+QCString
+KCmdLineArgs::getOption(const char *_opt) const
+{
+ QCString *value = 0;
+ if (parsedOptionList)
+ {
+ value = parsedOptionList->find(_opt);
+ }
+
+ if (value)
+ return (*value);
+
+ // Look up the default.
+ const char *opt_name;
+ const char *def;
+ bool dummy = true;
+ QCString opt = _opt;
+ int result = ::findOption( options, opt, opt_name, def, dummy) & ~4;
+
+ if (result != 3)
+ {
+ fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
+ fprintf(stderr, "Application requests for getOption(\"%s\") but the \"%s\" option\n",
+ _opt, _opt);
+ fprintf(stderr, "has never been specified via addCmdLineOptions( ... )\n\n");
+
+ assert( 0 );
+ exit(255);
+ }
+ return QCString(def);
+}
+
+QCStringList
+KCmdLineArgs::getOptionList(const char *_opt) const
+{
+ QCStringList result;
+ if (!parsedOptionList)
+ return result;
+
+ while(true)
+ {
+ QCString *value = parsedOptionList->take(_opt);
+ if (!value)
+ break;
+ result.prepend(*value);
+ delete value;
+ }
+
+ // Reinsert items in dictionary
+ // WABA: This is rather silly, but I don't want to add restrictions
+ // to the API like "you can only call this function once".
+ // I can't access all items without taking them out of the list.
+ // So taking them out and then putting them back is the only way.
+ for(QCStringList::ConstIterator it=result.begin();
+ it != result.end();
+ ++it)
+ {
+ parsedOptionList->insert(_opt, new QCString(*it));
+ }
+ return result;
+}
+
+bool
+KCmdLineArgs::isSet(const char *_opt) const
+{
+ // Look up the default.
+ const char *opt_name;
+ const char *def;
+ bool dummy = true;
+ QCString opt = _opt;
+ int result = ::findOption( options, opt, opt_name, def, dummy) & ~4;
+
+ if (result == 0)
+ {
+ fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
+ fprintf(stderr, "Application requests for isSet(\"%s\") but the \"%s\" option\n",
+ _opt, _opt);
+ fprintf(stderr, "has never been specified via addCmdLineOptions( ... )\n\n");
+
+ assert( 0 );
+ exit(255);
+ }
+
+ QCString *value = 0;
+ if (parsedOptionList)
+ {
+ value = parsedOptionList->find(opt);
+ }
+
+ if (value)
+ {
+ if (result == 3)
+ return true;
+ else
+ return ((*value)[0] == 't');
+ }
+
+ if (result == 3)
+ return false; // String option has 'false' as default.
+
+ // We return 'true' as default if the option was listed as '-nofork'
+ // We return 'false' as default if the option was listed as '-fork'
+ return (result == 2);
+}
+
+int
+KCmdLineArgs::count() const
+{
+ if (!parsedArgList)
+ return 0;
+ return parsedArgList->count();
+}
+
+const char *
+KCmdLineArgs::arg(int n) const
+{
+ if (!parsedArgList || (n >= (int) parsedArgList->count()))
+ {
+ fprintf(stderr, "\n\nFAILURE (KCmdLineArgs): Argument out of bounds\n");
+ fprintf(stderr, "Application requests for arg(%d) without checking count() first.\n",
+ n);
+
+ assert( 0 );
+ exit(255);
+ }
+
+ return parsedArgList->at(n);
+}
+
+KURL
+KCmdLineArgs::url(int n) const
+{
+ return makeURL( arg(n) );
+}
+
+KURL KCmdLineArgs::makeURL(const char *_urlArg)
+{
+ const QString urlArg = QFile::decodeName(_urlArg);
+ QFileInfo fileInfo(urlArg);
+ if (!fileInfo.isRelative()) { // i.e. starts with '/', on unix
+ KURL result;
+ result.setPath(urlArg);
+ return result; // Absolute path.
+ }
+
+ if ( KURL::isRelativeURL(urlArg) || fileInfo.exists() ) {
+ KURL result;
+ result.setPath( cwd()+'/'+urlArg );
+ result.cleanPath();
+ return result; // Relative path
+ }
+
+ return KURL(urlArg); // Argument is a URL
+}
+
+void
+KCmdLineArgs::addArgument(const char *argument)
+{
+ if (!parsedArgList)
+ parsedArgList = new KCmdLineParsedArgs;
+
+ parsedArgList->append(argument);
+}
+
+static const KCmdLineOptions kde_tempfile_option[] =
+{
+ { "tempfile", I18N_NOOP("The files/URLs opened by the application will be deleted after use"), 0},
+ KCmdLineLastOption
+};
+
+void
+KCmdLineArgs::addTempFileOption()
+{
+ KCmdLineArgs::addCmdLineOptions( kde_tempfile_option, "KDE-tempfile", "kde-tempfile" );
+}
+
+bool KCmdLineArgs::isTempFileSet()
+{
+ KCmdLineArgs* args = KCmdLineArgs::parsedArgs( "kde-tempfile" );
+ if ( args )
+ return args->isSet( "tempfile" );
+ return false;
+}