aboutsummaryrefslogtreecommitdiffstats
path: root/src/ArgParser.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/ArgParser.java')
-rw-r--r--src/ArgParser.java1082
1 files changed, 0 insertions, 1082 deletions
diff --git a/src/ArgParser.java b/src/ArgParser.java
deleted file mode 100644
index 6611b04..0000000
--- a/src/ArgParser.java
+++ /dev/null
@@ -1,1082 +0,0 @@
-/**
- * argparser – command line argument parser library
- *
- * Copyright © 2013 Mattias Andrée (maandree@member.fsf.org)
- *
- * This library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-import java.util.*;
-import java.io.*;
-
-
-/**
- * Simple argument parser
- *
- * @author Mattias Andrée, <a href="mailto:maandree@member.fsf.org">maandree@member.fsf.org</a>
- */
-public class ArgParser
-{
- /**
- * <p>Constructor</p>
- * <p>
- * The short description is printed on same line as the program name
- * </p>
- *
- * @param description Short, single-line, description of the program
- * @param usage Formated, multi-line, usage text, may be {@code null}
- */
- public ArgParser(final String description, final String usage)
- { this(description, usage, null, null, false);
- }
-
- /**
- * <p>Constructor</p>
- * <p>
- * The short description is printed on same line as the program name
- * </p>
- *
- * @param description Short, single-line, description of the program
- * @param usage Formated, multi-line, usage text, may be {@code null}
- * @param useStderr Whether to use stderr instead of stdout
- */
- public ArgParser(final String description, final String usage, final boolean useStderr)
- { this(description, usage, null, null, useStderr);
- }
-
- /**
- * <p>Constructor</p>
- * <p>
- * The short description is printed on same line as the program name
- * </p>
- *
- * @param description Short, single-line, description of the program
- * @param usage Formated, multi-line, usage text, may be {@code null}
- * @param longDescription Long, multi-line, description of the program, may be {@code null}
- */
- public ArgParser(final String description, final String usage, final String longDescription)
- { this(description, usage, longDescription, null, false);
- }
-
- /**
- * <p>Constructor</p>
- * <p>
- * The short description is printed on same line as the program name
- * </p>
- *
- * @param description Short, single-line, description of the program
- * @param usage Formated, multi-line, usage text, may be {@code null}
- * @param longDescription Long, multi-line, description of the program, may be {@code null}
- * @param useStderr Whether to use stderr instead of stdout
- */
- public ArgParser(final String description, final String usage, final String longDescription, final boolean useStderr)
- { this(description, usage, longDescription, null, useStderr);
- }
-
- /**
- * <p>Constructor</p>
- * <p>
- * The short description is printed on same line as the program name
- * </p>
- *
- * @param description Short, single-line, description of the program
- * @param usage Formated, multi-line, usage text, may be {@code null}
- * @param longDescription Long, multi-line, description of the program, may be {@code null}
- * @param program The name of the program, {@code null} for automatic
- */
- public ArgParser(final String description, final String usage, final String longDescription, final String program)
- { this(description, usage, longDescription, program, false);
- }
-
- /**
- * <p>Constructor</p>
- * <p>
- * The short description is printed on same line as the program name
- * </p>
- *
- * @param description Short, single-line, description of the program
- * @param usage Formated, multi-line, usage text, may be {@code null}
- * @param longDescription Long, multi-line, description of the program, may be {@code null}
- * @param program The name of the program, {@code null} for automatic
- * @param useStderr Whether to use stderr instead of stdout
- */
- public ArgParser(final String description, final String usage, final String longDescription, final String program, final boolean useStderr)
- {
- this.linuxvt = System.getenv("TERM") == null ? false : System.getenv("TERM").equals("linux");
- String prog = program == null ? ArgParser.parentName(0, true) : program;
- this.program = prog == null ? "?" : prog;
- this.description = description;
- this.usage = usage;
- this.longDescription = longDescription;
- this.out = useStderr ? System.err : System.out;
- }
-
-
-
- /**
- * Whether the Linux VT is being used
- */
- public boolean linuxvt;
-
- /**
- * The name of the executed command
- */
- public final String program;
-
- /**
- * Short, single-line, description of the program
- */
- private final String description;
-
- /**
- * Formated, multi-line, usage text, {@code null} if none
- */
- private final String usage;
-
- /**
- * Long, multi-line, description of the program, {@code null} if none
- */
- private final String longDescription;
-
- /**
- * The error output stream
- */
- private final OutputStream out;
-
- /**
- * The passed arguments
- */
- public String[] arguments = null;
-
- /**
- * The number of unrecognised arguments
- */
- public int unrecognisedCount = 0;
-
- /**
- * The concatination of {@link #files} with blankspaces as delimiters, {@code null} if no files
- */
- public String message = null;
-
- /**
- * Options, in order
- */
- private final ArrayList<Option> options = new ArrayList<Option>();
-
- /**
- * Option map
- */
- public final HashMap<String, Option> optmap = new HashMap<String, Option>();
-
- /**
- * The arguments passed that is not tied to an option
- */
- public final ArrayList<String> files = new ArrayList<String>();
-
- /**
- * Parsed arguments, a map from option to arguments, {@code null} if not used,
- * add one {@code null} element per argumentless use.
- */
- public final HashMap<String, String[]> opts = new HashMap<String, String[]>();
-
-
-
- /**
- * Option class
- */
- public static class Option
- {
- /**
- * Constructor
- *
- * @param alternatives Alterative option names
- * @param standard Standard option index
- * @param argument Argument name, not for argumentless options
- */
- protected Option(final String[] alternatives, final int standard, final String argument)
- {
- this.alternatives = alternatives;
- this.standard = alternatives[standard < 0 ? (alternatives.length + standard) : standard];
- this.argument = argument == null ? "ARG" : argument;
- }
-
-
-
- /**
- * Alterative option names
- */
- public final String[] alternatives;
-
- /**
- * Standard option name
- */
- public final String standard;
-
- /**
- * Argument name, not for argumentless options
- */
- public final String argument;
-
- /**
- * Help text, multi-line
- */
- public String help = null;
- }
-
-
- /**
- * Option takes no arguments
- */
- public static class Argumentless extends Option
- {
- /**
- * Constructor
- *
- * @param alternatives Alterative option names
- * @param standard Standard option index
- */
- public Argumentless(final String[] alternatives, final int standard)
- { super(alternatives, standard, null);
- }
-
- /**
- * Constructor
- *
- * @param standard Standard option index
- * @param alternatives Alterative option names
- */
- public Argumentless(final int standard, final String... alternatives)
- { super(alternatives, standard, null);
- }
-
- /**
- * Constructor
- *
- * @param alternatives Alterative option names
- */
- public Argumentless(final String... alternatives)
- { super(alternatives, 0, null);
- }
- }
-
-
- /**
- * Option takes one argument per instance
- */
- public static class Argumented extends Option
- {
- /**
- * Constructor
- *
- * @param alternatives Alterative option names
- * @param standard Standard option index
- * @param argument Argument name
- */
- public Argumented(final String[] alternatives, final int standard, final String argument)
- { super(alternatives, standard, argument);
- }
-
- /**
- * Constructor
- *
- * @param alternatives Alterative option names
- * @param argument Argument name
- * @param standard Standard option index
- */
- public Argumented(final String[] alternatives, final String argument, final int standard)
- { super(alternatives, standard, argument);
- }
-
- /**
- * Constructor
- *
- * @param alternatives Alterative option names
- * @param argument Argument name
- */
- public Argumented(final String[] alternatives, final String argument)
- { super(alternatives, 0, argument);
- }
-
- /**
- * Constructor
- *
- * @param standard Standard option index
- * @param argument Argument name
- * @param alternatives Alterative option names
- */
- public Argumented(final int standard, final String argument, final String... alternatives)
- { super(alternatives, standard, argument);
- }
-
- /**
- * Constructor
- *
- * @param argument Argument name
- * @param standard Standard option index
- * @param alternatives Alterative option names
- */
- public Argumented(final String argument, final int standard, final String... alternatives)
- { super(alternatives, standard, argument);
- }
-
- /**
- * Constructor
- *
- * @param argument Argument name
- * @param alternatives Alterative option names
- */
- public Argumented(final String argument, final String... alternatives)
- { super(alternatives, 0, argument);
- }
- }
-
-
- /**
- * Option consumes all following arguments
- */
- public static class Variadic extends Argumented
- {
- /**
- * Constructor
- *
- * @param alternatives Alterative option names
- * @param standard Standard option index
- * @param argument Argument name
- */
- public Variadic(final String[] alternatives, final int standard, final String argument)
- { super(alternatives, standard, argument);
- }
-
- /**
- * Constructor
- *
- * @param alternatives Alterative option names
- * @param argument Argument name
- * @param standard Standard option index
- */
- public Variadic(final String[] alternatives, final String argument, final int standard)
- { super(alternatives, argument, standard);
- }
-
- /**
- * Constructor
- *
- * @param alternatives Alterative option names
- * @param argument Argument name
- */
- public Variadic(final String[] alternatives, final String argument)
- { super(alternatives, argument);
- }
-
- /**
- * Constructor
- *
- * @param standard Standard option index
- * @param argument Argument name
- * @param alternatives Alterative option names
- */
- public Variadic(final int standard, final String argument, final String... alternatives)
- { super(standard, argument, alternatives);
- }
-
- /**
- * Constructor
- *
- * @param argument Argument name
- * @param standard Standard option index
- * @param alternatives Alterative option names
- */
- public Variadic(final String argument, final int standard, final String... alternatives)
- { super(argument, standard, alternatives);
- }
-
- /**
- * Constructor
- *
- * @param argument Argument name
- * @param alternatives Alterative option names
- */
- public Variadic(final String argument, final String... alternatives)
- { super(argument, alternatives);
- }
- }
-
-
-
- /**
- * Gets the name of the parent process
- *
- * @return The name of the parent process
- */
- public static String parentName()
- {
- return ArgParser.parentName(1, false);
- }
-
- /**
- * Gets the name of the parent process
- *
- * @param levels The number of parents to walk, 0 for self, and 1 for direct parent
- * @return The name of the parent process
- */
- public static String parentName(final int levels)
- {
- return ArgParser.parentName(levels, false);
- }
-
- /**
- * Gets the name of the parent process
- *
- * @param hasInterpretor Whether the parent process is an interpretor
- * @return The name of the parent process
- */
- public static String parentName(final boolean hasInterpretor)
- {
- return ArgParser.parentName(1, hasInterpretor);
- }
-
- /**
- * Gets the name of the parent process
- *
- * @param levels The number of parents to walk, 0 for self, and 1 for direct parent
- * @param hasInterpretor Whether the parent process is an interpretor
- * @return The name of the parent process
- */
- public static String parentName(final int levels, final boolean hasInterpretor)
- {
- int pid;
- try
- { pid = Integer.parseInt((new File("/proc/self")).getCanonicalPath().substring(6));
- }
- catch (final Throwable err)
- { return null;
- }
- int lvl = levels;
- try
- { outer:
- while (lvl > 0)
- {
- InputStream is = null;
- try
- { is = new FileInputStream(new File("/proc/" + pid + "/status"));
- byte[] data = new byte[1 << 12];
- int off = 0, read = 1;
- while (read > 0)
- { if (off == data.length)
- System.arraycopy(data, 0, data = new byte[data.length << 1], 0, off);
- off += read = is.read(data, off, data.length - off);
- }
- String[] lines = (new String(data, "UTF-8")).split("\n");
- for (String line : lines)
- { if (line.startsWith("PPid:"))
- {
- line = line.substring(5).replace('\t', ' ').replace(" ", "");
- pid = Integer.parseInt(line);
- lvl -= 1;
- continue outer;
- } }
- return null;
- }
- finally
- { if (is != null)
- try
- { is.close();
- }
- catch (final Throwable ignore)
- { /* ignore */
- } }
- }
- InputStream is = null;
- try
- { is = new FileInputStream(new File("/proc/" + pid + "/cmdline"));
- byte[] data = new byte[128];
- int off = 0, read = 1;
- while (read > 0)
- { if (off == data.length)
- System.arraycopy(data, 0, data = new byte[data.length << 1], 0, off);
- off += read = is.read(data, off, data.length - off);
- }
- String[] cmdline = new String(data, 0, off, "UTF-8").split("\0");
- if (hasInterpretor == false)
- { String rc = cmdline[0];
- return rc.length() == 0 ? null : rc;
- }
- boolean dashed = false;
- for (int i = 1, n = cmdline.length; i < n; i++)
- {
- if (dashed)
- return cmdline[i];
- if (cmdline[i].equals("--"))
- dashed = true;
- else if (cmdline[i].equals("-cp") || cmdline[i].equals("-classpath"))
- i++;
- else if (cmdline[i].startsWith("-") == false)
- return cmdline[i];
- }
- }
- finally
- { if (is != null)
- try
- { is.close();
- }
- catch (final Throwable ignore)
- { /* ignore */
- } }
- return null;
- }
- catch (final Throwable err)
- { return null;
- }
- }
-
-
- /**
- * Print an empty line to the selected error channel
- */
- private void println()
- {
- this.print("\n", true);
- }
-
- /**
- * Print an empty line to the selected error channel
- *
- * @param flush Whether to flush the stream
- */
- private void println(final boolean flush)
- {
- this.print("\n", flush);
- }
-
- /**
- * Print a text with an added line break to the selected error channel
- */
- private void println(final String text)
- {
- this.print(text + "\n", true);
- }
-
- /**
- * Print a text with an added line break to the selected error channel
- *
- * @param flush Whether to flush the stream
- */
- private void println(final String text, final boolean flush)
- {
- this.print(text + "\n", flush);
- }
-
- /**
- * Print a text to the selected error channel
- */
- private void print(final String text)
- {
- this.print(text, false);
- }
-
- /**
- * Print a text to the selected error channel
- *
- * @param flush Whether to flush the stream
- */
- private void print(final String text, final boolean flush)
- {
- try
- { if (text != null)
- this.out.write(text.getBytes("UTF-8"));
- if (flush)
- this.out.flush();
- }
- catch (final Throwable ignore)
- { /* ignore */
- }
- }
-
-
- /**
- * Add an option
- *
- * @param option The option
- */
- public void add(final Option option)
- {
- this.options.add(option);
- for (final String alternative : option.alternatives)
- this.optmap.put(alternative, option);
- this.opts.put(option.standard, null);
- }
-
- /**
- * Add an option
- *
- * @param option The option
- * @param help Help text, multi-line
- */
- public void add(final Option option, final String help)
- {
- this.add(help, option);
- }
-
- /**
- * Add an option
- *
- * @param help Help text, multi-line
- * @param option The option
- */
- public void add(final String help, final Option option)
- {
- this.add(option);
- option.help = help;
- }
-
-
- /**
- * Maps up options that are alternatives to the first alternative for each option
- */
- public void supportAlternatives()
- {
- for (final String opt : this.optmap.keySet())
- this.opts.put(opt, this.opts.get(this.optmap.get(opt).standard));
- }
-
-
- /**
- * Checks for option conflicts
- *
- * @param exclusives Exclusive options
- * @param exitValue The value to exit with on the check does not pass,
- * @return Whether at most one exclusive option was used
- */
- public boolean testExclusiveness(final Set<String> exclusives, final int exitValue)
- {
- boolean rc = this.testExclusiveness(exclusives);
- if (rc == false)
- System.exit(exitValue);
- return rc;
- }
-
- /**
- * Checks for option conflicts
- *
- * @param exclusives Exclusive options
- * @return Whether at most one exclusive option was used
- */
- public boolean testExclusiveness(final Set<String> exclusives)
- {
- final ArrayList<String> used = new ArrayList<String>();
-
- for (final String opt : this.opts.keySet())
- if ((this.opts.get(opt) != null) && exclusives.contains(opt))
- used.add(opt);
-
- if (used.size() > 1)
- { String msg = this.program + ": conflicting options:";
- for (final String opt : used)
- if (this.optmap.get(opt).standard.equals(opt))
- msg += " " + opt;
- else
- msg += " " + opt + "(" + this.optmap.get(opt).standard + ")";
- this.println(msg, true);
- return false;
- }
- return true;
- }
-
-
- /**
- * Checks for out of context option usage
- *
- * @param allowed Allowed options
- * @param exitValue The value to exit with on the check does not pass,
- * @return Whether only allowed options was used
- */
- public boolean testAllowed(final Set<String> allowed, final int exitValue)
- {
- boolean rc = this.testAllowed(allowed);
- if (rc == false)
- System.exit(exitValue);
- return rc;
- }
-
- /**
- * Checks for out of context option usage
- *
- * @param allowed Allowed options
- * @return Whether only allowed options was used
- */
- public boolean testAllowed(final Set<String> allowed)
- {
- boolean rc = true;
- for (final String opt : this.opts.keySet())
- if ((this.opts.get(opt) != null) && (allowed.contains(opt) == false))
- { String msg = this.program + ": option used out of context: " + opt;
- if (opt.equals(this.optmap.get(opt).standard) == false)
- msg += "(" + this.optmap.get(opt).standard + ")";
- this.println(msg, true);
- rc = false;
- }
- return rc;
- }
-
-
- /**
- * Checks the correctness of the number of used non-option arguments
- *
- * @param min The minimum number of files
- * @param exitValue The value to exit with on the check does not pass
- * @return Whether the usage was correct
- */
- public boolean testFilesMin(final int min, final int exitValue)
- {
- boolean rc = this.testFilesMin(min);
- if (rc == false)
- System.exit(exitValue);
- return rc;
- }
-
- /**
- * Checks the correctness of the number of used non-option arguments
- *
- * @param min The minimum number of files
- * @return Whether the usage was correct
- */
- public boolean testFilesMin(final int min)
- {
- return min <= this.files.size();
- }
-
- /**
- * Checks the correctness of the number of used non-option arguments
- *
- * @param max The maximum number of files
- * @param exitValue The value to exit with on the check does not pass
- * @return Whether the usage was correct
- */
- public boolean testFilesMax(final int max, final int exitValue)
- {
- boolean rc = this.testFilesMax(max);
- if (rc == false)
- System.exit(exitValue);
- return rc;
- }
-
- /**
- * Checks the correctness of the number of used non-option arguments
- *
- * @param max The maximum number of files
- * @return Whether the usage was correct
- */
- public boolean testFilesMax(final int max)
- {
- return this.files.size() <= max;
- }
-
- /**
- * Checks the correctness of the number of used non-option arguments
- *
- * @param min The minimum number of files
- * @param max The maximum number of files
- * @param exitValue The value to exit with on the check does not pass
- * @return Whether the usage was correct
- */
- public boolean testFiles(final int min, final int max, final int exitValue)
- {
- boolean rc = this.testFiles(min, max);
- if (rc == false)
- System.exit(exitValue);
- return rc;
- }
-
- /**
- * Checks the correctness of the number of used non-option arguments
- *
- * @param min The minimum number of files
- * @param max The maximum number of files
- * @return Whether the usage was correct
- */
- public boolean testFiles(final int min, final int max)
- {
- return (min <= this.files.size()) && (this.files.size() <= max);
- }
-
-
- /**
- * Prints a colourful help message
- */
- public void help()
- {
- final String dash = this.linuxvt ? "-" : "—";
- this.println("\033[01m" + program + "\033[21m " + dash + " " + this.description + "\n", false);
- if (this.longDescription != null)
- this.println(longDescription, false);
- this.println(false);
-
- if (this.usage != null)
- { this.print("\033[01mUSAGE:\033[21m");
- boolean first = true;
- for (final String line : this.usage.split("\n"))
- { if (first)
- first = false;
- else
- this.print(" or");
- this.println("\t" + line, false);
- }
- this.println(false);
- }
-
- int maxfirstlen = 0;
- for (final Option opt : this.options)
- { if (opt.help == null)
- continue;
- if (opt.alternatives.length > 1)
- if (maxfirstlen < opt.alternatives[0].length())
- maxfirstlen = opt.alternatives[0].length();
- }
- String empty = " ";
- while (empty.length() < maxfirstlen)
- empty += empty;
- empty = empty.substring(0, maxfirstlen);
-
- this.println("\033[01mSYNOPSIS:\033[21m", false);
- final ArrayList<String> lines = new ArrayList<String>();
- final ArrayList<int[]> lens = new ArrayList<int[]>();
- for (final Option opt : this.options)
- { if (opt.help == null)
- continue;
- int l = 0;
- String first = opt.alternatives[0];
- String last = opt.alternatives[opt.alternatives.length - 1];
- if (first == last)
- first = empty;
- else
- first += empty.substring(first.length());
- String line = " \033[02m" + first + "\033[22m \0" + last;
- l += first.length() + 6 + last.length();
- if (opt.getClass() == Variadic.class)
- { line += " [\033[04m" + opt.argument + "\033[24m...]";
- l += opt.argument.length() + 6;
- }
- else if (opt.getClass() == Argumented.class)
- { line += " \033[04m" + opt.argument + "\033[24m";
- l += opt.argument.length() + 1;
- }
- lines.add(line);
- lens.add(new int[] { l });
- }
-
- int col = 0;
- for (final int[] len : lens)
- if (col < len[0])
- col = len[0];
- col += 8 - ((col - 4) & 7);
- int index = 0;
-
- empty += " ";
- while (empty.length() < col)
- empty += empty;
- empty = empty.substring(0, col);
- for (final Option opt : this.options)
- { if (opt.help == null)
- continue;
- boolean first = true;
- final String colour = (index & 1) == 0 ? "36" : "34";
- { String line = lines.get(index).replace("\0", "\033[" + colour + ";01m");
- line += empty.substring(lens.get(index)[0]);
- this.print(line, false);
- }
- for (final String line : opt.help.split("\n"))
- if (first)
- { first = false;
- this.print(line + "\033[00m\n");
- }
- else
- this.print(empty + "\033[" + colour + "m" + line + "\033[00m\n");
- index++;
- }
-
- this.println(true);
- }
-
-
- /**
- * Parse arguments
- *
- * @param args The command line arguments, however it should not include the execute file at index 0
- * @return Whether no unrecognised option is used
- */
- public boolean parse(final String[] argv)
- {
- this.arguments = argv;
-
- final ArrayList<String> argqueue = new ArrayList<String>();
- final ArrayList<String> optqueue = new ArrayList<String>();
- final ArrayList<String> queue = new ArrayList<String>();
- for (final String arg : argv)
- queue.add(arg);
-
- boolean dashed = false, tmpdashed = false, rc = true;
- int get = 0, dontget = 0;
-
- while (queue.size() > 0)
- { final String arg = queue.remove(0);
- if ((get > 0) && (dontget == 0))
- { get--;
- argqueue.add(arg);
- }
- else if (tmpdashed)
- { this.files.add(arg);
- tmpdashed = false;
- }
- else if (dashed) this.files.add(arg);
- else if (arg.equals("++")) tmpdashed = true;
- else if (arg.equals("--")) dashed = true;
- else if ((arg.length() > 1) && ((arg.charAt(0) == '-') || (arg.charAt(0) == '+')))
- if ((arg.length() > 2) && (arg.charAt(1) == arg.charAt(0)))
- { Option opt = this.optmap.get(arg);
- if (dontget > 0)
- dontget--;
- else if ((opt != null) && (opt.getClass() == Argumentless.class))
- { optqueue.add(arg);
- argqueue.add(null);
- }
- else if (arg.contains("="))
- { String arg_opt = arg.substring(0, arg.indexOf('='));
- Option arg_opt_opt = this.optmap.get(arg_opt);
- if ((arg_opt_opt != null) && (arg_opt_opt instanceof Argumented))
- { optqueue.add(arg_opt);
- argqueue.add(arg.substring(arg.indexOf('=') + 1));
- if (arg_opt_opt instanceof Variadic)
- dashed = true;
- }
- else
- { if (++this.unrecognisedCount <= 5)
- this.println(this.program + ": warning: unrecognised option " + arg, true);
- rc = false;
- }
- }
- else if ((opt != null) && (opt.getClass() == Argumented.class))
- { optqueue.add(arg);
- get++;
- }
- else if ((opt != null) && (opt.getClass() == Variadic.class))
- { optqueue.add(arg);
- argqueue.add(null);
- dashed = true;
- }
- else
- { if (++this.unrecognisedCount <= 5)
- this.println(this.program + ": warning: unrecognised option " + arg, true);
- rc = false;
- }
- }
- else
- { String sign = String.valueOf(arg.charAt(0)), narg;
- int i = 1, n = arg.length();
- while (i < n)
- { Option opt = this.optmap.get(narg = sign + arg.charAt(i++));
- if (opt != null)
- if (opt.getClass() == Argumentless.class)
- { optqueue.add(narg);
- argqueue.add(null);
- }
- else if (opt.getClass() == Argumented.class)
- { optqueue.add(narg);
- String nargarg = arg.substring(i);
- if (nargarg.length() == 0)
- get++;
- else
- argqueue.add(nargarg);
- break;
- }
- else
- { optqueue.add(narg);
- String nargarg = arg.substring(i);
- argqueue.add(nargarg.length() > 0 ? nargarg : null);
- dashed = true;
- break;
- }
- else
- { if (++this.unrecognisedCount <= 5)
- this.println(this.program + ": warning: unrecognised option " + arg, true);
- rc = false;
- }
- } }
- else
- this.files.add(arg);
- }
-
- int i = 0, n = optqueue.size();
- while (i < n)
- {
- final String opt = this.optmap.get(optqueue.get(i)).standard;
- final String arg = argqueue.size() > i ? argqueue.get(i) : null;
- i++;
- if (this.opts.get(opt) == null)
- this.opts.put(opt, new String[] {});
- if (argqueue.size() >= i)
- this.opts.put(opt, append(this.opts.get(opt), arg));
- }
-
- for (final Option opt : this.options)
- if (opt.getClass() == Variadic.class)
- { final String[] varopt = this.opts.get(opt.standard);
- if (varopt != null)
- {
- final String[] additional = new String[this.files.size()];
- this.files.toArray(additional);
- if (varopt[0] == null)
- this.opts.put(opt.standard, additional);
- else
- this.opts.put(opt.standard, append(varopt, additional));
- this.files.clear();
- break;
- } }
-
- if (this.files.size() > 0)
- { final StringBuilder sb = new StringBuilder();
- for (final String file : this.files)
- { sb.append(' ');
- sb.append(file);
- }
- this.message = sb.toString();
- if (this.message.length() > 0)
- this.message = this.message.substring(1);
- }
-
- if (this.unrecognisedCount > 5)
- { int more = this.unrecognisedCount - 5;
- this.print(this.program + ": warning: " + more + " more unrecognised ");
- this.println(more == 1 ? "option" : "options");
- }
-
- return rc;
- }
-
-
- /**
- * Create a new identical array, except with extra items at the end
- *
- * @param array The array
- * @param items The new items
- * @return The new array
- */
- private String[] append(final String[] array, final String... items)
- {
- final String[] rc = new String[array.length + items.length];
- System.arraycopy(array, 0, rc, 0, array.length);
- System.arraycopy(items, 0, rc, array.length, items.length);
- return rc;
- }
-
-}
-