private String DescribeDualOption(Int32 id) { CLOptionDescriptor descriptor = GetDescriptorFor(id); if (null == descriptor) { return("<parameter>"); } else { StringBuilder sb = new StringBuilder(); Boolean hasCharOption = false; if (Char.IsLetter((Char)id)) { sb.Append('-'); sb.Append((Char)id); hasCharOption = true; } String longOption = descriptor.GetName(); if (null != longOption) { if (hasCharOption) { sb.Append('/'); } sb.Append("--"); sb.Append(longOption); } return(sb.ToString()); } }
/** * Constructor taking an descriptor * * @param descriptor * the descriptor iff null, will default to a "text argument" * descriptor. */ public CLOption(CLOptionDescriptor descriptor) { if (descriptor != null) { m_descriptor = descriptor; } }
/** * Constructor taking an descriptor * * @param descriptor * the descriptor iff null, will default to a "text argument" * descriptor. */ public CLOption(CLOptionDescriptor descriptor) { if (descriptor != null) { m_descriptor = descriptor; } }
private String GetOptionDescription(CLOptionDescriptor descriptor) { if (m_isLong) { return("--" + descriptor.GetName()); } else { return("-" + (char)descriptor.GetId()); } }
private void ParseShortOption() { m_ch = GetChar(); CLOptionDescriptor descriptor = GetDescriptorFor(m_ch); m_isLong = false; ParseOption(descriptor, "-" + m_ch); if (STATE_NORMAL == m_state) { m_state = STATE_OPTION_MODE; } }
/** * Parse Options from Normal mode. */ private void ParseNormal() { if ('-' != m_ch) { // Parse the arguments that are not options String argument = NextToken(NULL_SEPARATORS).GetValue(); AddOption(new CLOption(argument)); m_state = STATE_NORMAL; } else { GetChar(); // strip the - if (0 == PeekAtChar()) { throw new Exception("Malformed option -"); } else { m_ch = PeekAtChar(); // if it is a short option then parse it else ... if ('-' != m_ch) { ParseShortOption(); } else { GetChar(); // strip the - // -- sequence .. it can either mean a change of state // to STATE_NO_OPTIONS or else a long option if (0 == PeekAtChar()) { GetChar(); m_state = STATE_NO_OPTIONS; } else { // its a long option String optionName = NextToken(ARG_SEPARATORS).GetValue(); CLOptionDescriptor descriptor = GetDescriptorFor(optionName); m_isLong = true; ParseOption(descriptor, "--" + optionName); } } } } }
/** * Constructor. * * @param name * the name/long option * @param flags * the flags * @param id * the id/character option * @param description * description of option usage * @param incompatible * descriptors for incompatible options */ public CLOptionDescriptor(String name, int flags, int id, String description, CLOptionDescriptor[] incompatible) { checkFlags(flags); m_id = id; m_name = name; m_flags = flags; m_description = description; m_incompatible = new int[incompatible.Length]; for (int i = 0; i < incompatible.Length; i++) { m_incompatible[i] = incompatible[i].GetId(); } }
private void ParseOption(CLOptionDescriptor descriptor, String optionString) { if (null == descriptor) { throw new Exception("Unknown option " + optionString); } m_state = GetStateFor(descriptor); m_option = new CLOption(descriptor); if (STATE_NORMAL == m_state) { AddOption(m_option); } }
/** * Build the m_optionIndex lookup map for the parsed options. */ private void BuildOptionIndex() { m_optionIndex = new Dictionary <Object, CLOption>(m_options.Count * 2); foreach (CLOption option in m_options) { CLOptionDescriptor optionDescriptor = GetDescriptorFor(option.GetDescriptor().GetId()); m_optionIndex.Add(option.GetDescriptor().GetId(), option); if (null != optionDescriptor && null != optionDescriptor.GetName()) { m_optionIndex.Add(optionDescriptor.GetName(), option); } } }
/** * Create a parser that can deal with options and parses certain args. * * @param args * the args, typically that passed to the * <code>public static void main(String[] args)</code> method. * @param optionDescriptors * the option descriptors * @param control * the parser control used determine behaviour of parser */ public CLArgsParser(String[] args, CLOptionDescriptor[] optionDescriptors, ParserControl control) { m_optionDescriptors = optionDescriptors; m_control = control; m_options = new List<CLOption>(); m_args = args; try { Parse(); CheckIncompatibilities(m_options); BuildOptionIndex(); } catch (Exception pe) { m_errorMessage = pe.Message; } // System.out.println( "Built : " + m_options ); // System.out.println( "From : " + Arrays.asList( args ) ); }
/** * Require state to be placed in for option. * * @param descriptor * the Option Descriptor * @return the state */ private Int32 GetStateFor(CLOptionDescriptor descriptor) { int flags = descriptor.GetFlags(); if ((flags & CLOptionDescriptor.ARGUMENTS_REQUIRED_2) == CLOptionDescriptor.ARGUMENTS_REQUIRED_2) { return(STATE_REQUIRE_2ARGS); } else if ((flags & CLOptionDescriptor.ARGUMENT_REQUIRED) == CLOptionDescriptor.ARGUMENT_REQUIRED) { return(STATE_REQUIRE_ARG); } else if ((flags & CLOptionDescriptor.ARGUMENT_OPTIONAL) == CLOptionDescriptor.ARGUMENT_OPTIONAL) { return(STATE_OPTIONAL_ARG); } else { return(STATE_NORMAL); } }
/** * Check for duplicates of an option. It is an error to have duplicates * unless appropriate flags is set in descriptor. * * @param arguments * the arguments */ private void CheckIncompatibilities(List <CLOption> arguments) { int size = arguments.Count; for (int i = 0; i < size; i++) { CLOption option = arguments[i]; int id = option.GetDescriptor().GetId(); CLOptionDescriptor descriptor = GetDescriptorFor(id); // this occurs when id == 0 and user has not supplied a descriptor // for arguments if (null == descriptor) { continue; } int[] incompatible = descriptor.GetIncompatible(); CheckIncompatible(arguments, incompatible, i); } }
private void ParseOption(CLOptionDescriptor descriptor, String optionString) { if (null == descriptor) { throw new Exception("Unknown option " + optionString); } m_state = GetStateFor(descriptor); m_option = new CLOption(descriptor); if (STATE_NORMAL == m_state) { AddOption(m_option); } }
/** * Require state to be placed in for option. * * @param descriptor * the Option Descriptor * @return the state */ private Int32 GetStateFor(CLOptionDescriptor descriptor) { int flags = descriptor.GetFlags(); if ((flags & CLOptionDescriptor.ARGUMENTS_REQUIRED_2) == CLOptionDescriptor.ARGUMENTS_REQUIRED_2) { return STATE_REQUIRE_2ARGS; } else if ((flags & CLOptionDescriptor.ARGUMENT_REQUIRED) == CLOptionDescriptor.ARGUMENT_REQUIRED) { return STATE_REQUIRE_ARG; } else if ((flags & CLOptionDescriptor.ARGUMENT_OPTIONAL) == CLOptionDescriptor.ARGUMENT_OPTIONAL) { return STATE_OPTIONAL_ARG; } else { return STATE_NORMAL; } }
private String GetOptionDescription(CLOptionDescriptor descriptor) { if (m_isLong) { return "--" + descriptor.GetName(); } else { return "-" + (char) descriptor.GetId(); } }
/** * Create a parser that deals with options and parses certain args. * * @param args * the args * @param optionDescriptors * the option descriptors */ public CLArgsParser(String[] args, CLOptionDescriptor[] optionDescriptors) : this(args, optionDescriptors, null) { }
/** * Actually parse arguments */ private void Parse() { if (0 == m_args.Length) { return; } m_stringLength = m_args[m_argIndex].Length; while (true) { m_ch = PeekAtChar(); if (m_argIndex >= m_args.Length) { break; } if (null != m_control && m_control.isFinished(m_lastOptionId)) { // this may need mangling due to peeks m_unparsedArgs = SubArray(m_args, m_argIndex, m_stringIndex); return; } if (STATE_OPTION_MODE == m_state) { // if get to an arg barrier then return to normal mode // else continue accumulating options if (0 == m_ch) { GetChar(); // strip the null m_state = STATE_NORMAL; } else { ParseShortOption(); } } else if (STATE_NORMAL == m_state) { ParseNormal(); } else if (STATE_NO_OPTIONS == m_state) { // should never get to here when stringIndex != 0 AddOption(new CLOption(m_args[m_argIndex++])); } else { ParseArguments(); } } // Reached end of input arguments - perform final processing if (m_option != null) { if (STATE_OPTIONAL_ARG == m_state) { m_options.Add(m_option); } else if (STATE_REQUIRE_ARG == m_state) { CLOptionDescriptor descriptor = GetDescriptorFor(m_option.GetDescriptor().GetId()); String message = "Missing argument to option " + GetOptionDescription(descriptor); throw new Exception(message); } else if (STATE_REQUIRE_2ARGS == m_state) { if (1 == m_option.GetArgumentCount()) { m_option.AddArgument(""); m_options.Add(m_option); } else { CLOptionDescriptor descriptor = GetDescriptorFor(m_option.GetDescriptor().GetId()); String message = "Missing argument to option " + GetOptionDescription(descriptor); throw new Exception(message); } } else { throw new Exception("IllegalState " + m_state + ": " + m_option); } } }
private void ParseArguments() { if (STATE_REQUIRE_ARG == m_state) { if ('=' == m_ch || 0 == m_ch) { GetChar(); } Token token = NextToken(NULL_SEPARATORS); m_option.AddArgument(token.GetValue()); AddOption(m_option); m_state = STATE_NORMAL; } else if (STATE_OPTIONAL_ARG == m_state) { if ('-' == m_ch || 0 == m_ch) { GetChar(); // consume stray character AddOption(m_option); m_state = STATE_NORMAL; return; } if (m_isLong && '=' != m_tokesep) { // Long optional arg must have = as separator AddOption(m_option); m_state = STATE_NORMAL; return; } if ('=' == m_ch) { GetChar(); } Token token = NextToken(NULL_SEPARATORS); m_option.AddArgument(token.GetValue()); AddOption(m_option); m_state = STATE_NORMAL; } else if (STATE_REQUIRE_2ARGS == m_state) { if (0 == m_option.GetArgumentCount()) { /* * Fix bug: -D arg1=arg2 was causing parse error; however * --define arg1=arg2 is OK This seems to be because the parser * skips the terminator for the long options, but was not doing * so for the short options. */ if (!m_isLong) { if (0 == PeekAtChar()) { GetChar(); } } Token token = NextToken(ARG_SEPARATORS); if (TOKEN_SEPARATOR == token.GetType()) { CLOptionDescriptor descriptor = GetDescriptorFor(m_option.GetDescriptor().GetId()); String message = "Unable to parse first argument for option " + GetOptionDescription(descriptor); throw new Exception(message); } else { m_option.AddArgument(token.GetValue()); } // Are we about to start a new option? if (0 == m_ch && '-' == PeekAtChar()) { // Yes, so the second argument is missing m_option.AddArgument(""); m_options.Add(m_option); m_state = STATE_NORMAL; } } else // 2nd argument { StringBuilder sb = new StringBuilder(); m_ch = GetChar(); while (!isSeparator(m_ch, NULL_SEPARATORS)) { sb.Append(m_ch); m_ch = GetChar(); } String argument = sb.ToString(); // System.out.println( "Arguement:" + argument ); m_option.AddArgument(argument); AddOption(m_option); m_option = null; m_state = STATE_NORMAL; } } }
/** * Format options into StringBuilder and return. This is typically used to * print "Usage" text in response to a "--help" or invalid option. * * @param options * the option descriptors * @return the formatted description/help for options */ public static StringBuilder DescribeOptions(CLOptionDescriptor[] options) { String lSep = "\n\t"; StringBuilder sb = new StringBuilder(); for (int i = 0; i < options.Length; i++) { char ch = (char) options[i].GetId(); String name = options[i].GetName(); String description = options[i].GetDescription(); int flags = options[i].GetFlags(); Boolean argumentOptional = ((flags & CLOptionDescriptor.ARGUMENT_OPTIONAL) == CLOptionDescriptor.ARGUMENT_OPTIONAL); Boolean argumentRequired = ((flags & CLOptionDescriptor.ARGUMENT_REQUIRED) == CLOptionDescriptor.ARGUMENT_REQUIRED); Boolean twoArgumentsRequired = ((flags & CLOptionDescriptor.ARGUMENTS_REQUIRED_2) == CLOptionDescriptor.ARGUMENTS_REQUIRED_2); Boolean needComma = false; if (twoArgumentsRequired) { argumentRequired = true; } sb.Append('\t'); if (Char.IsLetter(ch)) { sb.Append("-"); sb.Append(ch); needComma = true; } if (null != name) { if (needComma) { sb.Append(", "); } sb.Append("--"); sb.Append(name); } if (argumentOptional) { sb.Append(" [<argument>]"); } if (argumentRequired) { sb.Append(" <argument>"); } if (twoArgumentsRequired) { sb.Append("=<value>"); } sb.Append(lSep); if (null != description) { while (description.Length > MAX_DESCRIPTION_COLUMN_LENGTH) { String descriptionPart = description.Substring(0, MAX_DESCRIPTION_COLUMN_LENGTH); description = description.Substring(MAX_DESCRIPTION_COLUMN_LENGTH); sb.Append("\t\t"); sb.Append(descriptionPart); sb.Append(lSep); } sb.Append("\t\t"); sb.Append(description); sb.Append(lSep); } } return sb; }