kdecore Library: kcmdlineargs.cpp Source File (kdecore Library)

| # kdecore Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# kcmdlineargs.cpp

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

This file is part of the documentation for kdecore Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:18:02 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003