/// <summary>
        /// Initializes the program options, proccesses the command line arguments and sets option values.
        /// </summary>
        /// <param name="args">Input from command line.</param>
        /// OptionInvalidException
        /// OptionsClashException
        /// OptionParameterDisalowedException
        /// RequiredParameterMissingException
        public void Initialize(string[] args)
        {
            optionList = new List<ProgramOption>();

            var fieldInfos = this.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
            foreach (var fieldInfo in fieldInfos) {
                OptionBase optionAttribute = (OptionBase)Attribute.GetCustomAttribute(fieldInfo, typeof(OptionBase));
                if (optionAttribute == null) {
                    continue;
                }
                ShortNameAttribute shortNameAttribute = (ShortNameAttribute)Attribute.GetCustomAttribute(fieldInfo, typeof(ShortNameAttribute));
                LongNameAttribute longNameAttribute = (LongNameAttribute)Attribute.GetCustomAttribute(fieldInfo, typeof(LongNameAttribute));
                ProgramOption option = new ProgramOption(fieldInfo, (OptionBase)optionAttribute, shortNameAttribute, longNameAttribute);
                optionAttribute.CheckDefinition(fieldInfo, option.Name);
                optionList.Add(option);
            }

            ArgumentParser argParser = new ArgumentParser(this);
            arguments.AddRange(argParser.ParseCommandLine(optionList, args));
            CheckRequiredOptions();
        }
        private bool ParseLongOption(string arg)
        {
            ProgramOption option = null;
            switch (expectedArgType) {
                case ArgumentType.ARGUMENT_PARAMETER_OPTIONAL:
                    prevOption.SetValueToDefault(programOptions);
                    goto case ArgumentType.ANY;

                case ArgumentType.ANY:
                    if (arg == "--") {
                        /* finish parsing options and parameters */
                        return false;
                    }
                    int eqPosition = arg.LastIndexOf('=');
                    try {
                        if (eqPosition == -1) {
                            option = optionsDictionary[arg.Substring(2)];
                        }
                        else {
                            option = optionsDictionary[arg.Substring(2, eqPosition - 2)];
                        }
                    }
                    catch (KeyNotFoundException) {
                        throw new OptionInvalidException(arg.Substring(2));
                    }

                    /* prepare for parameters? */
                    if (option.GetType() == typeof(OptionAttribute)) {
                        if (eqPosition != -1) {
                            throw new OptionParameterDisallowedException(option.Name, arg.Substring(eqPosition + 1));
                        }
                        option.SetValue("true", programOptions);
                    }
                    else if (option.GetType() == typeof(OptionWithOptionableParameterAttribute)) {
                        if (eqPosition != -1) {
                            option.SetValueToDefault(programOptions);
                        }
                        else {
                            option.SetValue(arg.Substring(eqPosition + 1), programOptions);
                        }
                    }
                    else if (option.GetType() == typeof(OptionWithParameterAttribute)) {
                        if (eqPosition != -1) {
                            throw new RequiredParameterMissingException(option.Name);
                        }
                        else {
                            option.SetValue(arg.Substring(eqPosition + 1), programOptions);
                        }
                    }
                    break;

                /* required option parameter, but short option found => exception */
                case ArgumentType.ARGUMENT_PARAMETER:
                    throw new OptionsClashException(prevOption.Name, arg, "Option found, required parameter expected.");

                default:
                    /* should not happen as expectedArgType is set only to above proccessed cases */
                    throw new NotSupportedException("Unexpected expectedArgType :-)");
            }
            expectedArgType = ArgumentType.ANY;
            prevOption = option;
            return true;
        }
        private void ParseShortOption(string arg)
        {
            ProgramOption option = null;
            switch (expectedArgType) {
                case ArgumentType.ARGUMENT_PARAMETER_OPTIONAL:
                    prevOption.SetValueToDefault(programOptions);
                    goto case ArgumentType.ANY;

                case ArgumentType.ANY:
                    try {
                        option = optionsDictionary[arg.Substring(1)];
                    }
                    catch (KeyNotFoundException) {
                        throw new OptionInvalidException(arg.Substring(1));
                    }

                    /* prepare for parameters? */
                    if (option.GetOptionAttributeType() == typeof(OptionAttribute)) {
                        option.SetValue("true", programOptions);
                        expectedArgType = ArgumentType.ANY;
                    }
                    else if (option.GetOptionAttributeType() == typeof(OptionWithOptionableParameterAttribute)) {
                        expectedArgType = ArgumentType.ARGUMENT_PARAMETER_OPTIONAL;
                    }
                    else if (option.GetOptionAttributeType() == typeof(OptionWithParameterAttribute)) {
                        expectedArgType = ArgumentType.ARGUMENT_PARAMETER;
                    }
                    break;

                /* required option parameter, but short option found => exception */
                case ArgumentType.ARGUMENT_PARAMETER:
                    throw new OptionsClashException(prevOption.Name, arg, "Option found, required parameter expected.");

                default:
                    /* should not happen as expectedArgType is set only to above proccessed cases */
                    throw new NotSupportedException("Unexpected expectedArgType :-)");
            }
            prevOption = option;
            return;
        }
        private void AddNamesToDictionary(ProgramOption programOption)
        {
            foreach (string name in programOption.ShortNames) {
                optionsDictionary.Add(name, programOption);
                Log("Adding option " + name + " to dictionary.");
            }

            foreach (string name in programOption.LongNames) {
                optionsDictionary.Add(name, programOption);
                Log("Adding option " + name + " to dictionary.");
            }
        }