Example #1
0
        /// <summary>
        /// Parses the valid options list.
        /// </summary>
        /// <param name="optstring">the options list</param>
        /// <returns>an array of valid option structures</returns>
        private Option[] OptStr2LongOpts(string optstring)
        {
            List<Option> optlst = new List<Option>();

            for (int i = 0; i < optstring.Length; i++) {
                Option curopt = new Option();
                curopt.Name = new String(new char[] { optstring[i] });
                curopt.Val = optstring[i];

                /* one colon means the previous option has an argument, two colons
                 * mean the option has an _optional_ argument */
                if (i + 1 < optstring.Length && optstring[i + 1] == ':') {
                    if (i + 2 < optstring.Length && optstring[i + 2] == ':') {
                        curopt.HasArg = ArgFlags.Optional;
                        i += 2;
                    } else {
                        curopt.HasArg = ArgFlags.Required;
                        i++;
                    }
                }

                optlst.Add(curopt);
            }

            return optlst.ToArray();
        }
Example #2
0
        /// <summary>
        /// Parses the argv array for long command-line options. The first element of
        /// argv must be the binary name!
        /// </summary>
        /// <param name="argv">reference to argv passed into main()</param>
        /// <param name="optstring">valid options list</param>
        /// <param name="longopts">an array of valid long options</param>
        /// <param name="longindex">returns the current long option index</param>
        /// <returns>the option character, -1 for no more options, or ? for error</returns>
        /// <remarks>For long options only, optstring should be an empty string and not null!</remarks>
        public int GetOptLong(ref string[] argv, string optstring, Option[] longopts, ref int longindex)
        {
            string imgname = Path.GetFileName(argv[0]);

            if (!Regex.IsMatch(optstring, "^([+]|-|:)?([A-Za-z0-9]:?:?)*$"))
                throw new Exception("Bad option string!");

            int res;
            Option[] validopts = this.OptStr2LongOpts(optstring);

            if (_optind < 1)
                _optind = 1;

            while (_optind < argv.Length) {
                string curitm = argv[_optind];
                bool hasarg = false;

                if (curitm == "--") {   /* -- always ends option scanning */

                    /* if we're not at the end of the array, then optind points to
                     * the first non-option in the array */
                    if (_optind + 1 < argv.Length)
                        _optind++;

                    /* end of option scanning */
                    return -1;
                } else if (this.IsOption(curitm)) {
                    char curchar;
                    Option curopt;
                    bool islong = false;
                    int nextoffset = 1;

                    if (this.IsOptionLong(curitm)) {    /* long options */

                        /* strip off the leading dashes and argument if there is one */
                        string optname = curitm.IndexOf('=') > 0 ?
                            curitm.Substring(2, curitm.IndexOf('=') - 2) :
                            curitm.Substring(2);

                        curopt = longopts.Where(o => o.Name == optname).SingleOrDefault();
                        curchar = curopt.Name != null ? curopt.Val : '\0';
                        islong = true;

                        longindex = curopt.Name != null ?
                            longopts.Select((e, i) => new { Elem = e, Index = i })
                                .Where(i => ((Option)i.Elem).Equals(curopt)).First().Index :
                            0;
                    } else {                            /* short options */
                        curchar = curitm.Substring(_nextchar + 1, 1)[0];
                        curopt = validopts.Where(o => o.Name[0] == curchar).SingleOrDefault();
                    }

                    _optopt = '\0';
                    _optarg = null;

                    if (curopt.Name != null) {
                        res = curopt.Val;
                        hasarg = curopt.HasArg != ArgFlags.None;

                        /* short option args can be the remainder of the option element or the next argv element
                         * ex: -ofoo    where -o is the option and 'foo' is the argument
                         * ex: -o foo
                         *
                         * long option args can be part of the option element if separated by equals, or the next argv element
                         * ex: --output=foo     where --output is option and 'foo' is the argument
                         * ex: --output foo
                         */
                        if (!islong && hasarg && curitm.Length > 2 && _nextchar == 0) {
                            _optarg = curitm.Substring(2);
                        } else if (!islong && hasarg && curitm.Length == 2 && _optind + 1 < argv.Length && !this.IsOption(argv[_optind + 1])) {
                            _optarg = argv[_optind + 1];
                            nextoffset = 2;
                        } else if (islong && hasarg && curitm.Contains('=')) {
                            _optarg = curitm.Substring(curitm.IndexOf('=') + 1);
                        } else if (islong && hasarg && _optind + 1 < argv.Length && !this.IsOption(argv[_optind + 1])) {
                            _optarg = argv[_optind + 1];
                            nextoffset = 2;
                        } else if (hasarg) {
                            if (curopt.HasArg == ArgFlags.Required) {
                                if (_opterr)
                                    Console.Error.WriteLine("{0}: option '{1}' requires an argument", imgname, curopt.Name);

                                res = optstring.StartsWith(":") ? ':' : '?';
                                _optopt = curopt.Val;
                            } else {
                                /* the argument is optional, so no need to complain */
                                hasarg = false;
                            }
                        }
                    } else {
                        if (_opterr) {
                            string optname = (curchar == '\0') ?
                                curitm :
                                new string(new char[] { curchar });
                            Console.Error.WriteLine("{0}: unrecognised option '{1}'", imgname, optname);
                        }

                        res = '?';
                        _optopt = curchar;
                    }

                    /* support options provided in the same argv element
                     * ex: -a -b -c becomes -abc */
                    if (!islong && !hasarg && _nextchar < curitm.Length - 2)
                        _nextchar++;
                    else {
                        if (hasarg)     /* don't permute arguments */
                            _optind += nextoffset;
                        else
                            _optind++;
                        _nextchar = 0;
                    }

                    return res;
                } else {  /* not an option */

                    /* strict POSIX mode ends option scanning at the first non-option. + also enables
                     * this mode. - forces non-options to return as character code 1. */
                    if (optstring.StartsWith("+") || this.POSIXLY_CORRECT) {
                        return -1;
                    } else if (optstring.StartsWith("-")) {
                        _optind++;
                        return (char)1;
                    }

                    /* deterimine if there are any options left to read... */
                    bool more = false;
                    for (int i = _optind; i < argv.Length; i++) {
                        if (this.IsOption(argv[i])) {
                            more = true;
                            break;
                        }
                    }

                    /* if not, we're done */
                    if (!more) break;

                    /* permute the argv array throwing the non-option on the end */
                    Array.Copy(argv, _optind + 1, argv, _optind, argv.Length - _optind - 1);
                    argv[argv.Length - 1] = curitm;
                }
            }

            /* no more options to read */
            return -1;
        }