RPM Package Manager, CVS Repository
  http://rpm5.org/cvs/
  ____________________________________________________________________________

  Server: rpm5.org                         Name:   Jeff Johnson
  Root:   /v/rpm/cvs                       Email:  j...@rpm5.org
  Module: rpm                              Date:   03-Jul-2017 06:08:54
  Branch: rpm-5_4                          Handle: 2017070304085400

  Modified files:           (Branch: rpm-5_4)
    rpm/rpmio               rpmjs45.cpp

  Log:
    - rpmjs45: WIP.

  Summary:
    Revision    Changes     Path
    1.1.2.17    +659 -65    rpm/rpmio/rpmjs45.cpp
  ____________________________________________________________________________

  patch -p0 <<'@@ .'
  Index: rpm/rpmio/rpmjs45.cpp
  ============================================================================
  $ cvs diff -u -r1.1.2.16 -r1.1.2.17 rpmjs45.cpp
  --- rpm/rpmio/rpmjs45.cpp     3 Jul 2017 03:41:36 -0000       1.1.2.16
  +++ rpm/rpmio/rpmjs45.cpp     3 Jul 2017 04:08:54 -0000       1.1.2.17
  @@ -27,6 +27,7 @@
   
   #include "jswrapper.h"
   
  +#include "vm/StringBuffer.h"
   #include "vm/TypedArrayObject.h"
   
   using namespace JS;
  @@ -141,9 +142,8 @@
   
   using namespace JS;
   
  -#else        /* NOTYET */
  +#endif       /* NOTYET */
   
  -#ifdef       NOTYET
   /* --- shell/jsshell.h */
   class AutoCloseFile
   {
  @@ -162,9 +162,6 @@
           return success;
       }
   };
  -#endif
  -
  -#endif       /* NOTYET */
   
   #ifdef XP_WIN
   const char PathSeparator = '\\';
  @@ -268,9 +265,7 @@
           JS_ReportError(cx, "can't open %s: %s", pathname, strerror(errno));
           return nullptr;
       }
  -#ifdef       FIXME
       AutoCloseFile autoClose(file);
  -#endif
   
       RootedObject obj(cx);
       if (fseek(file, 0, SEEK_END) != 0) {
  @@ -282,12 +277,8 @@
           } else {
               obj = JS_NewUint8Array(cx, len);
               if (!obj) {
  -#if !defined(FIXME)
  -             if (file && fileno(file) > 2) (void) fclose(file);
  -#endif
                   return nullptr;
            }
  -#if defined(FIXME)
               js::TypedArrayObject& ta = obj->as<js::TypedArrayObject>();
               if (ta.isSharedMemory()) {
                   // Must opt in to use shared memory.  For now, don't.
  @@ -300,13 +291,9 @@
                   // race-safe primitive to copy memory into the
                   // buffer.)
                   JS_ReportError(cx, "can't read %s: shared memory buffer", 
pathname);
  -             if (file) (void) fclose(file);
                   return nullptr;
               }
               char* buf = static_cast<char*>(ta.viewDataUnshared());
  -#else        /* FIMXME */
  -         char buf[len];
  -#endif       /* FIMXME */
               size_t cc = fread(buf, 1, len, file);
               if (cc != len) {
                   JS_ReportError(cx, "can't read %s: %s", pathname,
  @@ -315,9 +302,6 @@
               }
           }
       }
  -#if !defined(FIXME)
  -    if (file && fileno(file) > 2) (void) fclose(file);
  -#endif
       return obj;
   }
   
  @@ -415,9 +399,7 @@
           JS_ReportError(cx, "can't open %s: %s", filename.ptr(), 
strerror(errno));
           return false;
       }
  -#ifdef       FIXME
       AutoCloseFile autoClose(file);
  -#endif
   
       TypedArrayObject* obj = &args[1].toObject().as<TypedArrayObject>();
   
  @@ -426,28 +408,15 @@
           //
           // See further comments in FileAsTypedArray, above.
           JS_ReportError(cx, "can't write %s: shared memory buffer", 
filename.ptr());
  -#if !defined(FIXME)
  -        if (file && fileno(file) > 2) (void) fclose(file);
  -#endif
           return false;
       }
       void* buf = obj->viewDataUnshared();
  -#ifdef       FIXME
       if (fwrite(buf, obj->bytesPerElement(), obj->length(), file) != 
obj->length() ||
           !autoClose.release())
       {
           JS_ReportError(cx, "can't write %s", filename.ptr());
           return false;
       }
  -#else
  -    size_t nw = fwrite(buf, obj->bytesPerElement(), obj->length(), file);
  -    if (file && fileno(file) > 2) (void) fclose(file);
  -    if (nw != obj->length()) 
  -    {
  -        JS_ReportError(cx, "can't write %s", filename.ptr());
  -        return false;
  -    }   
  -#endif
   
       args.rval().setUndefined();
       return true;
  @@ -1590,9 +1559,7 @@
               return;
           }
       }
  -#ifdef       FIXME
       AutoCloseFile autoClose(file);
  -#endif
   
       if (!forceTTY && !isatty(fileno(file))) {
           // It's not interactive - just execute it.
  @@ -1605,9 +1572,6 @@
           MOZ_ASSERT(kind == FileScript);
           ReadEvalPrintLoop(cx, file, gOutFile, compileOnly);
       }
  -#if !defined(FIXME)
  -    if (file && fileno(file) > 2) (void) fclose(file);
  -#endif
   }
   #endif
   
  @@ -1691,9 +1655,7 @@
                                JSSMSG_CANT_OPEN, filename.ptr(), 
