• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KDECore

kcmdlineargs.cpp

Go to the documentation of this file.
00001 /*
00002    Copyright (C) 1999 Waldo Bastian <bastian@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License version 2 as published by the Free Software Foundation.
00007 
00008    This library is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011    Library General Public License for more details.
00012 
00013    You should have received a copy of the GNU Library General Public License
00014    along with this library; see the file COPYING.LIB.  If not, write to
00015    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016    Boston, MA 02110-1301, USA.
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    // WABA: Huh?
00066    // The compiler doesn't find KCmdLineParsedOptions::write(s) by itself ???
00067    // WABA: No, because there is another write function that hides the
00068    // write function in the base class even though this function has a
00069    // different signature. (obscure C++ feature)
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 // Static functions
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    // Strip path from argv[0]
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; // Options already present.
00223 
00224       if (id && args->id && (::qstrcmp(id, args->id) == 0))
00225    return; // Options already present.
00226 
00227       if (afterId && args->id && (::qstrcmp(afterId, args->id) == 0))
00228          pos = i+1;
00229    }
00230 
00231    assert( parsed == false ); // You must add _ALL_ cmd line options
00232                               // before accessing the arguments!
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    // Remove Qt and KDE options.
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; // don't reparse argc/argv!
00267 
00268    // Remove Qt and KDE options.
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  * @return:
00347  *  0 - option not found.
00348  *  1 - option found      // -fork
00349  *  2 - inverse option found ('no') // -nofork
00350  *  3 - option + arg found    // -fork now
00351  *
00352  *  +4 - no more options follow         // !fork
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       // Option not found check if it is a valid option
00454       // in the style of -Pprinter1 or ps -aux
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; // Unknown argument
00470 
00471          p++;
00472          if (result == 1) // Single option
00473          {
00474             args->setOption(singleCharOption, enabled);
00475             if (_opt[p])
00476                continue; // Next option
00477             else
00478                return; // Finished
00479          }
00480          else if (result == 3) // This option takes an argument
00481          {
00482             if (argument.isEmpty())
00483             {
00484                argument = _opt+p;
00485             }
00486             args->setOption(singleCharOption, argument);
00487             return;
00488          }
00489          break; // Unknown argument
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) // This option takes an argument
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          // Check whether appOptions allows these arguments
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(); // Lazy bastards!
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); // No qt options have been added!
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(); // Lazy bastards!
00714 
00715    static char** qt_argv;
00716    if( qt_argv != NULL )
00717       return &qt_argv;
00718 
00719    KCmdLineArgs *args = parsedArgs("qt");
00720    assert(args); // No qt options have been added!
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     // called twice or too late
00746     if (KGlobal::_locale)
00747       return;
00748 
00749     if (!KGlobal::_instance) {
00750   KInstance *instance = new KInstance(about);
00751   (void) instance->config();
00752   // Don't delete instance!
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); // It's an error to call usage(...) without
00776                           // having done addCmdLineOptions first!
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(); // Sets current to 1st.
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          // Option header
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          // Free-form comment
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          // Options
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 // Member functions
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       // Qt does it own parsing.
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       // Qt does it's own parsing.
01095       QCString arg = "-";
01096       arg += opt;
01097       addArgument(arg);
01098       addArgument(value);
01099 
01100 #ifdef Q_WS_X11
01101       // Hack coming up!
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    // Look up the default.
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    // Reinsert items in dictionary
01165    // WABA: This is rather silly, but I don't want to add restrictions
01166    // to the API like "you can only call this function once".
01167    // I can't access all items without taking them out of the list.
01168    // So taking them out and then putting them back is the only way.
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    // Look up the default.
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; // String option has 'false' as default.
01215 
01216    // We return 'true' as default if the option was listed as '-nofork'
01217    // We return 'false' as default if the option was listed as '-fork'
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()) { // i.e. starts with '/', on unix
01256       KURL result;
01257       result.setPath(urlArg);
01258       return result; // Absolute path.
01259    }
01260 
01261    if ( KURL::isRelativeURL(urlArg) || fileInfo.exists() ) {
01262       KURL result;
01263       result.setPath( cwd()+'/'+urlArg );
01264       result.cleanPath();
01265       return result;  // Relative path
01266    }
01267 
01268    return KURL(urlArg); // Argument is a URL
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 }

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal