kcmdlineargs.cpp Source File (kdecore Library)

| # kdecore Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | 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 #if HAVE_LIMITS_H
    00030 #include <limits.h>
    00031 #endif
    00032
    00033 #include <qfile.h>
    00034 #include <qasciidict.h>
    00035 #include <qstrlist.h>
    00036
    00037 #include "kcmdlineargs.h"
    00038 #include <kaboutdata.h>
    00039 #include <klocale.h>
    00040 #include <kapplication.h>
    00041 #include <kglobal.h>
    00042 #include <kstringhandler.h>
    00043 #include <kstaticdeleter.h>
    00044
    00045 #ifdef Q_WS_X11
    00046 #define DISPLAY "DISPLAY"
    00047 #elif defined(Q_WS_QWS)
    00048 #define DISPLAY "QWS_DISPLAY"
    00049 #endif
    00050
    00051 template class QAsciiDict<QCString>;
    00052 template class QPtrList<KCmdLineArgs>;
    00053
    00054 class KCmdLineParsedOptions : public QAsciiDict<QCString>
    00055 {
    00056 public:
    00057    KCmdLineParsedOptions()
    00058      : QAsciiDict<QCString>( 7 ) { }
    00059
    00060    // WABA: Huh?
    00061    // The compiler doesn't find KCmdLineParsedOptions::write(s) by itself ???
    00062    // WABA: No, because there is another write function that hides the
    00063    // write function in the base class even though this function has a
    00064    // different signature. (obscure C++ feature)
    00065    QDataStream& save( QDataStream &s) const
    00066    { return QGDict::write(s); }
    00067
    00068    QDataStream& load( QDataStream &s)
    00069    { return QGDict::read(s); }
    00070
    00071 protected:
    00072    virtual QDataStream& write( QDataStream &s, QPtrCollection::Item data) const
    00073    {
    00074       QCString *str = (QCString *) data;
    00075       s << (*str);
    00076       return s;
    00077    }
    00078
    00079    virtual QDataStream& read( QDataStream &s, QPtrCollection::Item &item)
    00080    {
    00081       QCString *str = new QCString;
    00082       s >> (*str);
    00083       item = (void *)str;
    00084       return s;
    00085    }
    00086
    00087 };
    00088
    00089 class KCmdLineParsedArgs : public QStrList
    00090 {
    00091 public:
    00092    KCmdLineParsedArgs()
    00093      : QStrList( true ) { }
    00094    QDataStream& save( QDataStream &s) const
    00095    { return QGList::write(s); }
    00096
    00097    QDataStream& load( QDataStream &s)
    00098    { return QGList::read(s); }
    00099 };
    00100
    00101
    00102 class KCmdLineArgsList: public QPtrList<KCmdLineArgs>
    00103 {
    00104 public:
    00105    KCmdLineArgsList() { }
    00106 };
    00107
    00108 KCmdLineArgsList *KCmdLineArgs::argsList = 0;
    00109 int KCmdLineArgs::argc = 0;
    00110 char **KCmdLineArgs::argv = 0;
    00111 char *KCmdLineArgs::mCwd = 0;
    00112 static KStaticDeleter <char> mCwdd;
    00113 const KAboutData *KCmdLineArgs::about = 0;
    00114 bool KCmdLineArgs::parsed = false;
    00115 bool KCmdLineArgs::ignoreUnknown = false;
    00116
    00117 //
    00118 // Static functions
    00119 //
    00120
    00121 void
    00122 KCmdLineArgs::init(int _argc, char **_argv, const char *_appname,
    00123                    const char *_description, const char *_version, bool noKApp)
    00124 {
    00125    init(_argc, _argv,
    00126         new KAboutData(_appname, _appname, _version, _description),
    00127         noKApp);
    00128 }
    00129
    00130 void
    00131 KCmdLineArgs::initIgnore(int _argc, char **_argv, const char *_appname )
    00132 {
    00133    init(_argc, _argv,
    00134         new KAboutData(_appname, _appname, "unknown", "KDE Application", false));
    00135    ignoreUnknown = true;
    00136 }
    00137
    00138 void
    00139 KCmdLineArgs::init(const KAboutData* ab)
    00140 {
    00141    init(0,0,ab, true);
    00142 }
    00143
    00144
    00145 void
    00146 KCmdLineArgs::init(int _argc, char **_argv, const KAboutData *_about, bool noKApp)
    00147 {
    00148    assert( argsList == 0 );     // Don't call init twice.
    00149    assert( argc == 0 );         // Don't call init twice.
    00150    assert( argv == 0 );         // Don't call init twice.
    00151    assert( about == 0 );        // Don't call init twice.
    00152    argc = _argc;
    00153    argv = _argv;
    00154
    00155    if (!argv)
    00156    {
    00157       fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
    00158       fprintf(stderr, "Passing null-pointer to 'argv' is not allowed.\n\n");
    00159
    00160       assert( 0 );
    00161       exit(255);
    00162    }
    00163
    00164    // Strip path from argv[0]
    00165    if (argc) {
    00166      char *p = strrchr( argv[0], '/');
    00167      if (p)
    00168        argv[0] = p+1;
    00169    }
    00170
    00171    about = _about;
    00172    parsed = false;
    00173    mCwd = mCwdd.setObject(new char [PATH_MAX+1], true);
    00174    getcwd(mCwd, PATH_MAX);
    00175    if (!noKApp)
    00176       KApplication::addCmdLineOptions();
    00177 }
    00178
    00179 QString KCmdLineArgs::cwd()
    00180 {
    00181    return QFile::decodeName(QCString(mCwd));
    00182 }
    00183
    00184 const char * KCmdLineArgs::appName()
    00185 {
    00186    if (!argc) return 0;
    00187    return argv[0];
    00188 }
    00189
    00190 void
    00191 KCmdLineArgs::addCmdLineOptions( const KCmdLineOptions *options, const char *name,
    00192                                  const char *id, const char *afterId)
    00193 {
    00194    if (!argsList)
    00195       argsList = new KCmdLineArgsList();
    00196
    00197    int pos = argsList->count();
    00198
    00199    if (pos && id && argsList->last() && !argsList->last()->name)
    00200       pos--;
    00201
    00202    KCmdLineArgs *args;
    00203    int i = 0;
    00204    for(args = argsList->first(); args; args = argsList->next(), i++)
    00205    {
    00206       if (!id && !args->id)
    00207          return; // Options already present.
    00208
    00209       if (id && args->id && (::qstrcmp(id, args->id) == 0))
    00210          return; // Options already present.
    00211
    00212       if (afterId && args->id && (::qstrcmp(afterId, args->id) == 0))
    00213          pos = i+1;
    00214    }
    00215
    00216    assert( parsed == false ); // You must add _ALL_ cmd line options
    00217                               // before accessing the arguments!
    00218    args = new KCmdLineArgs(options, name, id);
    00219    argsList->insert(pos, args);
    00220 }
    00221
    00222 void
    00223 KCmdLineArgs::saveAppArgs( QDataStream &ds)
    00224 {
    00225    if (!parsed)
    00226       parseAllArgs();
    00227
    00228    // Remove Qt and KDE options.
    00229    removeArgs("qt");
    00230    removeArgs("kde");
    00231
    00232    QCString qCwd = mCwd;
    00233    ds << qCwd;
    00234
    00235    uint count = argsList ? argsList->count() : 0;
    00236    ds << count;
    00237
    00238    if (!count) return;
    00239
    00240    KCmdLineArgs *args;
    00241    for(args = argsList->first(); args; args = argsList->next())
    00242    {
    00243       args->save(ds);
    00244    }
    00245 }
    00246
    00247 void
    00248 KCmdLineArgs::loadAppArgs( QDataStream &ds)
    00249 {
    00250    // Remove Qt and KDE options.
    00251    removeArgs("qt");
    00252    removeArgs("kde");
    00253
    00254    KCmdLineArgs *args;
    00255    if (argsList)
    00256    {
    00257       for(args = argsList->first(); args; args = argsList->next())
    00258       {
    00259          args->clear();
    00260       }
    00261    }
    00262
    00263    QCString qCwd;
    00264    ds >> qCwd;
    00265    if (mCwd)
    00266       delete [] mCwd;
    00267
    00268    mCwd = mCwdd.setObject(new char[qCwd.length()+1], true);
    00269    strncpy(mCwd, qCwd.data(), qCwd.length()+1);
    00270
    00271    uint count;
    00272    ds >> count;
    00273
    00274    if (count == 0)
    00275       return;
    00276
    00277    if (!argsList || (count != argsList->count()))
    00278    {
    00279       fprintf(stderr, "loadAppArgs:: Unexpected number of command line sets "
    00280                       "(%d instead of %d)\n", count, argsList ? argsList->count() : 0);
    00281       return;
    00282    }
    00283
    00284    for(args = argsList->first(); args; args = argsList->next())
    00285    {
    00286       args->load(ds);
    00287    }
    00288 }
    00289
    00290 KCmdLineArgs *KCmdLineArgs::parsedArgs(const char *id)
    00291 {
    00292    KCmdLineArgs *args = argsList ? argsList->first() : 0;
    00293    while(args)
    00294    {
    00295       if ((id && ::qstrcmp(args->id, id) == 0) || (!id && !args->id))
    00296       {
    00297           if (!parsed)
    00298              parseAllArgs();
    00299           return args;
    00300       }
    00301       args = argsList->next();
    00302    }
    00303
    00304    if (!args)
    00305    {
    00306 #ifndef NDEBUG
    00307       fprintf(stderr, "WARNING (KCmdLineArgs):\n");
    00308       fprintf(stderr, "Application requests for parsedArgs(\"%s\") without a prior call\n", id?id:"null");
    00309       fprintf(stderr, "to addCmdLineOptions( ..., \"%s\")\n\n", id?id:"null");
    00310 #endif
    00311    }
    00312    return args;
    00313 }
    00314
    00315 void KCmdLineArgs::removeArgs(const char *id)
    00316 {
    00317    KCmdLineArgs *args = argsList ? argsList->first() : 0;
    00318    while(args)
    00319    {
    00320       if (args->id && id && ::qstrcmp(args->id, id) == 0)
    00321       {
    00322           if (!parsed)
    00323              parseAllArgs();
    00324           break;
    00325       }
    00326       args = argsList->next();
    00327    }
    00328
    00329    if (args)
    00330       delete args;
    00331 }
    00332
    00333 /*
    00334  * @return:
    00335  *  0 - option not found.
    00336  *  1 - option found                    // -fork
    00337  *  2 - inverse option found ('no')     // -nofork
    00338  *  3 - option + arg found              // -fork now
    00339  *
    00340  *  +4 - no more options follow         // !fork
    00341  */
    00342 static int
    00343 findOption(const KCmdLineOptions *options, QCString &opt,
    00344            const char *&opt_name, const char *&def, bool &enabled)
    00345 {
    00346    int result;
    00347    bool inverse;
    00348    int len = opt.length();
    00349    while(options && options->name)
    00350    {
    00351       result = 0;
    00352       inverse = false;
    00353       opt_name = options->name;
    00354       if (opt_name[0] == '!')
    00355       {
    00356          opt_name++;
    00357          result = 4;
    00358       }
    00359       if ((opt_name[0] == 'n') && (opt_name[1] == 'o'))
    00360       {
    00361          opt_name += 2;
    00362          inverse = true;
    00363       }
    00364       if (strncmp(opt.data(), opt_name, len) == 0)
    00365       {
    00366          opt_name += len;
    00367          if (!opt_name[0])
    00368          {
    00369             if (inverse)
    00370                return result+2;
    00371
    00372             if (!options->description)
    00373             {
    00374                options++;
    00375                if (!options->name)
    00376                   return result+0;
    00377                QCString nextOption = options->name;
    00378                int p = nextOption.find(' ');
    00379                if (p > 0)
    00380                   nextOption = nextOption.left(p);
    00381                if (strncmp(nextOption.data(), "no", 2) == 0)
    00382                {
    00383                   nextOption = nextOption.mid(2);
    00384                   enabled = !enabled;
    00385                }
    00386                result = findOption(options, nextOption, opt_name, def, enabled);
    00387                assert(result);
    00388                opt = nextOption;
    00389                return result;
    00390             }
    00391
    00392             return 1;
    00393          }
    00394          if (opt_name[0] == ' ')
    00395          {
    00396             opt_name++;
    00397             def = options->def;
    00398             return result+3;
    00399          }
    00400       }
    00401
    00402       options++;
    00403    }
    00404    return 0;
    00405 }
    00406
    00407
    00408 void
    00409 KCmdLineArgs::findOption(const char *_opt, QCString opt, int &i, bool _enabled, bool &moreOptions)
    00410 {
    00411    KCmdLineArgs *args = argsList->first();
    00412    const char *opt_name;
    00413    const char *def;
    00414    QCString argument;
    00415    int j = opt.find('=');
    00416    if (j != -1)
    00417    {
    00418       argument = opt.mid(j+1);
    00419       opt = opt.left(j);
    00420    }
    00421
    00422    bool enabled = true;
    00423    int result = 0;
    00424    while (args)
    00425    {
    00426       enabled = _enabled;
    00427       result = ::findOption(args->options, opt, opt_name, def, enabled);
    00428       if (result) break;
    00429       args = argsList->next();
    00430    }
    00431    if (!args && (_opt[0] == '-') && _opt[1] && (_opt[1] != '-'))
    00432    {
    00433       // Option not found check if it is a valid option
    00434       // in the style of -Pprinter1 or ps -aux
    00435       int p = 1;
    00436       while (true)
    00437       {
    00438          QCString singleCharOption = " ";
    00439          singleCharOption[0] = _opt[p];
    00440          args = argsList->first();
    00441          while (args)
    00442          {
    00443             enabled = _enabled;
    00444             result = ::findOption(args->options, singleCharOption, opt_name, def, enabled);
    00445             if (result) break;
    00446             args = argsList->next();
    00447          }
    00448          if (!args)
    00449             break; // Unknown argument
    00450
    00451          p++;
    00452          if (result == 1) // Single option
    00453          {
    00454             args->setOption(singleCharOption, enabled);
    00455             if (_opt[p])
    00456                continue; // Next option
    00457             else
    00458                return; // Finished
    00459          }
    00460          else if (result == 3) // This option takes an argument
    00461          {
    00462             if (argument.isEmpty())
    00463             {
    00464                argument = _opt+p;
    00465             }
    00466             args->setOption(singleCharOption, argument);
    00467             return;
    00468          }
    00469          break; // Unknown argument
    00470       }
    00471       args = 0;
    00472       result = 0;
    00473    }
    00474
    00475    if (!args || !result)
    00476    {
    00477       if (ignoreUnknown)
    00478          return;
    00479       enable_i18n();
    00480       usage( i18n("Unknown option '%1'.").arg(_opt));
    00481    }
    00482
    00483    if ((result & 4) != 0)
    00484    {
    00485       result &= ~4;
    00486       moreOptions = false;
    00487    }
    00488
    00489    if (result == 3) // This option takes an argument
    00490    {
    00491       if (!enabled)
    00492       {
    00493          if (ignoreUnknown)
    00494             return;
    00495          enable_i18n();
    00496          usage( i18n("Unknown option '%1'.").arg(_opt));
    00497       }
    00498       if (argument.isEmpty())
    00499       {
    00500          i++;
    00501          if (i >= argc)
    00502          {
    00503             enable_i18n();
    00504             usage( i18n("'%1' missing.").arg( opt_name));
    00505          }
    00506          argument = argv[i];
    00507       }
    00508       args->setOption(opt, argument);
    00509    }
    00510    else
    00511    {
    00512       args->setOption(opt, enabled);
    00513    }
    00514 }
    00515
    00516 void
    00517 KCmdLineArgs::printQ(const QString &msg)
    00518 {
    00519    QCString localMsg = msg.local8Bit();
    00520    fprintf(stdout, "%s", localMsg.data());
    00521 }
    00522
    00523 void
    00524 KCmdLineArgs::parseAllArgs()
    00525 {
    00526    bool allowArgs = false;
    00527    bool inOptions = true;
    00528    bool everythingAfterArgIsArgs = false;
    00529    KCmdLineArgs *appOptions = argsList->last();
    00530    if (!appOptions->id)
    00531    {
    00532      const KCmdLineOptions *option = appOptions->options;
    00533      while(option && option->name)
    00534      {
    00535        if (option->name[0] == '+')
    00536            allowArgs = true;
    00537        if ( option->name[0] == '!' && option->name[1] == '+' )
    00538        {
    00539            allowArgs = true;
    00540            everythingAfterArgIsArgs = true;
    00541        }
    00542        option++;
    00543      }
    00544    }
    00545    for(int i = 1; i < argc; i++)
    00546    {
    00547       if (!argv[i])
    00548          continue;
    00549
    00550       if ((argv[i][0] == '-') && argv[i][1] && inOptions)
    00551       {
    00552          bool enabled = true;
    00553          const char *option = &argv[i][1];
    00554          const char *orig = argv[i];
    00555          if (option[0] == '-')
    00556          {
    00557             option++;
    00558             argv[i]++;
    00559             if (!option[0])
    00560             {
    00561                inOptions = false;
    00562                continue;
    00563             }
    00564          }
    00565          if (::qstrcmp(option, "help") == 0)
    00566          {
    00567             usage(0);
    00568          }
    00569          else if (strncmp(option, "help-",5) == 0)
    00570          {
    00571             usage(option+5);
    00572          }
    00573          else if ( (::qstrcmp(option, "version") == 0) ||
    00574                    (::qstrcmp(option, "v") == 0))
    00575          {
    00576             printQ( QString("Qt: %1\n").arg(qVersion()));
    00577             printQ( QString("KDE: %1\n").arg(KDE_VERSION_STRING));
    00578             printQ( QString("%1: %2\n").
    00579                         arg(about->programName()).arg(about->version()));
    00580             exit(0);
    00581          } else if ( (::qstrcmp(option, "license") == 0) )
    00582          {
    00583             enable_i18n();
    00584             printQ( about->license() );
    00585             printQ( "\n" );
    00586             exit(0);
    00587          } else if ( ::qstrcmp( option, "author") == 0 ) {
    00588              enable_i18n();
    00589              if ( about ) {
    00590                  const QValueList<KAboutPerson> authors = about->authors();
    00591                  if ( !authors.isEmpty() ) {
    00592                      QString authorlist;
    00593                      for (QValueList<KAboutPerson>::ConstIterator it = authors.begin(); it != authors.end(); ++it ) {
    00594                          authorlist += QString("    ") + (*it).name() + " <" + (*it).emailAddress() + ">\n";
    00595                      }
    00596                      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 ) );
    00597                  }
    00598              } else {
    00599                  printQ( i18n("%1 was written by somebody who wants to remain anonymous.").arg(about->programName()) );
    00600              }
    00601              if (!about->bugAddress().isEmpty())
    00602              {
    00603                 QString bugReporting = i18n( "Please use http://bugs.kde.org to report bugs, do not mail the authors directly.\n" );
    00604                 if (about->bugAddress() != "submit@bugs.kde.org")
    00605                     bugReporting.replace("http://bugs.kde.org", about->bugAddress());
    00606                 printQ(bugReporting);
    00607              }
    00608              exit(0);
    00609          } else {
    00610            if ((option[0] == 'n') && (option[1] == 'o'))
    00611            {
    00612               option += 2;
    00613               enabled = false;
    00614            }
    00615            findOption(orig, option, i, enabled, inOptions);
    00616          }
    00617       }
    00618       else
    00619       {
    00620          // Check whether appOptions allows these arguments
    00621          if (!allowArgs)
    00622          {
    00623             if (ignoreUnknown)
    00624                continue;
    00625             enable_i18n();
    00626             usage( i18n("Unexpected argument '%1'.").arg( argv[i]));
    00627          }
    00628          else
    00629          {
    00630             appOptions->addArgument(argv[i]);
    00631             if (everythingAfterArgIsArgs)
    00632                 inOptions = false;
    00633          }
    00634       }
    00635    }
    00636    parsed = true;
    00637 }
    00638
    00644 int *
    00645 KCmdLineArgs::qt_argc()
    00646 {
    00647    if (!argsList)
    00648       KApplication::addCmdLineOptions(); // Lazy bastards!
    00649
    00650    KCmdLineArgs *args = parsedArgs("qt");
    00651
    00652    assert(args); // No qt options have been added!
    00653    if (!argv)
    00654    {
    00655       fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
    00656       fprintf(stderr, "Application has not called KCmdLineArgs::init(...).\n\n");
    00657
    00658       assert( 0 );
    00659       exit(255);
    00660    }
    00661
    00662    assert(argc >= (args->count()+1));
    00663    argc = args->count() +1;
    00664    return &argc;
    00665 }
    00666
    00672 char ***
    00673 KCmdLineArgs::qt_argv()
    00674 {
    00675    if (!argsList)
    00676       KApplication::addCmdLineOptions(); // Lazy bastards!
    00677
    00678    KCmdLineArgs *args = parsedArgs("qt");
    00679    assert(args); // No qt options have been added!
    00680    if (!argv)
    00681    {
    00682       fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
    00683       fprintf(stderr, "Application has not called KCmdLineArgs::init(...).\n\n");
    00684
    00685       assert( 0 );
    00686       exit(255);
    00687    }
    00688
    00689    int i = 0;
    00690    for(; i < args->count(); i++)
    00691    {
    00692       argv[i+1] = (char *) args->arg(i);
    00693    }
    00694    argv[i+1] = 0;
    00695
    00696    return &argv;
    00697 }
    00698
    00699 void
    00700 KCmdLineArgs::enable_i18n()
    00701 {
    00702     // called twice or too late
    00703     if (KGlobal::_locale)
    00704             return;
    00705
    00706     if (!KGlobal::_instance) {
    00707         KInstance *instance = new KInstance(about);
    00708         (void) instance->config();
    00709         // Don't delete instance!
    00710     }
    00711 }
    00712
    00713 void
    00714 KCmdLineArgs::usage(const QString &error)
    00715 {
    00716     assert(KGlobal::_locale);
    00717     QCString localError = error.local8Bit();
    00718     if (localError[error.length()-1] == '\n')
    00719         localError = localError.left(error.length()-1);
    00720     fprintf(stderr, "%s: %s\n", argv[0], localError.data());
    00721
    00722     QString tmp = i18n("Use --help to get a list of available command line options.");
    00723     localError = tmp.local8Bit();
    00724     fprintf(stderr, "%s: %s\n", argv[0], localError.data());
    00725     exit(254);
    00726 }
    00727
    00728 void
    00729 KCmdLineArgs::usage(const char *id)
    00730 {
    00731    enable_i18n();
    00732    assert(argsList != 0); // It's an error to call usage(...) without
    00733                           // having done addCmdLineOptions first!
    00734
    00735    QString optionFormatString           = "  %1 %2\n";
    00736    QString optionFormatStringDef        = "  %1 %2 [%3]\n";
    00737    QString optionHeaderString = i18n("\n%1:\n");
    00738    QString tmp;
    00739    QString usage;
    00740
    00741    KCmdLineArgs *args = argsList->last();
    00742
    00743    if (!(args->id) && (args->options) &&
    00744        (args->options->name) && (args->options->name[0] != '+'))
    00745    {
    00746       usage = i18n("[options] ")+usage;
    00747    }
    00748
    00749    while(args)
    00750    {
    00751       if (args->name)
    00752       {
    00753          usage = QString(i18n("[%1-options]")).arg(args->name)+" "+usage;
    00754       }
    00755       args = argsList->prev();
    00756    }
    00757
    00758    KCmdLineArgs *appOptions = argsList->last();
    00759    if (!appOptions->id)
    00760    {
    00761      const KCmdLineOptions *option = appOptions->options;
    00762      while(option && option->name)
    00763      {
    00764        if (option->name[0] == '+')
    00765           usage = usage + (option->name+1) + " ";
    00766        else if ( option->name[0] == '!' && option->name[1] == '+' )
    00767           usage = usage + (option->name+2) + " ";
    00768
    00769        option++;
    00770      }
    00771    }
    00772
    00773    printQ(i18n("Usage: %1 %2\n").arg(argv[0]).arg(usage));
    00774    printQ("\n"+about->shortDescription()+"\n");
    00775
    00776    printQ(optionHeaderString.arg(i18n("Generic options")));
    00777    printQ(optionFormatString.arg("--help", -25).arg(i18n("Show help about options")));
    00778
    00779    args = argsList->first();
    00780    while(args)
    00781    {
    00782       if (args->name && args->id)
    00783       {
    00784          QString option = QString("--help-%1").arg(args->id);
    00785          QString desc = i18n("Show %1 specific options").arg(args->name);
    00786
    00787          printQ(optionFormatString.arg(option, -25).arg(desc));
    00788       }
    00789       args = argsList->next();
    00790    }
    00791
    00792    printQ(optionFormatString.arg("--help-all",-25).arg(i18n("Show all options")));
    00793    printQ(optionFormatString.arg("--author",-25).arg(i18n("Show author information")));
    00794    printQ(optionFormatString.arg("-v, --version",-25).arg(i18n("Show version information")));
    00795    printQ(optionFormatString.arg("--license",-25).arg(i18n("Show license information")));
    00796    printQ(optionFormatString.arg("--", -25).arg(i18n("End of options")));
    00797
    00798    args = argsList->first(); // Sets current to 1st.
    00799
    00800    bool showAll = id && (::qstrcmp(id, "all") == 0);
    00801
    00802    if (!showAll)
    00803    {
    00804      while(args)
    00805      {
    00806        if (!id && !args->id) break;
    00807        if (id && (::qstrcmp(args->id, id) == 0)) break;
    00808        args = argsList->next();
    00809      }
    00810    }
    00811
    00812    while(args)
    00813    {
    00814      bool hasArgs = false;
    00815      bool hasOptions = false;
    00816      while (args)
    00817      {
    00818        const KCmdLineOptions *option = args->options;
    00819        QCString opt = "";
    00820 //
    00821        while(option && option->name)
    00822        {
    00823          QString description;
    00824          QString descriptionRest;
    00825          QStringList dl;
    00826          if (option->description)
    00827          {
    00828             description = i18n(option->description);
    00829             dl = QStringList::split("\n", description, true);
    00830             description = dl.first();
    00831             dl.remove( dl.begin() );
    00832          }
    00833          QCString name = option->name;
    00834          if (name[0] == '!')
    00835              name = name.mid(1);
    00836
    00837          if (name[0] == '+')
    00838          {
    00839             if (!hasArgs)
    00840             {
    00841                printQ(i18n("\nArguments:\n"));
    00842                hasArgs = true;
    00843             }
    00844
    00845             name = name.mid(1);
    00846             if ((name[0] == '[') && (name[name.length()-1] == ']'))
    00847                name = name.mid(1, name.length()-2);
    00848             printQ(optionFormatString.arg(name, -25)
    00849                  .arg(description));
    00850          }
    00851          else
    00852          {
    00853             if (!hasOptions)
    00854             {
    00855                if (!args->name)
    00856                   printQ(i18n("\nOptions:\n"));
    00857                else if (args->name)
    00858                   printQ(optionHeaderString.arg(i18n("%1 options").arg(QString::fromLatin1(args->name))));
    00859                hasOptions = true;
    00860             }
    00861
    00862             if ((name.length() == 1) || (name[1] == ' '))
    00863                name = "-"+name;
    00864             else
    00865                name = "--"+name;
    00866             if (!option->description)
    00867             {
    00868                opt = name + ", ";
    00869             }
    00870             else
    00871             {
    00872                opt = opt + name;
    00873                if (!option->def)
    00874                {
    00875                   printQ(optionFormatString.arg(opt, -25)
    00876                          .arg(description));
    00877                }
    00878                else
    00879                {
    00880                   printQ(optionFormatStringDef.arg(opt, -25)
    00881                          .arg(description).arg(option->def));
    00882                }
    00883                opt = "";
    00884             }
    00885          }
    00886          for(QStringList::Iterator it = dl.begin();
    00887              it != dl.end();
    00888              it++)
    00889          {
    00890             printQ(optionFormatString.arg("", -25).arg(*it));
    00891          }
    00892
    00893          option++;
    00894        }
    00895        args = argsList->next();
    00896        if (!args || args->name || !args->id) break;
    00897      }
    00898      if (!showAll) break;
    00899    }
    00900
    00901    exit(254);
    00902 }
    00903
    00904 //
    00905 // Member functions
    00906 //
    00907
    00913 KCmdLineArgs::KCmdLineArgs( const KCmdLineOptions *_options,
    00914                             const char *_name, const char *_id)
    00915   : options(_options), name(_name), id(_id)
    00916 {
    00917   parsedOptionList = 0;
    00918   parsedArgList = 0;
    00919   isQt = (::qstrcmp(id, "qt") == 0);
    00920 }
    00921
    00925 KCmdLineArgs::~KCmdLineArgs()
    00926 {
    00927   delete parsedOptionList;
    00928   delete parsedArgList;
    00929   if (argsList)
    00930   {
    00931      argsList->removeRef(this);
    00932      if (argsList->count() == 0)
    00933      {
    00934         delete argsList;
    00935         argsList = 0;
    00936      }
    00937   }
    00938 }
    00939
    00940 void
    00941 KCmdLineArgs::clear()
    00942 {
    00943    delete parsedArgList;
    00944    parsedArgList = 0;
    00945    delete parsedOptionList;
    00946    parsedOptionList = 0;
    00947 }
    00948
    00949 void
    00950 KCmdLineArgs::save( QDataStream &ds) const
    00951 {
    00952    uint count = 0;
    00953    if (parsedOptionList)
    00954       parsedOptionList->save( ds );
    00955    else
    00956       ds << count;
    00957
    00958    if (parsedArgList)
    00959       parsedArgList->save( ds );
    00960    else
    00961       ds << count;
    00962 }
    00963
    00964 void
    00965 KCmdLineArgs::load( QDataStream &ds)
    00966 {
    00967    if (!parsedOptionList) parsedOptionList = new KCmdLineParsedOptions;
    00968    if (!parsedArgList) parsedArgList = new KCmdLineParsedArgs;
    00969
    00970    parsedOptionList->load( ds );
    00971    parsedArgList->load( ds );
    00972
    00973    if (parsedOptionList->count() == 0)
    00974    {
    00975       delete parsedOptionList;
    00976       parsedOptionList = 0;
    00977    }
    00978    if (parsedArgList->count() == 0)
    00979    {
    00980       delete parsedArgList;
    00981       parsedArgList = 0;
    00982    }
    00983 }
    00984
    00985 void
    00986 KCmdLineArgs::setOption(const QCString &opt, bool enabled)
    00987 {
    00988    if (isQt)
    00989    {
    00990       // Qt does it own parsing.
    00991       QCString arg = "-";
    00992       if( !enabled )
    00993           arg += "no";
    00994       arg += opt;
    00995       addArgument(arg);
    00996    }
    00997    if (!parsedOptionList) {
    00998         parsedOptionList = new KCmdLineParsedOptions;
    00999         parsedOptionList->setAutoDelete(true);
    01000    }
    01001
    01002    if (enabled)
    01003       parsedOptionList->replace( opt, new QCString("t") );
    01004    else
    01005       parsedOptionList->replace( opt, new QCString("f") );
    01006 }
    01007
    01008 void
    01009 KCmdLineArgs::setOption(const QCString &opt, const char *value)
    01010 {
    01011    if (isQt)
    01012    {
    01013       // Qt does it's own parsing.
    01014       QCString arg = "-";
    01015       arg += opt;
    01016       addArgument(arg);
    01017       addArgument(value);
    01018
    01019       // Hack coming up!
    01020       if (arg == "-display")
    01021       {
    01022          setenv(DISPLAY, value, true);
    01023       }
    01024    }
    01025    if (!parsedOptionList) {
    01026         parsedOptionList = new KCmdLineParsedOptions;
    01027         parsedOptionList->setAutoDelete(true);
    01028    }
    01029
    01030    parsedOptionList->insert( opt, new QCString(value) );
    01031 }
    01032
    01033 QCString
    01034 KCmdLineArgs::getOption(const char *_opt) const
    01035 {
    01036    QCString *value = 0;
    01037    if (parsedOptionList)
    01038    {
    01039       value = parsedOptionList->find(_opt);
    01040    }
    01041
    01042    if (value)
    01043       return (*value);
    01044
    01045    // Look up the default.
    01046    const char *opt_name;
    01047    const char *def;
    01048    bool dummy = true;
    01049    QCString opt = _opt;
    01050    int result = ::findOption( options, opt, opt_name, def, dummy) & ~4;
    01051
    01052    if (result != 3)
    01053    {
    01054       fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
    01055       fprintf(stderr, "Application requests for getOption(\"%s\") but the \"%s\" option\n",
    01056                       _opt, _opt);
    01057       fprintf(stderr, "has never been specified via addCmdLineOptions( ... )\n\n");
    01058
    01059       assert( 0 );
    01060       exit(255);
    01061    }
    01062    return QCString(def);
    01063 }
    01064
    01065 QCStringList
    01066 KCmdLineArgs::getOptionList(const char *_opt) const
    01067 {
    01068    QCStringList result;
    01069    if (!parsedOptionList)
    01070       return result;
    01071
    01072    while(true)
    01073    {
    01074       QCString *value = parsedOptionList->take(_opt);
    01075       if (!value)
    01076          break;
    01077       result.prepend(*value);
    01078       delete value;
    01079    }
    01080
    01081    // Reinsert items in dictionary
    01082    // WABA: This is rather silly, but I don't want to add restrictions
    01083    // to the API like "you can only call this function once".
    01084    // I can't access all items without taking them out of the list.
    01085    // So taking them out and then putting them back is the only way.
    01086    for(QCStringList::ConstIterator it=result.begin();
    01087        it != result.end();
    01088        ++it)
    01089    {
    01090       parsedOptionList->insert(_opt, new QCString(*it));
    01091    }
    01092    return result;
    01093 }
    01094
    01095 bool
    01096 KCmdLineArgs::isSet(const char *_opt) const
    01097 {
    01098    // Look up the default.
    01099    const char *opt_name;
    01100    const char *def;
    01101    bool dummy = true;
    01102    QCString opt = _opt;
    01103    int result = ::findOption( options, opt, opt_name, def, dummy) & ~4;
    01104
    01105    if (result == 0)
    01106    {
    01107       fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
    01108       fprintf(stderr, "Application requests for isSet(\"%s\") but the \"%s\" option\n",
    01109                       _opt, _opt);
    01110       fprintf(stderr, "has never been specified via addCmdLineOptions( ... )\n\n");
    01111
    01112       assert( 0 );
    01113       exit(255);
    01114    }
    01115
    01116    QCString *value = 0;
    01117    if (parsedOptionList)
    01118    {
    01119       value = parsedOptionList->find(opt);
    01120    }
    01121
    01122    if (value)
    01123    {
    01124       if (result == 3)
    01125          return true;
    01126       else
    01127          return ((*value)[0] == 't');
    01128    }
    01129
    01130    if (result == 3)
    01131       return false; // String option has 'false' as default.
    01132
    01133    // We return 'true' as default if the option was listed as '-nofork'
    01134    // We return 'false' as default if the option was listed as '-fork'
    01135    return (result == 2);
    01136 }
    01137
    01138 int
    01139 KCmdLineArgs::count() const
    01140 {
    01141    if (!parsedArgList)
    01142       return 0;
    01143    return parsedArgList->count();
    01144 }
    01145
    01146 const char *
    01147 KCmdLineArgs::arg(int n) const
    01148 {
    01149    if (!parsedArgList || (n >= (int) parsedArgList->count()))
    01150    {
    01151       fprintf(stderr, "\n\nFAILURE (KCmdLineArgs): Argument out of bounds\n");
    01152       fprintf(stderr, "Application requests for arg(%d) without checking count() first.\n",
    01153                       n);
    01154
    01155       assert( 0 );
    01156       exit(255);
    01157    }
    01158
    01159    return parsedArgList->at(n);
    01160 }
    01161
    01162 KURL
    01163 KCmdLineArgs::url(int n) const
    01164 {
    01165    return makeURL( arg(n) );
    01166 }
    01167
    01168 KURL KCmdLineArgs::makeURL( const char *urlArg )
    01169 {
    01170    if (*urlArg == '/')
    01171    {
    01172       KURL result;
    01173       result.setPath(QFile::decodeName( urlArg));
    01174       return result; // Absolute path.
    01175    }
    01176
    01177    if ( !KURL::isRelativeURL( QString::fromLocal8Bit(urlArg) ) )
    01178      return KURL(QString::fromLocal8Bit(urlArg)); // Argument is a URL
    01179
    01180    KURL result;
    01181    result.setPath( cwd()+"/"+QFile::decodeName( urlArg ));
    01182    result.cleanPath();
    01183    return result;  // Relative path
    01184 }
    01185
    01186 void
    01187 KCmdLineArgs::addArgument(const char *argument)
    01188 {
    01189    if (!parsedArgList)
    01190       parsedArgList = new KCmdLineParsedArgs;
    01191
    01192    parsedArgList->append(argument);
    01193 }

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 12:46:21 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001