strerror(errno));
           return false;
       }
  -#ifdef       FIXME
  -    AutoCloseFile autoClose(file);
  -#endif
  +    js::shell::AutoCloseFile autoClose(file);
   
       if (!sizeGiven) {
           struct stat st;
  @@ -1704,23 +1666,14 @@
           if (st.st_size < off_t(offset)) {
               JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
                                    JSMSG_ARG_INDEX_OUT_OF_RANGE, "2");
  -#if !defined(FIXME)
  -            if (file && fileno(file) > 2) (void) fclose(file);
  -#endif
               return false;
           }
           size = st.st_size - offset;
       }
   
       void* contents = JS_CreateMappedArrayBufferContents(fileno(file), 
offset, size);
  -#if !defined(FIXME)
  -    if (file && fileno(file) > 2) (void) fclose(file);
  -#endif
       if (!contents) {
           JS_ReportError(cx, "failed to allocate mapped array buffer contents 
(possibly due to bad alignment)");
  -#if !defined(FIXME)
  -        if (file && fileno(file) > 2) (void) fclose(file);
  -#endif
           return false;
       }
   
  @@ -2351,9 +2304,7 @@
           JS_ReportError(cx, "can't open %s: %s", pathname, strerror(errno));
           return nullptr;
       }
  -#ifdef       FIXME
  -    AutoCloseFile autoClose(file);
  -#endif
  +    js::shell::AutoCloseFile autoClose(file);
   
       if (fseek(file, 0, SEEK_END) != 0) {
           JS_ReportError(cx, "can't seek end of %s", pathname);
  @@ -2373,9 +2324,6 @@
                           JS::UTF8CharsToNewTwoByteCharsZ(cx, 
JS::UTF8Chars(buf, len), &len).get();
                       if (!ucbuf) {
                           JS_ReportError(cx, "Invalid UTF-8 in file '%s'", 
pathname);
  -#if !defined(FIXME)
  -                     if (file && fileno(file) > 2) (void) fclose(file);
  -#endif
                           return nullptr;
                       }
                       str = JS_NewUCStringCopyN(cx, ucbuf, len);
  @@ -2386,9 +2334,6 @@
           }
       }
   
  -#if !defined(FIXME)
  -                     if (file) fclose(file);
  -#endif
       return str;
   }
   
  @@ -5243,21 +5188,21 @@
       return true;
   }
   
  -#ifdef       NOTYET
   static bool
   SetCachingEnabled(JSContext* cx, unsigned argc, Value* vp)
   {
       CallArgs args = CallArgsFromVp(argc, vp);
  +#ifdef       FIXME
       if (GetShellRuntime(cx)->isWorker) {
           JS_ReportError(cx, "Caching is not supported in workers");
           return false;
       }
  +#endif
   
       jsCachingEnabled = ToBoolean(args.get(0));
       args.rval().setUndefined();
       return true;
   }
  -#endif
   
   static void
   PrintProfilerEvents_Callback(const char* msg)
  @@ -5980,9 +5925,7 @@
       JS_FN("getMaxArgs",                      GetMaxArgs,                     
0,0),
       JS_FN("objectEmulatingUndefined",        ObjectEmulatingUndefined,       
0,0),
       JS_FN("isCachingEnabled",                IsCachingEnabled,               
0,0),
  -#ifdef       NOTYET
       JS_FN("setCachingEnabled",               SetCachingEnabled,              
1,0),
  -#endif       /* NOTYET */
       JS_FN("cacheEntry",                      CacheEntry,                     
1,0),
   #ifdef       NOTYET
       JS_FN("printProfilerEvents",     PrintProfilerEvents,            0,0),
  @@ -7266,6 +7209,658 @@
       return glob;
   }
   
  +/*==============================================================*/
  +/* --- shell/jsoptparse.cpp */
  +
  +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  + * vim: set ts=8 sts=4 et sw=4 tw=99:
  + * This Source Code Form is subject to the terms of the Mozilla Public
  + * License, v. 2.0. If a copy of the MPL was not distributed with this
  + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  +
  +#include "shell/jsoptparse.h"
  +
  +#include <ctype.h>
  +#include <stdarg.h>
  +
  +#include "jsutil.h"
  +
  +using namespace js;
  +using namespace js::cli;
  +using namespace js::cli::detail;
  +
  +const char OptionParser::prognameMeta[] = "{progname}";
  +
  +#define OPTION_CONVERT_IMPL(__cls) \
  +    bool \
  +    Option::is##__cls##Option() const \
  +    { \
  +        return kind == OptionKind##__cls; \
  +    } \
  +    __cls##Option * \
  +    Option::as##__cls##Option() \
  +    { \
  +        MOZ_ASSERT(is##__cls##Option()); \
  +        return static_cast<__cls##Option*>(this); \
  +    } \
  +    const __cls##Option * \
  +    Option::as##__cls##Option() const \
  +    { \
  +        return const_cast<Option*>(this)->as##__cls##Option(); \
  +    }
  +
  +ValuedOption*
  +Option::asValued()
  +{
  +    MOZ_ASSERT(isValued());
  +    return static_cast<ValuedOption*>(this);
  +}
  +
  +const ValuedOption*
  +Option::asValued() const
  +{
  +    return const_cast<Option*>(this)->asValued();
  +}
  +
  +OPTION_CONVERT_IMPL(Bool)
  +OPTION_CONVERT_IMPL(String)
  +OPTION_CONVERT_IMPL(Int)
  +OPTION_CONVERT_IMPL(MultiString)
  +
  +void
  +OptionParser::setArgTerminatesOptions(const char* name, bool enabled)
  +{
  +    findArgument(name)->setTerminatesOptions(enabled);
  +}
  +
  +void
  +OptionParser::setArgCapturesRest(const char* name)
  +{
  +    MOZ_ASSERT(restArgument == -1, "only one argument may be set to capture 
the rest");
  +    restArgument = findArgumentIndex(name);
  +    MOZ_ASSERT(restArgument != -1, "unknown argument name passed to 
setArgCapturesRest");
  +}
  +
  +OptionParser::Result
  +OptionParser::error(const char* fmt, ...)
  +{
  +    va_list args;
  +    va_start(args, fmt);
  +    fprintf(stderr, "Error: ");
  +    vfprintf(stderr, fmt, args);
  +    va_end(args);
  +    fputs("\n\n", stderr);
  +    return ParseError;
  +}
  +
  +/* Quick and dirty paragraph printer. */
  +static void
  +PrintParagraph(const char* text, unsigned startColno, const unsigned 
limitColno, bool padFirstLine)
  +{
  +    unsigned colno = startColno;
  +    unsigned indent = 0;
  +    const char* it = text;
  +
  +    if (padFirstLine)
  +        printf("%*s", startColno, "");
  +
  +    /* Skip any leading spaces. */
  +    while (*it != '\0' && isspace(*it))
  +        ++it;
  +
  +    while (*it != '\0') {
  +        MOZ_ASSERT(!isspace(*it));
  +
  +        /* Delimit the current token. */
  +        const char* limit = it;
  +        while (!isspace(*limit) && *limit != '\0')
  +            ++limit;
  +
  +        /*
  +         * If the current token is longer than the available number of 
columns,
  +         * then make a line break before printing the token.
  +         */
  +        MOZ_ASSERT(limit - it > 0);
  +        size_t tokLen = limit - it;
  +        MOZ_ASSERT(tokLen);
  +        if (tokLen + colno >= limitColno) {
  +            printf("\n%*s%.*s", startColno + indent, "", int(tokLen), it);
  +            colno = startColno + tokLen;
  +        } else {
  +            printf("%.*s", int(tokLen), it);
  +            colno += tokLen;
  +        }
  +
  +        switch (*limit) {
  +          case '\0':
  +            return;
  +          case ' ':
  +            putchar(' ');
  +            colno += 1;
  +            it = limit;
  +            while (*it == ' ')
  +                ++it;
  +            break;
  +          case '\n':
  +            /* |text| wants to force a newline here. */
  +            printf("\n%*s", startColno, "");
  +            colno = startColno;
  +            it = limit + 1;
  +            /* Could also have line-leading spaces. */
  +            indent = 0;
  +            while (*it == ' ') {
  +                putchar(' ');
  +                ++colno;
  +                ++indent;
  +                ++it;
  +            }
  +            break;
  +          default:
  +            MOZ_CRASH("unhandled token splitting character in text");
  +        }
  +    }
  +}
  +
  +static const char*
  +OptionFlagsToFormatInfo(char shortflag, bool isValued, size_t* length)
  +{
  +    static const char * const fmt[4] = { "  -%c --%s ",
  +                                         "  --%s ",
  +                                         "  -%c --%s=%s ",
  +                                         "  --%s=%s " };
  +
  +    /* How mny chars w/o longflag? */
  +    size_t lengths[4] = { strlen(fmt[0]) - 3,
  +                          strlen(fmt[1]) - 3,
  +                          strlen(fmt[2]) - 5,
  +                          strlen(fmt[3]) - 5 };
  +    int index = isValued ? 2 : 0;
  +    if (!shortflag)
  +        index++;
  +
  +    *length = lengths[index];
  +    return fmt[index];
  +}
  +
  +OptionParser::Result
  +OptionParser::printHelp(const char* progname)
  +{
  +    const char* prefixEnd = strstr(usage, prognameMeta);
  +    if (prefixEnd) {
  +        printf("%.*s%s%s\n", int(prefixEnd - usage), usage, progname,
  +               prefixEnd + sizeof(prognameMeta) - 1);
  +    } else {
  +        puts(usage);
  +    }
  +
  +    if (descr) {
  +        putchar('\n');
  +        PrintParagraph(descr, 2, descrWidth, true);
  +        putchar('\n');
  +    }
  +
  +    if (version)
  +        printf("\nVersion: %s\n\n", version);
  +
  +    if (!arguments.empty()) {
  +        printf("Arguments:\n");
  +
  +        static const char fmt[] = "  %s ";
  +        size_t fmtChars = sizeof(fmt) - 2;
  +        size_t lhsLen = 0;
  +        for (Option* arg : arguments)
  +            lhsLen = Max(lhsLen, strlen(arg->longflag) + fmtChars);
  +
  +        for (Option* arg : arguments) {
  +            size_t chars = printf(fmt, arg->longflag);
  +            for (; chars < lhsLen; ++chars)
  +                putchar(' ');
  +            PrintParagraph(arg->help, lhsLen, helpWidth, false);
  +            putchar('\n');
  +        }
  +        putchar('\n');
  +    }
  +
  +    if (!options.empty()) {
  +        printf("Options:\n");
  +
  +        /* Calculate sizes for column alignment. */
  +        size_t lhsLen = 0;
  +        for (Option* opt : options) {
  +            size_t longflagLen = strlen(opt->longflag);
  +
  +            size_t fmtLen;
  +            OptionFlagsToFormatInfo(opt->shortflag, opt->isValued(), 
&fmtLen);
  +
  +            size_t len = fmtLen + longflagLen;
  +            if (opt->isValued())
  +                len += strlen(opt->asValued()->metavar);
  +            lhsLen = Max(lhsLen, len);
  +        }
  +
  +        /* Print option help text. */
  +        for (Option* opt : options) {
  +            size_t fmtLen;
  +            const char* fmt = OptionFlagsToFormatInfo(opt->shortflag, 
opt->isValued(), &fmtLen);
  +            size_t chars;
  +            if (opt->isValued()) {
  +                if (opt->shortflag)
  +                    chars = printf(fmt, opt->shortflag, opt->longflag, 
opt->asValued()->metavar);
  +                else
  +                    chars = printf(fmt, opt->longflag, 
opt->asValued()->metavar);
  +            } else {
  +                if (opt->shortflag)
  +                    chars = printf(fmt, opt->shortflag, opt->longflag);
  +                else
  +                    chars = printf(fmt, opt->longflag);
  +            }
  +            for (; chars < lhsLen; ++chars)
  +                putchar(' ');
  +            PrintParagraph(opt->help, lhsLen, helpWidth, false);
  +            putchar('\n');
  +        }
  +    }
  +
  +    return EarlyExit;
  +}
  +
  +OptionParser::Result
  +OptionParser::printVersion()
  +{
  +    MOZ_ASSERT(version);
  +    printf("%s\n", version);
  +    return EarlyExit;
  +}
  +
  +OptionParser::Result
  +OptionParser::extractValue(size_t argc, char** argv, size_t* i, char** value)
  +{
  +    MOZ_ASSERT(*i < argc);
  +    char* eq = strchr(argv[*i], '=');
  +    if (eq) {
  +        *value = eq + 1;
  +        if (*value[0] == '\0')
  +            return error("A value is required for option %.*s", eq - 
argv[*i], argv[*i]);
  +        return Okay;
  +    }
  +
  +    if (argc == *i + 1)
  +        return error("Expected a value for option %s", argv[*i]);
  +
  +    *i += 1;
  +    *value = argv[*i];
  +    return Okay;
  +}
  +
  +OptionParser::Result
  +OptionParser::handleOption(Option* opt, size_t argc, char** argv, size_t* i, 
bool* optionsAllowed)
  +{
  +    if (opt->getTerminatesOptions())
  +        *optionsAllowed = false;
  +
  +    switch (opt->kind) {
  +      case OptionKindBool:
  +      {
  +        if (opt == &helpOption)
  +            return printHelp(argv[0]);
  +        if (opt == &versionOption)
  +            return printVersion();
  +        opt->asBoolOption()->value = true;
  +        return Okay;
  +      }
  +      /*
  +       * Valued options are allowed to specify their values either via
  +       * successive arguments or a single --longflag=value argument.
  +       */
  +      case OptionKindString:
  +      {
  +        char* value = nullptr;
  +        if (Result r = extractValue(argc, argv, i, &value))
  +            return r;
  +        opt->asStringOption()->value = value;
  +        return Okay;
  +      }
  +      case OptionKindInt:
  +      {
  +        char* value = nullptr;
  +        if (Result r = extractValue(argc, argv, i, &value))
  +            return r;
  +        opt->asIntOption()->value = atoi(value);
  +        return Okay;
  +      }
  +      case OptionKindMultiString:
  +      {
  +        char* value = nullptr;
  +        if (Result r = extractValue(argc, argv, i, &value))
  +            return r;
  +        StringArg arg(value, *i);
  +        return opt->asMultiStringOption()->strings.append(arg) ? Okay : Fail;
  +      }
  +      default:
  +        MOZ_CRASH("unhandled option kind");
  +    }
  +}
  +
  +OptionParser::Result
  +OptionParser::handleArg(size_t argc, char** argv, size_t* i, bool* 
optionsAllowed)
  +{
  +    if (nextArgument >= arguments.length())
  +        return error("Too many arguments provided");
  +
  +    Option* arg = arguments[nextArgument];
  +
  +    if (arg->getTerminatesOptions())
  +        *optionsAllowed = false;
  +
  +    switch (arg->kind) {
  +      case OptionKindString:
  +        arg->asStringOption()->value = argv[*i];
  +        nextArgument += 1;
  +        return Okay;
  +      case OptionKindMultiString:
  +      {
  +        /* Don't advance the next argument -- there can only be one (final) 
variadic argument. */
  +        StringArg value(argv[*i], *i);
  +        return arg->asMultiStringOption()->strings.append(value) ? Okay : 
Fail;
  +      }
  +      default:
  +        MOZ_CRASH("unhandled argument kind");
  +    }
  +}
  +
  +OptionParser::Result
  +OptionParser::parseArgs(int inputArgc, char** argv)
  +{
  +    MOZ_ASSERT(inputArgc >= 0);
  +    size_t argc = inputArgc;
  +    /* Permit a "no more options" capability, like |--| offers in many shell 
interfaces. */
  +    bool optionsAllowed = true;
  +
  +    for (size_t i = 1; i < argc; ++i) {
  +        char* arg = argv[i];
  +        Result r;
  +        /* Note: solo dash option is actually a 'stdin' argument. */
  +        if (arg[0] == '-' && arg[1] != '\0' && optionsAllowed) {
  +            /* Option. */
  +            Option* opt;
  +            if (arg[1] == '-') {
  +                if (arg[2] == '\0') {
  +                    /* End of options */
  +                    optionsAllowed = false;
  +                    nextArgument = restArgument;
  +                    continue;
  +                } else {
  +                    /* Long option. */
  +                    opt = findOption(arg + 2);
  +                    if (!opt)
  +                        return error("Invalid long option: %s", arg);
  +                }
  +            } else {
  +                /* Short option */
  +                if (arg[2] != '\0')
  +                    return error("Short option followed by junk: %s", arg);
  +                opt = findOption(arg[1]);
  +                if (!opt)
  +                    return error("Invalid short option: %s", arg);
  +            }
  +
  +            r = handleOption(opt, argc, argv, &i, &optionsAllowed);
  +        } else {
  +            /* Argument. */
  +            r = handleArg(argc, argv, &i, &optionsAllowed);
  +        }
  +
  +        if (r != Okay)
  +            return r;
  +    }
  +    return Okay;
  +}
  +
  +void
  +OptionParser::setHelpOption(char shortflag, const char* longflag, const 
char* help)
  +{
  +    helpOption.setFlagInfo(shortflag, longflag, help);
  +}
  +
  +bool
  +OptionParser::getHelpOption() const
  +{
  +    return helpOption.value;
  +}
  +
  +bool
  +OptionParser::getBoolOption(char shortflag) const
  +{
  +    return findOption(shortflag)->asBoolOption()->value;
  +}
  +
  +int
  +OptionParser::getIntOption(char shortflag) const
  +{
  +    return findOption(shortflag)->asIntOption()->value;
  +}
  +
  +const char*
  +OptionParser::getStringOption(char shortflag) const
  +{
  +    return findOption(shortflag)->asStringOption()->value;
  +}
  +
  +MultiStringRange
  +OptionParser::getMultiStringOption(char shortflag) const
  +{
  +    const MultiStringOption* mso = 
findOption(shortflag)->asMultiStringOption();
  +    return MultiStringRange(mso->strings.begin(), mso->strings.end());
  +}
  +
  +bool
  +OptionParser::getBoolOption(const char* longflag) const
  +{
  +    return findOption(longflag)->asBoolOption()->value;
  +}
  +
  +int
  +OptionParser::getIntOption(const char* longflag) const
  +{
  +    return findOption(longflag)->asIntOption()->value;
  +}
  +
  +const char*
  +OptionParser::getStringOption(const char* longflag) const
  +{
  +    return findOption(longflag)->asStringOption()->value;
  +}
  +
  +MultiStringRange
  +OptionParser::getMultiStringOption(const char* longflag) const
  +{
  +    const MultiStringOption* mso = 
findOption(longflag)->asMultiStringOption();
  +    return MultiStringRange(mso->strings.begin(), mso->strings.end());
  +}
  +
  +OptionParser::~OptionParser()
  +{
  +    for (Option* opt : options)
  +        js_delete<Option>(opt);
  +    for (Option* arg : arguments)
  +        js_delete<Option>(arg);
  +}
  +
  +Option*
  +OptionParser::findOption(char shortflag)
  +{
  +    for (Option* opt : options) {
  +        if (opt->shortflag == shortflag)
  +            return opt;
  +    }
  +
  +    if (versionOption.shortflag == shortflag)
  +        return &versionOption;
  +
  +    return helpOption.shortflag == shortflag ? &helpOption : nullptr;
  +}
  +
  +const Option*
  +OptionParser::findOption(char shortflag) const
  +{
  +    return const_cast<OptionParser*>(this)->findOption(shortflag);
  +}
  +
  +Option*
  +OptionParser::findOption(const char* longflag)
  +{
  +    for (Option* opt : options) {
  +        const char* target = opt->longflag;
  +        if (opt->isValued()) {
  +            size_t targetLen = strlen(target);
  +            /* Permit a trailing equals sign on the longflag argument. */
  +            for (size_t i = 0; i < targetLen; ++i) {
  +                if (longflag[i] == '\0' || longflag[i] != target[i])
  +                    goto no_match;
  +            }
  +            if (longflag[targetLen] == '\0' || longflag[targetLen] == '=')
  +                return opt;
  +        } else {
  +            if (strcmp(target, longflag) == 0)
  +                return opt;
  +        }
  +  no_match:;
  +    }
  +
  +    if (strcmp(versionOption.longflag, longflag) == 0)
  +        return &versionOption;
  +
  +    return strcmp(helpOption.longflag, longflag) ? nullptr : &helpOption;
  +}
  +
  +const Option*
  +OptionParser::findOption(const char* longflag) const
  +{
  +    return const_cast<OptionParser*>(this)->findOption(longflag);
  +}
  +
  +/* Argument accessors */
  +
  +int
  +OptionParser::findArgumentIndex(const char* name) const
  +{
  +    for (Option * const* it = arguments.begin(); it != arguments.end(); 
++it) {
  +        const char* target = (*it)->longflag;
  +        if (strcmp(target, name) == 0)
  +            return it - arguments.begin();
  +    }
  +    return -1;
  +}
  +
  +Option*
  +OptionParser::findArgument(const char* name)
  +{
  +    int index = findArgumentIndex(name);
  +    return (index == -1) ? nullptr : arguments[index];
  +}
  +
  +const Option*
  +OptionParser::findArgument(const char* name) const
  +{
  +    int index = findArgumentIndex(name);
  +    return (index == -1) ? nullptr : arguments[index];
  +}
  +
  +const char*
  +OptionParser::getStringArg(const char* name) const
  +{
  +    return findArgument(name)->asStringOption()->value;
  +}
  +
  +MultiStringRange
  +OptionParser::getMultiStringArg(const char* name) const
  +{
  +    const MultiStringOption* mso = findArgument(name)->asMultiStringOption();
  +    return MultiStringRange(mso->strings.begin(), mso->strings.end());
  +}
  +
  +/* Option builders */
  +
  +bool
  +OptionParser::addIntOption(char shortflag, const char* longflag, const char* 
metavar,
  +                           const char* help, int defaultValue)
  +{
  +    if (!options.reserve(options.length() + 1))
  +        return false;
  +    IntOption* io = js_new<IntOption>(shortflag, longflag, help, metavar, 
defaultValue);
  +    if (!io)
  +        return false;
  +    options.infallibleAppend(io);
  +    return true;
  +}
  +
  +bool
  +OptionParser::addBoolOption(char shortflag, const char* longflag, const 
char* help)
  +{
  +    if (!options.reserve(options.length() + 1))
  +        return false;
  +    BoolOption* bo = js_new<BoolOption>(shortflag, longflag, help);
  +    if (!bo)
  +        return false;
  +    options.infallibleAppend(bo);
  +    return true;
  +}
  +
  +bool
  +OptionParser::addStringOption(char shortflag, const char* longflag, const 
char* metavar,
  +                              const char* help)
  +{
  +    if (!options.reserve(options.length() + 1))
  +        return false;
  +    StringOption* so = js_new<StringOption>(shortflag, longflag, help, 
metavar);
  +    if (!so)
  +        return false;
  +    options.infallibleAppend(so);
  +    return true;
  +}
  +
  +bool
  +OptionParser::addMultiStringOption(char shortflag, const char* longflag, 
const char* metavar,
  +                                   const char* help)
  +{
  +    if (!options.reserve(options.length() + 1))
  +        return false;
  +    MultiStringOption* mso = js_new<MultiStringOption>(shortflag, longflag, 
help, metavar);
  +    if (!mso)
  +        return false;
  +    options.infallibleAppend(mso);
  +    return true;
  +}
  +
  +/* Argument builders */
  +
  +bool
  +OptionParser::addOptionalStringArg(const char* name, const char* help)
  +{
  +    if (!arguments.reserve(arguments.length() + 1))
  +        return false;
  +    StringOption* so = js_new<StringOption>(1, name, help, (const char*) 
nullptr);
  +    if (!so)
  +        return false;
  +    arguments.infallibleAppend(so);
  +    return true;
  +}
  +
  +bool
  +OptionParser::addOptionalMultiStringArg(const char* name, const char* help)
  +{
  +    MOZ_ASSERT_IF(!arguments.empty(), !arguments.back()->isVariadic());
  +    if (!arguments.reserve(arguments.length() + 1))
  +        return false;
  +    MultiStringOption* mso = js_new<MultiStringOption>(1, name, help, (const 
char*) nullptr);
  +    if (!mso)
  +        return false;
  +    arguments.infallibleAppend(mso);
  +    return true;
  +}
  +
  +/*==============================================================*/
  +
   #ifdef       NOTYET
   static bool
   BindScriptArgs(JSContext* cx, OptionParser* op)
  @@ -7394,7 +7989,6 @@
   }
   #endif
   
  -#ifdef       NOTYET
   static bool
   SetRuntimeOptions(JSRuntime* rt, const OptionParser& op)
   {
  @@ -7648,7 +8242,6 @@
   
       return true;
   }
  -#endif
   
   static void
   SetWorkerRuntimeOptions(JSRuntime* rt)
  @@ -7753,6 +8346,7 @@
       }
   #endif
   }
  +
   /*==============================================================*/
   static void mozFini(rpmjss jss)
   {
  @@ .
______________________________________________________________________
RPM Package Manager                                    http://rpm5.org
CVS Sources Repository                                rpm-cvs@rpm5.org

Reply via email to