Index: src/gnu/getopt/Getopt.java
===================================================================
--- src/gnu/getopt/Getopt.java	(Revision 14351)
+++ src/gnu/getopt/Getopt.java	(nicht existent)
@@ -1,1384 +0,0 @@
-/*
-/* Copyright (c) 1987-1997 Free Software Foundation, Inc.
-/* Java Port Copyright (c) 1998 by Aaron M. Renn (arenn@urbanophile.com)
-/*
-/* This program is free software; you can redistribute it and/or modify
-/* it under the terms of the GNU Library General Public License as published
-/* by  the Free Software Foundation; either version 2 of the License or
-/* (at your option) any later version.
-/*
-/* This program 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 Library General Public License for more details.
-/*
-/* You should have received a copy of the GNU Library General Public License
-/* along with this program; see the file COPYING.LIB.  If not, write to
-/* the Free Software Foundation Inc., 59 Temple Place - Suite 330,
-/* Boston, MA  02111-1307 USA
-/**************************************************************************/
-
-package gnu.getopt;
-
-import java.text.MessageFormat;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.function.Function;
-
-/**************************************************************************/
-
-/**
-  * This is a Java port of GNU getopt, a class for parsing command line
-  * arguments passed to programs.  It it based on the C getopt() functions
-  * in glibc 2.0.6 and should parse options in a 100% compatible manner.
-  * If it does not, that is a bug.  The programmer's interface is also
-  * very compatible.
-  * <p>
-  * To use Getopt, create a Getopt object with a argv array passed to the
-  * main method, then call the getopt() method in a loop.  It will return an
-  * int that contains the value of the option character parsed from the
-  * command line.  When there are no more options to be parsed, it
-  * returns -1.
-  * <p>
-  * A command line option can be defined to take an argument.  If an
-  * option has an argument, the value of that argument is stored in an
-  * instance variable called optarg, which can be accessed using the
-  * getOptarg() method.  If an option that requires an argument is
-  * found, but there is no argument present, then an error message is
-  * printed. Normally getopt() returns a '?' in this situation, but
-  * that can be changed as described below.
-  * <p>
-  * If an invalid option is encountered, an error message is printed
-  * to the standard error and getopt() returns a '?'.  The value of the
-  * invalid option encountered is stored in the instance variable optopt
-  * which can be retrieved using the getOptopt() method.  To suppress
-  * the printing of error messages for this or any other error, set
-  * the value of the opterr instance variable to false using the
-  * setOpterr() method.
-  * <p>
-  * Between calls to getopt(), the instance variable optind is used to
-  * keep track of where the object is in the parsing process.  After all
-  * options have been returned, optind is the index in argv of the first
-  * non-option argument.  This variable can be accessed with the getOptind()
-  * method.
-  * <p>
-  * Note that this object expects command line options to be passed in the
-  * traditional Unix manner.  That is, proceeded by a '-' character.
-  * Multiple options can follow the '-'.  For example "-abc" is equivalent
-  * to "-a -b -c".  If an option takes a required argument, the value
-  * of the argument can immediately follow the option character or be
-  * present in the next argv element.  For example, "-cfoo" and "-c foo"
-  * both represent an option character of 'c' with an argument of "foo"
-  * assuming c takes a required argument.  If an option takes an argument
-  * that is not required, then any argument must immediately follow the
-  * option character in the same argv element.  For example, if c takes
-  * a non-required argument, then "-cfoo" represents option character 'c'
-  * with an argument of "foo" while "-c foo" represents the option
-  * character 'c' with no argument, and a first non-option argv element
-  * of "foo".
-  * <p>
-  * The user can stop getopt() from scanning any further into a command line
-  * by using the special argument "--" by itself.  For example:
-  * "-a -- -d" would return an option character of 'a', then return -1
-  * The "--" is discarded and "-d" is pointed to by optind as the first
-  * non-option argv element.
-  * <p>
-  * Here is a basic example of using Getopt:
-  * <p>
-  * <pre>
-  * Getopt g = new Getopt("testprog", argv, "ab:c::d");
-  * //
-  * int c;
-  * String arg;
-  * while ((c = g.getopt()) != -1)
-  *   {
-  *     switch(c)
-  *       {
-  *          case 'a':
-  *          case 'd':
-  *            System.out.print("You picked " + (char)c + "\n");
-  *            break;
-  *            //
-  *          case 'b':
-  *          case 'c':
-  *            arg = g.getOptarg();
-  *            System.out.print("You picked " + (char)c +
-  *                             " with an argument of " +
-  *                             ((arg != null) ? arg : "null") + "\n");
-  *            break;
-  *            //
-  *          case '?':
-  *            break; // getopt() already printed an error
-  *            //
-  *          default:
-  *            System.out.print("getopt() returned " + c + "\n");
-  *       }
-  *   }
-  * </pre>
-  * <p>
-  * In this example, a new Getopt object is created with three params.
-  * The first param is the program name.  This is for printing error
-  * messages in the form "program: error message".  In the C version, this
-  * value is taken from argv[0], but in Java the program name is not passed
-  * in that element, thus the need for this parameter.  The second param is
-  * the argument list that was passed to the main() method.  The third
-  * param is the list of valid options.  Each character represents a valid
-  * option.  If the character is followed by a single colon, then that
-  * option has a required argument.  If the character is followed by two
-  * colons, then that option has an argument that is not required.
-  * <p>
-  * Note in this example that the value returned from getopt() is cast to
-  * a char prior to printing.  This is required in order to make the value
-  * display correctly as a character instead of an integer.
-  * <p>
-  * If the first character in the option string is a colon, for example
-  * ":abc::d", then getopt() will return a ':' instead of a '?' when it
-  * encounters an option with a missing required argument.  This allows the
-  * caller to distinguish between invalid options and valid options that
-  * are simply incomplete.
-  * <p>
-  * In the traditional Unix getopt(), -1 is returned when the first non-option
-  * charcter is encountered.  In GNU getopt(), the default behavior is to
-  * allow options to appear anywhere on the command line.  The getopt()
-  * method permutes the argument to make it appear to the caller that all
-  * options were at the beginning of the command line, and all non-options
-  * were at the end.  For example, calling getopt() with command line args
-  * of "-a foo bar -d" returns options 'a' and 'd', then sets optind to
-  * point to "foo".  The program would read the last two argv elements as
-  * "foo" and "bar", just as if the user had typed "-a -d foo bar".
-  * <p>
-  * The user can force getopt() to stop scanning the command line with
-  * the special argument "--" by itself.  Any elements occuring before the
-  * "--" are scanned and permuted as normal.  Any elements after the "--"
-  * are returned as is as non-option argv elements.  For example,
-  * "foo -a -- bar -d" would return  option 'a' then -1.  optind would point
-  * to "foo", "bar" and "-d" as the non-option argv elements.  The "--"
-  * is discarded by getopt().
-  * <p>
-  * There are two ways this default behavior can be modified.  The first is
-  * to specify traditional Unix getopt() behavior (which is also POSIX
-  * behavior) in which scanning stops when the first non-option argument
-  * encountered.  (Thus "-a foo bar -d" would return 'a' as an option and
-  * have "foo", "bar", and "-d" as non-option elements).  The second is to
-  * allow options anywhere, but to return all elements in the order they
-  * occur on the command line.  When a non-option element is ecountered,
-  * an integer 1 is returned and the value of the non-option element is
-  * stored in optarg is if it were the argument to that option.  For
-  * example, "-a foo -d", returns first 'a', then 1 (with optarg set to
-  * "foo") then 'd' then -1.  When this "return in order" functionality
-  * is enabled, the only way to stop getopt() from scanning all command
-  * line elements is to use the special "--" string by itself as described
-  * above.  An example is "-a foo -b -- bar", which would return 'a', then
-  * integer 1 with optarg set to "foo", then 'b', then -1.  optind would
-  * then point to "bar" as the first non-option argv element.  The "--"
-  * is discarded.
-  * <p>
-  * The POSIX/traditional behavior is enabled by either setting the
-  * property "gnu.posixly_correct" or by putting a '+' sign as the first
-  * character of the option string.  The difference between the two
-  * methods is that setting the gnu.posixly_correct property also forces
-  * certain error messages to be displayed in POSIX format.  To enable
-  * the "return in order" functionality, put a '-' as the first character
-  * of the option string.  Note that after determining the proper
-  * behavior, Getopt strips this leading '+' or '-', meaning that a ':'
-  * placed as the second character after one of those two will still cause
-  * getopt() to return a ':' instead of a '?' if a required option
-  * argument is missing.
-  * <p>
-  * In addition to traditional single character options, GNU Getopt also
-  * supports long options.  These are preceeded by a "--" sequence and
-  * can be as long as desired.  Long options provide a more user-friendly
-  * way of entering command line options.  For example, in addition to a
-  * "-h" for help, a program could support also "--help".
-  * <p>
-  * Like short options, long options can also take a required or non-required
-  * argument.  Required arguments can either be specified by placing an
-  * equals sign after the option name, then the argument, or by putting the
-  * argument in the next argv element.  For example: "--outputdir=foo" and
-  * "--outputdir foo" both represent an option of "outputdir" with an
-  * argument of "foo", assuming that outputdir takes a required argument.
-  * If a long option takes a non-required argument, then the equals sign
-  * form must be used to specify the argument.  In this case,
-  * "--outputdir=foo" would represent option outputdir with an argument of
-  * "foo" while "--outputdir foo" would represent the option outputdir
-  * with no argument and a first non-option argv element of "foo".
-  * <p>
-  * Long options can also be specified using a special POSIX argument
-  * format (one that I highly discourage).  This form of entry is
-  * enabled by placing a "W;" (yes, 'W' then a semi-colon) in the valid
-  * option string.  This causes getopt to treat the name following the
-  * "-W" as the name of the long option.  For example, "-W outputdir=foo"
-  * would be equivalent to "--outputdir=foo".  The name can immediately
-  * follow the "-W" like so: "-Woutputdir=foo".  Option arguments are
-  * handled identically to normal long options.  If a string follows the
-  * "-W" that does not represent a valid long option, then getopt() returns
-  * 'W' and the caller must decide what to do.  Otherwise getopt() returns
-  * a long option value as described below.
-  * <p>
-  * While long options offer convenience, they can also be tedious to type
-  * in full.  So it is permissible to abbreviate the option name to as
-  * few characters as required to uniquely identify it.  If the name can
-  * represent multiple long options, then an error message is printed and
-  * getopt() returns a '?'.
-  * <p>
-  * If an invalid option is specified or a required option argument is
-  * missing, getopt() prints an error and returns a '?' or ':' exactly
-  * as for short options.  Note that when an invalid long option is
-  * encountered, the optopt variable is set to integer 0 and so cannot
-  * be used to identify the incorrect option the user entered.
-  * <p>
-  * Long options are defined by LongOpt objects.  These objects are created
-  * with a contructor that takes four params: a String representing the
-  * object name, a integer specifying what arguments the option takes
-  * (the value is one of LongOpt.NO_ARGUMENT, LongOpt.REQUIRED_ARGUMENT,
-  * or LongOpt.OPTIONAL_ARGUMENT), a StringBuffer flag object (described
-  * below), and an integer value (described below).
-  * <p>
-  * To enable long option parsing, create an array of LongOpt's representing
-  * the legal options and pass it to the Getopt() constructor.  WARNING: If
-  * all elements of the array are not populated with LongOpt objects, the
-  * getopt() method will throw a NullPointerException.
-  * <p>
-  * When getopt() is called and a long option is encountered, one of two
-  * things can be returned.  If the flag field in the LongOpt object
-  * representing the long option is non-null, then the integer value field
-  * is stored there and an integer 0 is returned to the caller.  The val
-  * field can then be retrieved from the flag field.  Note that since the
-  * flag field is a StringBuffer, the appropriate String to integer converions
-  * must be performed in order to get the actual int value stored there.
-  * If the flag field in the LongOpt object is null, then the value field
-  * of the LongOpt is returned.  This can be the character of a short option.
-  * This allows an app to have both a long and short option sequence
-  * (say, "-h" and "--help") that do the exact same thing.
-  * <p>
-  * With long options, there is an alternative method of determining
-  * which option was selected.  The method getLongind() will return the
-  * the index in the long option array (NOT argv) of the long option found.
-  * So if multiple long options are configured to return the same value,
-  * the application can use getLongind() to distinguish between them.
-  * <p>
-  * Here is an expanded Getopt example using long options and various
-  * techniques described above:
-  * <p>
-  * <pre>
-  * int c;
-  * String arg;
-  * LongOpt[] longopts = new LongOpt[3];
-  * //
-  * StringBuffer sb = new StringBuffer();
-  * longopts[0] = new LongOpt("help", LongOpt.NO_ARGUMENT, null, 'h');
-  * longopts[1] = new LongOpt("outputdir", LongOpt.REQUIRED_ARGUMENT, sb, 'o');
-  * longopts[2] = new LongOpt("maximum", LongOpt.OPTIONAL_ARGUMENT, null, 2);
-  * //
-  * Getopt g = new Getopt("testprog", argv, "-:bc::d:hW;", longopts);
-  * g.setOpterr(false); // We'll do our own error handling
-  * //
-  * while ((c = g.getopt()) != -1)
-  *   switch (c)
-  *     {
-  *        case 0:
-  *          arg = g.getOptarg();
-  *          System.out.println("Got long option with value '" +
-  *                             (char)(new Integer(sb.toString())).intValue()
-  *                             + "' with argument " +
-  *                             ((arg != null) ? arg : "null"));
-  *          break;
-  *          //
-  *        case 1:
-  *          System.out.println("I see you have return in order set and that " +
-  *                             "a non-option argv element was just found " +
-  *                             "with the value '" + g.getOptarg() + "'");
-  *          break;
-  *          //
-  *        case 2:
-  *          arg = g.getOptarg();
-  *          System.out.println("I know this, but pretend I didn't");
-  *          System.out.println("We picked option " +
-  *                             longopts[g.getLongind()].getName() +
-  *                           " with value " +
-  *                           ((arg != null) ? arg : "null"));
-  *          break;
-  *          //
-  *        case 'b':
-  *          System.out.println("You picked plain old option " + (char)c);
-  *          break;
-  *          //
-  *        case 'c':
-  *        case 'd':
-  *          arg = g.getOptarg();
-  *          System.out.println("You picked option '" + (char)c +
-  *                             "' with argument " +
-  *                             ((arg != null) ? arg : "null"));
-  *          break;
-  *          //
-  *        case 'h':
-  *          System.out.println("I see you asked for help");
-  *          break;
-  *          //
-  *        case 'W':
-  *          System.out.println("Hmmm. You tried a -W with an incorrect long " +
-  *                             "option name");
-  *          break;
-  *          //
-  *        case ':':
-  *          System.out.println("Doh! You need an argument for option " +
-  *                             (char)g.getOptopt());
-  *          break;
-  *          //
-  *        case '?':
-  *          System.out.println("The option '" + (char)g.getOptopt() +
-  *                           "' is not valid");
-  *          break;
-  *          //
-  *        default:
-  *          System.out.println("getopt() returned " + c);
-  *          break;
-  *     }
-  * //
-  * for (int i = g.getOptind(); i < argv.length ; i++)
-  *   System.out.println("Non option argv element: " + argv[i] + "\n");
-  * </pre>
-  * <p>
-  * There is an alternative form of the constructor used for long options
-  * above.  This takes a trailing boolean flag.  If set to false, Getopt
-  * performs identically to the example, but if the boolean flag is true
-  * then long options are allowed to start with a single '-' instead of
-  * "--".  If the first character of the option is a valid short option
-  * character, then the option is treated as if it were the short option.
-  * Otherwise it behaves as if the option is a long option.  Note that
-  * the name given to this option - long_only - is very counter-intuitive.
-  * It does not cause only long options to be parsed but instead enables
-  * the behavior described above.
-  * <p>
-  * Note that the functionality and variable names used are driven from
-  * the C lib version as this object is a port of the C code, not a
-  * new implementation.  This should aid in porting existing C/C++ code,
-  * as well as helping programmers familiar with the glibc version to
-  * adapt to the Java version even if it seems very non-Java at times.
-  * <p>
-  * In this release I made all instance variables protected due to
-  * overwhelming public demand.  Any code which relied on optarg,
-  * opterr, optind, or optopt being public will need to be modified to
-  * use the appropriate access methods.
-  * <p>
-  * Please send all bug reports, requests, and comments to
-  * <a href="mailto:arenn@urbanophile.com">arenn@urbanophile.com</a>.
-  *
-  * @version 1.0.7
-  *
-  * @author Roland McGrath (roland@gnu.ai.mit.edu)
-  * @author Ulrich Drepper (drepper@cygnus.com)
-  * @author Aaron M. Renn (arenn@urbanophile.com)
-  *
-  * @see LongOpt
-  */
-public class Getopt extends Object
-{
-
-/**************************************************************************/
-
-/*
- * Class Variables
- */
-
-/**
-  * Describe how to deal with options that follow non-option ARGV-elements.
-  *
-  * If the caller did not specify anything,
-  * the default is REQUIRE_ORDER if the property
-  * gnu.posixly_correct is defined, PERMUTE otherwise.
-  *
-  * The special argument `--' forces an end of option-scanning regardless
-  * of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
-  * `--' can cause `getopt' to return -1 with `optind' != ARGC.
-  *
-  * REQUIRE_ORDER means don't recognize them as options;
-  * stop option processing when the first non-option is seen.
-  * This is what Unix does.
-  * This mode of operation is selected by either setting the property
-  * gnu.posixly_correct, or using `+' as the first character
-  * of the list of option characters.
-  */
-protected static final int REQUIRE_ORDER = 1;
-
-/**
-  * PERMUTE is the default.  We permute the contents of ARGV as we scan,
-  * so that eventually all the non-options are at the end.  This allows options
-  * to be given in any order, even with programs that were not written to
-  * expect this.
-  */
-protected static final int PERMUTE = 2;
-
-/**
-  * RETURN_IN_ORDER is an option available to programs that were written
-  * to expect options and other ARGV-elements in any order and that care about
-  * the ordering of the two.  We describe each non-option ARGV-element
-  * as if it were the argument of an option with character code 1.
-  * Using `-' as the first character of the list of option characters
-  * selects this mode of operation.
-  */
-protected static final int RETURN_IN_ORDER = 3;
-
-/**************************************************************************/
-
-/*
- * Instance Variables
- */
-
-/**
-  * For communication from `getopt' to the caller.
-  * When `getopt' finds an option that takes an argument,
-  * the argument value is returned here.
-  * Also, when `ordering' is RETURN_IN_ORDER,
-  * each non-option ARGV-element is returned here.
-  */
-protected String optarg;
-
-/**
-  *  Index in ARGV of the next element to be scanned.
-  *  This is used for communication to and from the caller
-  *  and for communication between successive calls to `getopt'.
-  *
-  *  On entry to `getopt', zero means this is the first call; initialize.
-  *
-  *  When `getopt' returns -1, this is the index of the first of the
-  *  non-option elements that the caller should itself scan.
-  *
-  *  Otherwise, `optind' communicates from one call to the next
-  *  how much of ARGV has been scanned so far.
-  */
-protected int optind = 0;
-
-/**
-  * Callers store false here to inhibit the error message
-  * for unrecognized options.
-  */
-protected boolean opterr = true;
-
-/**
-  * When an unrecognized option is encountered, getopt will return a '?'
-  * and store the value of the invalid option here.
-  */
-protected int optopt = '?';
-
-/**
-  * The next char to be scanned in the option-element
-  * in which the last option character we returned was found.
-  * This allows us to pick up the scan where we left off.
-  *
-  * If this is zero, or a null string, it means resume the scan
-  * by advancing to the next ARGV-element.
-  */
-protected String nextchar;
-
-/**
-  * This is the string describing the valid short options.
-  */
-protected String optstring;
-
-/**
-  * This is an array of LongOpt objects which describ the valid long
-  * options.
-  */
-protected LongOpt[] long_options;
-
-/**
-  * This flag determines whether or not we are parsing only long args
-  */
-protected boolean long_only;
-
-/**
-  * Stores the index into the long_options array of the long option found
-  */
-protected int longind;
-
-/**
-  * The flag determines whether or not we operate in strict POSIX compliance
-  */
-protected boolean posixly_correct;
-
-/**
-  * A flag which communicates whether or not checkLongOption() did all
-  * necessary processing for the current option
-  */
-protected boolean longopt_handled;
-
-/**
-  * The index of the first non-option in argv[]
-  */
-protected int first_nonopt = 1;
-
-/**
-  * The index of the last non-option in argv[]
-  */
-protected int last_nonopt = 1;
-
-/**
-  * Flag to tell getopt to immediately return -1 the next time it is
-  * called.
-  */
-private boolean endparse = false;
-
-/**
-  * Saved argument list passed to the program
-  */
-protected String[] argv;
-
-/**
-  * Determines whether we permute arguments or not
-  */
-protected int ordering;
-
-/**
-  * Name to print as the program name in error messages.  This is necessary
-  * since Java does not place the program name in argv[0]
-  */
-protected String progname;
-
-/**
-  * The localized strings are kept in a separate file
-  */
-private OptI18n _messages = new OptI18n(); // ResourceBundle.getBundle("gnu/getopt/MessagesBundle", Locale.getDefault());
-
-/**************************************************************************/
-
-/*
- * Constructors
- */
-
-/**
-  * Construct a basic Getopt instance with the given input data.  Note that
-  * this handles "short" options only.
-  *
-  * @param progname The name to display as the program name when printing errors
-  * @param argv The String array passed as the command line to the program.
-  * @param optstring A String containing a description of the valid args for this program
-  */
-public
-Getopt(String progname, String[] argv, String optstring)
-{
-  this(progname, argv, optstring, null, false);
-}
-
-/**************************************************************************/
-
-/**
-  * Construct a Getopt instance with given input data that is capable of
-  * parsing long options as well as short.
-  *
-  * @param progname The name to display as the program name when printing errors
-  * @param argv The String array passed as the command ilne to the program
-  * @param optstring A String containing a description of the valid short args for this program
-  * @param long_options An array of LongOpt objects that describes the valid long args for this program
-  */
-public
-Getopt(String progname, String[] argv, String optstring,
-       LongOpt[] long_options)
-{
-  this(progname, argv, optstring, long_options, false);
-}
-
-/**************************************************************************/
-
-private static Function<String, String> tr = Function.identity();
-
-/**
- * Set the global translation handler for Getopt.
- *
- * This needs to be done before any call to {@link Getopt} or {@link LongOpt}
- * constructor.
- * @param tr function that takes messages in English and returns the localized message
- */
-public static void setI18nHandler(Function<String, String> tr) {
-    Getopt.tr = tr;
-}
-
-static class OptI18n {
-
-    private final Map<String, String> trns = new HashMap<>();
-
-    public  OptI18n() {
-        add("getopt.ambigious", tr("{0}: option ''{1}'' is ambiguous"));
-        add("getopt.arguments1", tr("{0}: option ''--{1}'' does not allow an argument"));
-        add("getopt.arguments2", tr("{0}: option ''{1}{2}'' does not allow an argument"));
-        add("getopt.requires", tr("{0}: option ''{1}'' requires an argument"));
-        add("getopt.unrecognized", tr("{0}: unrecognized option ''--{1}''"));
-        add("getopt.unrecognized2", tr("{0}: unrecognized option ''{1}{2}''"));
-        add("getopt.illegal", tr("{0}: illegal option -- {1}"));
-        add("getopt.invalid", tr("{0}: invalid option -- {1}"));
-        add("getopt.requires2", tr("{0}: option requires an argument -- {1}"));
-        add("getopt.invalidValue", tr("Invalid value {0} for parameter ''has_arg''"));
-    }
-
-    private String tr(String s) {
-        return Getopt.tr.apply(s);
-    }
-
-    private void add(String key, String value) {
-        trns.put(key, value);
-    }
-
-    public String getString(String s) {
-        String val = trns.get(s);
-        if (val == null) throw new IllegalArgumentException();
-        return val.replace("'", "''");
-    }
-}
-
-/**
-  * Construct a Getopt instance with given input data that is capable of
-  * parsing long options and short options.  Contrary to what you might
-  * think, the flag 'long_only' does not determine whether or not we
-  * scan for only long arguments.  Instead, a value of true here allows
-  * long arguments to start with a '-' instead of '--' unless there is a
-  * conflict with a short option name.
-  *
-  * @param progname The name to display as the program name when printing errors
-  * @param argv The String array passed as the command ilne to the program
-  * @param optstring A String containing a description of the valid short args for this program
-  * @param long_options An array of LongOpt objects that describes the valid long args for this program
-  * @param long_only true if long options that do not conflict with short options can start with a '-' as well as '--'
-  */
-public
-Getopt(String progname, String[] argv, String optstring,
-       LongOpt[] long_options, boolean long_only)
-{
-  if (optstring.length() == 0)
-    optstring = " ";
-
-  // This function is essentially _getopt_initialize from GNU getopt
-  this.progname = progname;
-  this.argv = argv;
-  this.optstring = optstring;
-  this.long_options = long_options;
-  this.long_only = long_only;
-
-  // Check for property "gnu.posixly_correct" to determine whether to
-  // strictly follow the POSIX standard.  This replaces the "POSIXLY_CORRECT"
-  // environment variable in the C version
-  try {
-  if (System.getProperty("gnu.posixly_correct", null) == null)
-    posixly_correct = false;
-  else
-    {
-      posixly_correct = true;
-      _messages = new OptI18n();//ResourceBundle.getBundle("gnu/getopt/MessagesBundle",
-                             //                      Locale.US);
-    }
-  } catch (SecurityException e) {
-    System.err.println(e.getMessage());
-  }
-
-  // Determine how to handle the ordering of options and non-options
-  if (optstring.charAt(0) == '-')
-    {
-      ordering = RETURN_IN_ORDER;
-      if (optstring.length() > 1)
-        this.optstring = optstring.substring(1);
-    }
-  else if (optstring.charAt(0) == '+')
-    {
-      ordering = REQUIRE_ORDER;
-      if (optstring.length() > 1)
-        this.optstring = optstring.substring(1);
-    }
-  else if (posixly_correct)
-    {
-      ordering = REQUIRE_ORDER;
-    }
-  else
-    {
-      ordering = PERMUTE; // The normal default case
-    }
-}
-
-/**************************************************************************/
-
-/*
- * Instance Methods
- */
-
-/**
-  * In GNU getopt, it is possible to change the string containg valid options
-  * on the fly because it is passed as an argument to getopt() each time.  In
-  * this version we do not pass the string on every call.  In order to allow
-  * dynamic option string changing, this method is provided.
-  *
-  * @param optstring The new option string to use
-  */
-public void
-setOptstring(String optstring)
-{
-  if (optstring.length() == 0)
-    optstring = " ";
-
-  this.optstring = optstring;
-}
-
-/**************************************************************************/
-
-/**
-  * optind it the index in ARGV of the next element to be scanned.
-  * This is used for communication to and from the caller
-  * and for communication between successive calls to `getopt'.
-  *
-  * When `getopt' returns -1, this is the index of the first of the
-  * non-option elements that the caller should itself scan.
-  *
-  * Otherwise, `optind' communicates from one call to the next
-  * how much of ARGV has been scanned so far.
-  */
-public int
-getOptind()
-{
-  return(optind);
-}
-
-/**************************************************************************/
-
-/**
-  * This method allows the optind index to be set manually.  Normally this
-  * is not necessary (and incorrect usage of this method can lead to serious
-  * lossage), but optind is a public symbol in GNU getopt, so this method
-  * was added to allow it to be modified by the caller if desired.
-  *
-  * @param optind The new value of optind
-  */
-public void
-setOptind(int optind)
-{
-  this.optind = optind;
-}
-
-/**************************************************************************/
-
-/**
-  * Since in GNU getopt() the argument vector is passed back in to the
-  * function every time, the caller can swap out argv on the fly.  Since
-  * passing argv is not required in the Java version, this method allows
-  * the user to override argv.  Note that incorrect use of this method can
-  * lead to serious lossage.
-  *
-  * @param argv New argument list
-  */
-public void
-setArgv(String[] argv)
-{
-  this.argv = argv;
-}
-
-/**************************************************************************/
-
-/**
-  * For communication from `getopt' to the caller.
-  * When `getopt' finds an option that takes an argument,
-  * the argument value is returned here.
-  * Also, when `ordering' is RETURN_IN_ORDER,
-  * each non-option ARGV-element is returned here.
-  * No set method is provided because setting this variable has no effect.
-  */
-public String
-getOptarg()
-{
-  return(optarg);
-}
-
-/**************************************************************************/
-
-/**
-  * Normally Getopt will print a message to the standard error when an
-  * invalid option is encountered.  This can be suppressed (or re-enabled)
-  * by calling this method.  There is no get method for this variable
-  * because if you can't remember the state you set this to, why should I?
-  */
-public void
-setOpterr(boolean opterr)
-{
-  this.opterr = opterr;
-}
-
-/**************************************************************************/
-
-/**
-  * When getopt() encounters an invalid option, it stores the value of that
-  * option in optopt which can be retrieved with this method.  There is
-  * no corresponding set method because setting this variable has no effect.
-  */
-public int
-getOptopt()
-{
-  return(optopt);
-}
-
-/**************************************************************************/
-
-/**
-  * Returns the index into the array of long options (NOT argv) representing
-  * the long option that was found.
-  */
-public int
-getLongind()
-{
-  return(longind);
-}
-
-/**************************************************************************/
-
-/**
-  * Exchange the shorter segment with the far end of the longer segment.
-  * That puts the shorter segment into the right place.
-  * It leaves the longer segment in the right place overall,
-  * but it consists of two parts that need to be swapped next.
-  * This method is used by getopt() for argument permutation.
-  */
-protected void
-exchange(String[] argv)
-{
-  int bottom = first_nonopt;
-  int middle = last_nonopt;
-  int top = optind;
-  String tem;
-
-  while (top > middle && middle > bottom)
-    {
-      if (top - middle > middle - bottom)
-        {
-          // Bottom segment is the short one.
-          int len = middle - bottom;
-          int i;
-
-          // Swap it with the top part of the top segment.
-          for (i = 0; i < len; i++)
-            {
-              tem = argv[bottom + i];
-              argv[bottom + i] = argv[top - (middle - bottom) + i];
-              argv[top - (middle - bottom) + i] = tem;
-            }
-          // Exclude the moved bottom segment from further swapping.
-          top -= len;
-        }
-      else
-        {
-          // Top segment is the short one.
-          int len = top - middle;
-          int i;
-
-          // Swap it with the bottom part of the bottom segment.
-          for (i = 0; i < len; i++)
-            {
-              tem = argv[bottom + i];
-              argv[bottom + i] = argv[middle + i];
-              argv[middle + i] = tem;
-            }
-          // Exclude the moved top segment from further swapping.
-          bottom += len;
-        }
-    }
-
-  // Update records for the slots the non-options now occupy.
-
-  first_nonopt += (optind - last_nonopt);
-  last_nonopt = optind;
-}
-
-/**************************************************************************/
-
-/**
-  * Check to see if an option is a valid long option.  Called by getopt().
-  * Put in a separate method because this needs to be done twice.  (The
-  * C getopt authors just copy-pasted the code!).
-  *
-  * @param longind A buffer in which to store the 'val' field of found LongOpt
-  *
-  * @return Various things depending on circumstances
-  */
-protected int
-checkLongOption()
-{
-  LongOpt pfound = null;
-  int nameend;
-  boolean ambig;
-  boolean exact;
-
-  longopt_handled = true;
-  ambig = false;
-  exact = false;
-  longind = -1;
-
-  nameend = nextchar.indexOf("=");
-  if (nameend == -1)
-    nameend = nextchar.length();
-
-  // Test all lnog options for either exact match or abbreviated matches
-  for (int i = 0; i < long_options.length; i++)
-    {
-      if (long_options[i].getName().startsWith(nextchar.substring(0, nameend)))
-        {
-          if (long_options[i].getName().equals(nextchar.substring(0, nameend)))
-            {
-              // Exact match found
-              pfound = long_options[i];
-              longind = i;
-              exact = true;
-              break;
-            }
-          else if (pfound == null)
-            {
-              // First nonexact match found
-              pfound = long_options[i];
-              longind = i;
-            }
-          else
-            {
-              // Second or later nonexact match found
-              ambig = true;
-            }
-        }
-    } // for
-
-  // Print out an error if the option specified was ambiguous
-  if (ambig && !exact)
-    {
-      if (opterr)
-        {
-          Object[] msgArgs = { progname, argv[optind] };
-          System.err.println(MessageFormat.format(
-                             _messages.getString("getopt.ambigious"),
-                             msgArgs));
-        }
-
-       nextchar = "";
-       optopt = 0;
-       ++optind;
-
-       return('?');
-    }
-
-  if (pfound != null)
-    {
-      ++optind;
-
-      if (nameend != nextchar.length())
-        {
-          if (pfound.has_arg != LongOpt.NO_ARGUMENT)
-            {
-              if (nextchar.substring(nameend).length() > 1)
-                optarg = nextchar.substring(nameend+1);
-              else
-                optarg = "";
-            }
-          else
-            {
-              if (opterr)
-                {
-                  // -- option
-                  if (argv[optind - 1].startsWith("--"))
-                    {
-                      Object[] msgArgs = { progname, pfound.name };
-                      System.err.println(MessageFormat.format(
-                                  _messages.getString("getopt.arguments1"),
-                                  msgArgs));
-                    }
-                  // +option or -option
-                  else
-                    {
-                      Object[] msgArgs = { progname,
-                               Character.toString(argv[optind-1].charAt(0)),
-                               pfound.name };
-                      System.err.println(MessageFormat.format(
-                               _messages.getString("getopt.arguments2"),
-                               msgArgs));
-                    }
-                 }
-
-              nextchar = "";
-              optopt = pfound.val;
-
-              return('?');
-            }
-        } // if (nameend)
-      else if (pfound.has_arg == LongOpt.REQUIRED_ARGUMENT)
-        {
-          if (optind < argv.length)
-            {
-               optarg = argv[optind];
-               ++optind;
-            }
-          else
-            {
-              if (opterr)
-                {
-                  Object[] msgArgs = { progname, argv[optind-1] };
-                  System.err.println(MessageFormat.format(
-                                     _messages.getString("getopt.requires"),
-                                     msgArgs));
-                }
-
-              nextchar = "";
-              optopt = pfound.val;
-              if (optstring.charAt(0) == ':')
-                return(':');
-              else
-                return('?');
-            }
-        } // else if (pfound)
-
-      nextchar = "";
-
-      if (pfound.flag != null)
-        {
-          pfound.flag.setLength(0);
-          pfound.flag.append(pfound.val);
-
-          return(0);
-        }
-
-      return(pfound.val);
-   } // if (pfound != null)
-
-  longopt_handled = false;
-
-  return(0);
-}
-
-/**************************************************************************/
-
-/**
-  * This method returns a char that is the current option that has been
-  * parsed from the command line.  If the option takes an argument, then
-  * the internal variable 'optarg' is set which is a String representing
-  * the the value of the argument.  This value can be retrieved by the
-  * caller using the getOptarg() method.  If an invalid option is found,
-  * an error message is printed and a '?' is returned.  The name of the
-  * invalid option character can be retrieved by calling the getOptopt()
-  * method.  When there are no more options to be scanned, this method
-  * returns -1.  The index of first non-option element in argv can be
-  * retrieved with the getOptind() method.
-  *
-  * @return Various things as described above
-  */
-public int
-getopt()
-{
-  optarg = null;
-
-  if (endparse == true)
-    return(-1);
-
-  if ((nextchar == null) || (nextchar.equals("")))
-    {
-      // If we have just processed some options following some non-options,
-      //  exchange them so that the options come first.
-      if (last_nonopt > optind)
-        last_nonopt = optind;
-      if (first_nonopt > optind)
-        first_nonopt = optind;
-
-      if (ordering == PERMUTE)
-        {
-          // If we have just processed some options following some non-options,
-          // exchange them so that the options come first.
-          if ((first_nonopt != last_nonopt) && (last_nonopt != optind))
-            exchange(argv);
-          else if (last_nonopt != optind)
-            first_nonopt = optind;
-
-          // Skip any additional non-options
-          // and extend the range of non-options previously skipped.
-          while ((optind < argv.length) && (argv[optind].equals("") ||
-            (argv[optind].charAt(0) != '-') || argv[optind].equals("-")))
-            {
-              optind++;
-            }
-
-          last_nonopt = optind;
-        }
-
-      // The special ARGV-element `--' means premature end of options.
-      // Skip it like a null option,
-      // then exchange with previous non-options as if it were an option,
-      // then skip everything else like a non-option.
-      if ((optind != argv.length) && argv[optind].equals("--"))
-        {
-          optind++;
-
-          if ((first_nonopt != last_nonopt) && (last_nonopt != optind))
-            exchange (argv);
-          else if (first_nonopt == last_nonopt)
-            first_nonopt = optind;
-
-          last_nonopt = argv.length;
-
-          optind = argv.length;
-        }
-
-      // If we have done all the ARGV-elements, stop the scan
-      // and back over any non-options that we skipped and permuted.
-      if (optind == argv.length)
-        {
-          // Set the next-arg-index to point at the non-options
-          // that we previously skipped, so the caller will digest them.
-          if (first_nonopt != last_nonopt)
-            optind = first_nonopt;
-
-          return(-1);
-        }
-
-      // If we have come to a non-option and did not permute it,
-      // either stop the scan or describe it to the caller and pass it by.
-      if (argv[optind].equals("") || (argv[optind].charAt(0) != '-') ||
-          argv[optind].equals("-"))
-        {
-          if (ordering == REQUIRE_ORDER)
-            return(-1);
-
-            optarg = argv[optind++];
-            return(1);
-        }
-
-      // We have found another option-ARGV-element.
-      // Skip the initial punctuation.
-      if (argv[optind].startsWith("--"))
-        nextchar = argv[optind].substring(2);
-      else
-        nextchar = argv[optind].substring(1);
-   }
-
-  // Decode the current option-ARGV-element.
-
-  /* Check whether the ARGV-element is a long option.
-
-     If long_only and the ARGV-element has the form "-f", where f is
-     a valid short option, don't consider it an abbreviated form of
-     a long option that starts with f.  Otherwise there would be no
-     way to give the -f short option.
-
-     On the other hand, if there's a long option "fubar" and
-     the ARGV-element is "-fu", do consider that an abbreviation of
-     the long option, just like "--fu", and not "-f" with arg "u".
-
-     This distinction seems to be the most useful approach.  */
-  if ((long_options != null) && (argv[optind].startsWith("--")
-      || (long_only && ((argv[optind].length()  > 2) ||
-      (optstring.indexOf(argv[optind].charAt(1)) == -1)))))
-    {
-       int c = checkLongOption();
-
-       if (longopt_handled)
-         return(c);
-
-      // Can't find it as a long option.  If this is not getopt_long_only,
-      // or the option starts with '--' or is not a valid short
-      // option, then it's an error.
-      // Otherwise interpret it as a short option.
-      if (!long_only || argv[optind].startsWith("--")
-        || (optstring.indexOf(nextchar.charAt(0)) == -1))
-        {
-          if (opterr)
-            {
-              if (argv[optind].startsWith("--"))
-                {
-                  Object[] msgArgs = { progname, nextchar };
-                  System.err.println(MessageFormat.format(
-                                   _messages.getString("getopt.unrecognized"),
-                                   msgArgs));
-                }
-              else
-                {
-                  Object[] msgArgs = { progname,
-                                 Character.toString(argv[optind].charAt(0)),
-                                 nextchar };
-                  System.err.println(MessageFormat.format(
-                                 _messages.getString("getopt.unrecognized2"),
-                                 msgArgs));
-                }
-            }
-
-          nextchar = "";
-          ++optind;
-          optopt = 0;
-
-          return('?');
-        }
-    } // if (longopts)
-
-  // Look at and handle the next short option-character */
-  int c = nextchar.charAt(0); //**** Do we need to check for empty str?
-  if (nextchar.length() > 1)
-    nextchar = nextchar.substring(1);
-  else
-    nextchar = "";
-
-  String temp = null;
-  if (optstring.indexOf(c) != -1)
-    temp = optstring.substring(optstring.indexOf(c));
-
-  if (nextchar.equals(""))
-    ++optind;
-
-  if ((temp == null) || (c == ':'))
-    {
-      if (opterr)
-        {
-          if (posixly_correct)
-            {
-              // 1003.2 specifies the format of this message
-              Object[] msgArgs = { progname,
-                                   Character.toString((char)c) };
-              System.err.println(MessageFormat.format(
-                            _messages.getString("getopt.illegal"), msgArgs));
-            }
-          else
-            {
-              Object[] msgArgs = { progname,
-                                   Character.toString((char)c) };
-              System.err.println(MessageFormat.format(
-                            _messages.getString("getopt.invalid"), msgArgs));
-            }
-        }
-
-      optopt = c;
-
-      return('?');
-    }
-
-  // Convenience. Treat POSIX -W foo same as long option --foo
-  if ((temp.charAt(0) == 'W') && (temp.length() > 1) && (temp.charAt(1) == ';'))
-    {
-      if (!nextchar.equals(""))
-        {
-          optarg = nextchar;
-        }
-      // No further cars in this argv element and no more argv elements
-      else if (optind == argv.length)
-        {
-          if (opterr)
-            {
-              // 1003.2 specifies the format of this message.
-              Object[] msgArgs = { progname,
-                                   Character.toString((char)c) };
-              System.err.println(MessageFormat.format(
-                            _messages.getString("getopt.requires2"), msgArgs));
-            }
-
-          optopt = c;
-          if (optstring.charAt(0) == ':')
-            return(':');
-          else
-            return('?');
-        }
-      else
-        {
-          // We already incremented `optind' once;
-          // increment it again when taking next ARGV-elt as argument.
-          nextchar = argv[optind];
-          optarg  = argv[optind];
-        }
-
-      c = checkLongOption();
-
-      if (longopt_handled)
-        return(c);
-      else
-        // Let the application handle it
-        {
-          nextchar = null;
-          ++optind;
-          return('W');
-        }
-    }
-
-  if ((temp.length() > 1) && (temp.charAt(1) == ':'))
-    {
-      if ((temp.length() > 2) && (temp.charAt(2) == ':'))
-        // This is an option that accepts and argument optionally
-        {
-          if (!nextchar.equals(""))
-            {
-               optarg = nextchar;
-               ++optind;
-            }
-          else
-            {
-              optarg = null;
-            }
-
-          nextchar = null;
-        }
-      else
-        {
-          if (!nextchar.equals(""))
-            {
-              optarg = nextchar;
-              ++optind;
-            }
-          else if (optind == argv.length)
-            {
-              if (opterr)
-                {
-                  // 1003.2 specifies the format of this message
-                  Object[] msgArgs = { progname,
-                                       Character.toString((char)c) };
-                  System.err.println(MessageFormat.format(
-                            _messages.getString("getopt.requires2"), msgArgs));
-                }
-
-              optopt = c;
-
-              if (optstring.charAt(0) == ':')
-                return(':');
-              else
-                return('?');
-            }
-          else
-            {
-              optarg = argv[optind];
-              ++optind;
-
-              // Ok, here's an obscure Posix case.  If we have o:, and
-              // we get -o -- foo, then we're supposed to skip the --,
-              // end parsing of options, and make foo an operand to -o.
-              // Only do this in Posix mode.
-              if ((posixly_correct) && optarg.equals("--"))
-                {
-                  // If end of argv, error out
-                  if (optind == argv.length)
-                    {
-                      if (opterr)
-                        {
-                          // 1003.2 specifies the format of this message
-                          Object[] msgArgs = { progname,
-                                               Character.toString((char)c) };
-                          System.err.println(MessageFormat.format(
-                             _messages.getString("getopt.requires2"), msgArgs));
-                        }
-
-                      optopt = c;
-
-                      if (optstring.charAt(0) == ':')
-                        return(':');
-                      else
-                        return('?');
-                    }
-
-                  // Set new optarg and set to end
-                  // Don't permute as we do on -- up above since we
-                  // know we aren't in permute mode because of Posix.
-                  optarg = argv[optind];
-                  ++optind;
-                  first_nonopt = optind;
-                  last_nonopt = argv.length;
-                  endparse = true;
-                }
-            }
-
-          nextchar = null;
-        }
-    }
-
-  return(c);
-}
-
-} // Class Getopt
-
-
Index: src/gnu/getopt/LongOpt.java
===================================================================
--- src/gnu/getopt/LongOpt.java	(Revision 14351)
+++ src/gnu/getopt/LongOpt.java	(nicht existent)
@@ -1,192 +0,0 @@
-/**************************************************************************
-/* LongOpt.java -- Long option object for Getopt
-/*
-/* Copyright (c) 1998 by Aaron M. Renn (arenn@urbanophile.com)
-/*
-/* This program is free software; you can redistribute it and/or modify
-/* it under the terms of the GNU Library General Public License as published
-/* by  the Free Software Foundation; either version 2 of the License or
-/* (at your option) any later version.
-/*
-/* This program 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 Library General Public License for more details.
-/*
-/* You should have received a copy of the GNU Library General Public License
-/* along with this program; see the file COPYING.LIB.  If not, write to
-/* the Free Software Foundation Inc., 59 Temple Place - Suite 330,
-/* Boston, MA  02111-1307 USA
-/**************************************************************************/
-
-package gnu.getopt;
-
-import java.text.MessageFormat;
-
-/**************************************************************************/
-
-/**
-  * This object represents the definition of a long option in the Java port
-  * of GNU getopt.  An array of LongOpt objects is passed to the Getopt
-  * object to define the list of valid long options for a given parsing
-  * session.  Refer to the getopt documentation for details on the
-  * format of long options.
-  *
-  * @version 1.0.5
-  * @author Aaron M. Renn (arenn@urbanophile.com)
-  *
-  * @see Getopt
-  */
-public class LongOpt extends Object
-{
-
-/**************************************************************************/
-
-/*
- * Class Variables
- */
-
-/**
-  * Constant value used for the "has_arg" constructor argument.  This
-  * value indicates that the option takes no argument.
-  */
-public static final int NO_ARGUMENT = 0;
-
-/**
-  * Constant value used for the "has_arg" constructor argument.  This
-  * value indicates that the option takes an argument that is required.
-  */
-public static final int REQUIRED_ARGUMENT = 1;
-
-/**
-  * Constant value used for the "has_arg" constructor argument.  This
-  * value indicates that the option takes an argument that is optional.
-  */
-public static final int OPTIONAL_ARGUMENT = 2;
-
-/**************************************************************************/
-
-/*
- * Instance Variables
- */
-
-/**
-  * The name of the long option
-  */
-protected String name;
-
-/**
-  * Indicates whether the option has no argument, a required argument, or
-  * an optional argument.
-  */
-protected int has_arg;
-
-/**
-  * If this variable is not null, then the value stored in "val" is stored
-  * here when this long option is encountered.  If this is null, the value
-  * stored in "val" is treated as the name of an equivalent short option.
-  */
-protected StringBuffer flag;
-
-/**
-  * The value to store in "flag" if flag is not null, otherwise the
-  * equivalent short option character for this long option.
-  */
-protected int val;
-
-/**
-  * Localized strings for error messages
-  */
-private Getopt.OptI18n _messages = new Getopt.OptI18n(); // ResourceBundle.getBundle("gnu/getopt/MessagesBundle", Locale.getDefault());
-
-/**************************************************************************/
-
-/*
- * Constructors
- */
-
-/**
-  * Create a new LongOpt object with the given parameter values.  If the
-  * value passed as has_arg is not valid, then an exception is thrown.
-  *
-  * @param name The long option String.
-  * @param has_arg Indicates whether the option has no argument (NO_ARGUMENT), a required argument (REQUIRED_ARGUMENT) or an optional argument (OPTIONAL_ARGUMENT).
-  * @param flag If non-null, this is a location to store the value of "val" when this option is encountered, otherwise "val" is treated as the equivalent short option character.
-  * @param val The value to return for this long option, or the equivalent single letter option to emulate if flag is null.
-  *
-  * @exception IllegalArgumentException If the has_arg param is not one of NO_ARGUMENT, REQUIRED_ARGUMENT or OPTIONAL_ARGUMENT.
-  */
-public
-LongOpt(String name, int has_arg,
-        StringBuffer flag, int val) throws IllegalArgumentException
-{
-  // Validate has_arg
-  if ((has_arg != NO_ARGUMENT) && (has_arg != REQUIRED_ARGUMENT)
-     && (has_arg != OPTIONAL_ARGUMENT))
-    {
-      Object[] msgArgs = { Integer.toString(has_arg) };
-      throw new IllegalArgumentException(MessageFormat.format(
-                    _messages.getString("getopt.invalidValue"), msgArgs));
-    }
-
-  // Store off values
-  this.name = name;
-  this.has_arg = has_arg;
-  this.flag = flag;
-  this.val = val;
-}
-
-/**************************************************************************/
-
-/**
-  * Returns the name of this LongOpt as a String
-  *
-  * @return Then name of the long option
-  */
-public String
-getName()
-{
-  return(name);
-}
-
-/**************************************************************************/
-
-/**
-  * Returns the value set for the 'has_arg' field for this long option
-  *
-  * @return The value of 'has_arg'
-  */
-public int
-getHasArg()
-{
-  return(has_arg);
-}
-
-/**************************************************************************/
-
-/**
-  * Returns the value of the 'flag' field for this long option
-  *
-  * @return The value of 'flag'
-  */
-public StringBuffer
-getFlag()
-{
-  return(flag);
-}
-
-/**
-  * Returns the value of the 'val' field for this long option
-  *
-  * @return The value of 'val'
-  */
-public int
-getVal()
-{
-  return(val);
-}
-
-/**************************************************************************/
-
-} // Class LongOpt
-
Index: src/org/openstreetmap/josm/data/projection/ProjectionCLI.java
===================================================================
--- src/org/openstreetmap/josm/data/projection/ProjectionCLI.java	(Revision 14351)
+++ src/org/openstreetmap/josm/data/projection/ProjectionCLI.java	(Arbeitskopie)
@@ -11,6 +11,7 @@
 import java.nio.file.Files;
 import java.nio.file.Paths;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.function.Function;
 
@@ -18,12 +19,9 @@
 import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.coor.conversion.LatLonParser;
-import org.openstreetmap.josm.tools.I18n;
+import org.openstreetmap.josm.tools.OptionParser;
 import org.openstreetmap.josm.tools.Utils;
 
-import gnu.getopt.Getopt;
-import gnu.getopt.LongOpt;
-
 /**
  * Command line interface for projecting coordinates.
  * @since 12792
@@ -43,37 +41,23 @@
 
     @Override
     public void processArguments(String[] argArray) {
-        Getopt.setI18nHandler(I18n::tr);
-        Getopt getopt = new Getopt("JOSM projection", argArray, "Irh", new LongOpt[] {
-                new LongOpt("help", LongOpt.NO_ARGUMENT, null, 'h')});
+        List<String> positionalArguments = new OptionParser("JOSM projection")
+            .addFlagParameter("help", this::showHelp)
+            .addShortAlias("help", "h")
+            .addFlagParameter("inverse", () -> argInverse = true)
+            .addShortAlias("inverse", "I")
+            .addFlagParameter("switch-input", () -> argSwitchInput = true)
+            .addShortAlias("switch-input", "r")
+            .addFlagParameter("switch-output", () -> argSwitchOutput = true)
+            .addShortAlias("switch-output", "s")
+            .parseOptionsOrExit(Arrays.asList(argArray));
 
-        int c;
-        while ((c = getopt.getopt()) != -1) {
-            switch (c) {
-            case 'h':
-                showHelp();
-                System.exit(0);
-            case 'I':
-                argInverse = true;
-                break;
-            case 'r':
-                argSwitchInput = true;
-                break;
-            case 's':
-                argSwitchOutput = true;
-                break;
-            default:
-                // ignore
-            }
-        }
-
         List<String> projParamFrom = new ArrayList<>();
         List<String> projParamTo = new ArrayList<>();
         List<String> otherPositional = new ArrayList<>();
         boolean toTokenSeen = false;
         // positional arguments:
-        for (int i = getopt.getOptind(); i < argArray.length; ++i) {
-            String arg = argArray[i];
+        for (String arg: positionalArguments) {
             if (arg.isEmpty()) throw new IllegalArgumentException("non-empty argument expected");
             if (arg.startsWith("+")) {
                 if ("+to".equals(arg)) {
@@ -99,8 +83,9 @@
     /**
      * Displays help on the console
      */
-    public static void showHelp() {
+    private void showHelp() {
         System.out.println(getHelp());
+        System.exit(0);
     }
 
     private static String getHelp() {
Index: src/org/openstreetmap/josm/gui/ProgramArguments.java
===================================================================
--- src/org/openstreetmap/josm/gui/ProgramArguments.java	(Revision 14351)
+++ src/org/openstreetmap/josm/gui/ProgramArguments.java	(Arbeitskopie)
@@ -2,6 +2,7 @@
 package org.openstreetmap.josm.gui;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumMap;
@@ -13,12 +14,10 @@
 import java.util.logging.Level;
 import java.util.stream.Stream;
 
-import org.openstreetmap.josm.tools.I18n;
 import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.OptionParser;
+import org.openstreetmap.josm.tools.OptionParser.OptionCount;
 
-import gnu.getopt.Getopt;
-import gnu.getopt.LongOpt;
-
 /**
  * This class holds the arguments passed on to {@link MainApplication#main}.
  * @author Michael Zangl
@@ -90,10 +89,6 @@
         public boolean requiresArgument() {
             return requiresArg;
         }
-
-        LongOpt toLongOpt() {
-            return new LongOpt(getName(), requiresArgument() ? LongOpt.REQUIRED_ARGUMENT : LongOpt.NO_ARGUMENT, null, 0);
-        }
     }
 
     private final Map<Option, List<String>> argMap = new EnumMap<>(Option.class);
@@ -113,34 +108,23 @@
      * @param args command-line arguments array
      */
     private void buildCommandLineArgumentMap(String... args) {
-        Getopt.setI18nHandler(I18n::tr);
-        LongOpt[] los = Stream.of(Option.values()).map(Option::toLongOpt).toArray(LongOpt[]::new);
-        Getopt g = new Getopt("JOSM", args, "hv", los);
-
-        int c;
-        while ((c = g.getopt()) != -1) {
-            Option opt;
-            switch (c) {
-            case 'h':
-                opt = Option.HELP;
-                break;
-            case 'v':
-                opt = Option.VERSION;
-                break;
-            case 0:
-                opt = Option.values()[g.getLongind()];
-                break;
-            default:
-                opt = null;
+        OptionParser parser = new OptionParser("JOSM");
+        for (Option o : Option.values()) {
+            if (o.requiresArgument()) {
+                parser.addArgumentParameter(o.getName(), OptionCount.MULTIPLE, p -> addOption(o, p));
+            } else {
+                parser.addFlagParameter(o.getName(), () -> addOption(o, ""));
             }
-            if (opt != null) {
-                addOption(opt, g.getOptarg());
-            } else
-                throw new IllegalArgumentException("Invalid option: "+ (char) c);
         }
+
+        parser.addShortAlias(Option.HELP.getName(), "h");
+        parser.addShortAlias(Option.VERSION.getName(), "v");
+
+        List<String> remaining = parser.parseOptionsOrExit(Arrays.asList(args));
+
         // positional arguments are a shortcut for the --download ... option
-        for (int i = g.getOptind(); i < args.length; ++i) {
-            addOption(Option.DOWNLOAD, args[i]);
+        for (String arg : remaining) {
+            addOption(Option.DOWNLOAD, arg);
         }
     }
 
Index: src/org/openstreetmap/josm/gui/mappaint/RenderingCLI.java
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/RenderingCLI.java	(Revision 14351)
+++ src/org/openstreetmap/josm/gui/mappaint/RenderingCLI.java	(Arbeitskopie)
@@ -11,6 +11,7 @@
 import java.nio.file.Files;
 import java.nio.file.Paths;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Locale;
 import java.util.Optional;
@@ -37,14 +38,13 @@
 import org.openstreetmap.josm.io.OsmReader;
 import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.spi.preferences.MemoryPreferences;
-import org.openstreetmap.josm.tools.I18n;
 import org.openstreetmap.josm.tools.JosmDecimalFormatSymbolsProvider;
 import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.OptionParser;
+import org.openstreetmap.josm.tools.OptionParser.OptionCount;
+import org.openstreetmap.josm.tools.OptionParser.OptionParseException;
 import org.openstreetmap.josm.tools.RightAndLefthandTraffic;
 
-import gnu.getopt.Getopt;
-import gnu.getopt.LongOpt;
-
 /**
  * Command line interface for rendering osm data to an image file.
  *
@@ -76,24 +76,13 @@
     private String argProjection;
     private Integer argMaxImageSize;
 
+    private StyleData argCurrentStyle;
+
     private enum Option {
-        HELP(false, 'h'),
-        DEBUG(false, '*'),
-        TRACE(false, '*'),
-        INPUT(true, 'i'),
-        STYLE(true, 's'),
-        SETTING(true, '*'),
-        OUTPUT(true, 'o'),
-        ZOOM(true, 'z'),
-        SCALE(true, '*'),
-        BOUNDS(true, 'b'),
-        ANCHOR(true, '*'),
-        WIDTH_M(true, '*'),
-        HEIGHT_M(true, '*'),
-        WIDTH_PX(true, '*'),
-        HEIGHT_PX(true, '*'),
-        PROJECTION(true, '*'),
-        MAX_IMAGE_SIZE(true, '*');
+        HELP(false, 'h'), DEBUG(false, '*'), TRACE(false, '*'), INPUT(true, 'i'), STYLE(true, 's'), SETTING(true,
+                '*'), OUTPUT(true, 'o'), ZOOM(true, 'z'), SCALE(true, '*'), BOUNDS(true, 'b'), ANCHOR(true,
+                        '*'), WIDTH_M(true, '*'), HEIGHT_M(true, '*'), WIDTH_PX(true,
+                                '*'), HEIGHT_PX(true, '*'), PROJECTION(true, '*'), MAX_IMAGE_SIZE(true, '*');
 
         private final String name;
         private final boolean requiresArg;
@@ -128,10 +117,6 @@
         public char getShortOption() {
             return shortOption;
         }
-
-        LongOpt toLongOpt() {
-            return new LongOpt(getName(), requiresArgument() ? LongOpt.REQUIRED_ARGUMENT : LongOpt.NO_ARGUMENT, null, getShortOption());
-        }
     }
 
     /**
@@ -187,170 +172,182 @@
      * @param argArray the arguments array
      */
     void parseArguments(String[] argArray) {
-        Getopt.setI18nHandler(I18n::tr);
         Logging.setLogLevel(Level.INFO);
 
-        LongOpt[] opts = new LongOpt[Option.values().length];
-        StringBuilder optString = new StringBuilder();
+        OptionParser parser = new OptionParser("JOSM rendering");
         for (Option o : Option.values()) {
-            opts[o.ordinal()] = o.toLongOpt();
+            if (o.requiresArgument()) {
+                parser.addArgumentParameter(o.getName(),
+                        o == Option.SETTING ? OptionCount.MULTIPLE : OptionCount.OPTIONAL,
+                        arg -> handleOption(o, arg));
+            } else {
+                parser.addFlagParameter(o.getName(), () -> handleOption(o));
+            }
             if (o.getShortOption() != '*') {
-                optString.append(o.getShortOption());
-                if (o.requiresArgument()) {
-                    optString.append(':');
-                }
+                parser.addShortAlias(o.getName(), o.getShortOption() + "");
             }
         }
 
-        Getopt getopt = new Getopt("JOSM rendering", argArray, optString.toString(), opts);
-
-        StyleData currentStyle = new StyleData();
+        argCurrentStyle = new StyleData();
         argStyles = new ArrayList<>();
 
-        int c;
-        while ((c = getopt.getopt()) != -1) {
-            switch (c) {
-            case 'h':
-                showHelp();
-                System.exit(0);
-            case 'i':
-                argInput = getopt.getOptarg();
-                break;
-            case 's':
-                if (currentStyle.styleUrl != null) {
-                    argStyles.add(currentStyle);
-                    currentStyle = new StyleData();
-                }
-                currentStyle.styleUrl = getopt.getOptarg();
-                break;
-            case 'o':
-                argOutput = getopt.getOptarg();
-                break;
-            case 'z':
+        parser.parseOptionsOrExit(Arrays.asList(argArray));
+
+        if (argCurrentStyle.styleUrl != null) {
+            argStyles.add(argCurrentStyle);
+        }
+    }
+
+    private void handleOption(Option o) {
+        switch (o) {
+        case HELP:
+            showHelp();
+            System.exit(0);
+            break;
+        case DEBUG:
+            argDebug = true;
+            break;
+        case TRACE:
+            argTrace = true;
+            break;
+        default:
+            throw new AssertionError("Unexpected option index: " + o);
+        }
+    }
+
+    private void handleOption(Option o, String arg) {
+        switch (o) {
+        case INPUT:
+            argInput = arg;
+            break;
+        case STYLE:
+            if (argCurrentStyle.styleUrl != null) {
+                argStyles.add(argCurrentStyle);
+                argCurrentStyle = new StyleData();
+            }
+            argCurrentStyle.styleUrl = arg;
+            break;
+        case OUTPUT:
+            argOutput = arg;
+            break;
+        case ZOOM:
+            try {
+                argZoom = Integer.valueOf(arg);
+            } catch (NumberFormatException nfe) {
+                throw new OptionParseException(
+                        tr("Expected integer number for option {0}, but got ''{1}''", "--zoom", arg), nfe);
+            }
+            if (argZoom < 0) {
+                throw new OptionParseException(
+                        tr("Expected integer number >= 0 for option {0}, but got ''{1}''", "--zoom", arg));
+            }
+            break;
+        case BOUNDS:
+            if (!"auto".equals(arg)) {
                 try {
-                    argZoom = Integer.valueOf(getopt.getOptarg());
-                } catch (NumberFormatException nfe) {
-                    throw new IllegalArgumentException(
-                            tr("Expected integer number for option {0}, but got ''{1}''", "--zoom", getopt.getOptarg()), nfe);
+                    argBounds = new Bounds(arg, ",", Bounds.ParseMethod.LEFT_BOTTOM_RIGHT_TOP, false);
+                } catch (IllegalArgumentException iae) { // NOPMD
+                    throw new OptionParseException(
+                            tr("Unable to parse {0} parameter: {1}", "--bounds", iae.getMessage()), iae);
                 }
-                if (argZoom < 0)
-                    throw new IllegalArgumentException(
-                            tr("Expected integer number >= 0 for option {0}, but got ''{1}''", "--zoom", getopt.getOptarg()));
-                break;
-            case 'b':
-                if (!"auto".equals(getopt.getOptarg())) {
-                    try {
-                        argBounds = new Bounds(getopt.getOptarg(), ",", Bounds.ParseMethod.LEFT_BOTTOM_RIGHT_TOP, false);
-                    } catch (IllegalArgumentException iae) { // NOPMD
-                        throw new IllegalArgumentException(tr("Unable to parse {0} parameter: {1}", "--bounds", iae.getMessage()), iae);
-                    }
-                }
-                break;
-            case '*':
-                switch (Option.values()[getopt.getLongind()]) {
-                case DEBUG:
-                    argDebug = true;
-                    break;
-                case TRACE:
-                    argTrace = true;
-                    break;
-                case SETTING:
-                    String keyval = getopt.getOptarg();
-                    String[] comp = keyval.split(":");
-                    if (comp.length != 2)
-                        throw new IllegalArgumentException(
-                                tr("Expected key and value, separated by '':'' character for option {0}, but got ''{1}''",
-                                        "--setting", getopt.getOptarg()));
-                    currentStyle.settings.put(comp[0].trim(), comp[1].trim());
-                    break;
-                case SCALE:
-                    try {
-                        argScale = JosmDecimalFormatSymbolsProvider.parseDouble(getopt.getOptarg());
-                    } catch (NumberFormatException nfe) {
-                        throw new IllegalArgumentException(
-                                tr("Expected floating point number for option {0}, but got ''{1}''", "--scale", getopt.getOptarg()), nfe);
-                    }
-                    break;
-                case ANCHOR:
-                    String[] parts = getopt.getOptarg().split(",");
-                    if (parts.length != 2)
-                        throw new IllegalArgumentException(
-                                tr("Expected two coordinates, separated by comma, for option {0}, but got ''{1}''",
-                                "--anchor", getopt.getOptarg()));
-                    try {
-                        double lon = LatLonParser.parseCoordinate(parts[0]);
-                        double lat = LatLonParser.parseCoordinate(parts[1]);
-                        argAnchor = new LatLon(lat, lon);
-                    } catch (IllegalArgumentException iae) { // NOPMD
-                        throw new IllegalArgumentException(tr("In option {0}: {1}", "--anchor", iae.getMessage()), iae);
-                    }
-                    break;
-                case WIDTH_M:
-                    try {
-                        argWidthM = JosmDecimalFormatSymbolsProvider.parseDouble(getopt.getOptarg());
-                    } catch (NumberFormatException nfe) {
-                        throw new IllegalArgumentException(
-                                tr("Expected floating point number for option {0}, but got ''{1}''", "--width-m", getopt.getOptarg()), nfe);
-                    }
-                    if (argWidthM <= 0) throw new IllegalArgumentException(
-                            tr("Expected floating point number > 0 for option {0}, but got ''{1}''", "--width-m", getopt.getOptarg()));
-                    break;
-                case HEIGHT_M:
-                    try {
-                        argHeightM = JosmDecimalFormatSymbolsProvider.parseDouble(getopt.getOptarg());
-                    } catch (NumberFormatException nfe) {
-                        throw new IllegalArgumentException(
-                                tr("Expected floating point number for option {0}, but got ''{1}''", "--height-m", getopt.getOptarg()), nfe);
-                    }
-                    if (argHeightM <= 0) throw new IllegalArgumentException(
-                            tr("Expected floating point number > 0 for option {0}, but got ''{1}''", "--width-m", getopt.getOptarg()));
-                    break;
-                case WIDTH_PX:
-                    try {
-                        argWidthPx = Integer.valueOf(getopt.getOptarg());
-                    } catch (NumberFormatException nfe) {
-                        throw new IllegalArgumentException(
-                                tr("Expected integer number for option {0}, but got ''{1}''", "--width-px", getopt.getOptarg()), nfe);
-                    }
-                    if (argWidthPx <= 0) throw new IllegalArgumentException(
-                            tr("Expected integer number > 0 for option {0}, but got ''{1}''", "--width-px", getopt.getOptarg()));
-                    break;
-                case HEIGHT_PX:
-                    try {
-                        argHeightPx = Integer.valueOf(getopt.getOptarg());
-                    } catch (NumberFormatException nfe) {
-                        throw new IllegalArgumentException(
-                                tr("Expected integer number for option {0}, but got ''{1}''", "--height-px", getopt.getOptarg()), nfe);
-                    }
-                    if (argHeightPx <= 0) throw new IllegalArgumentException(
-                            tr("Expected integer number > 0 for option {0}, but got ''{1}''", "--height-px", getopt.getOptarg()));
-                    break;
-                case PROJECTION:
-                    argProjection = getopt.getOptarg();
-                    break;
-                case MAX_IMAGE_SIZE:
-                    try {
-                        argMaxImageSize = Integer.valueOf(getopt.getOptarg());
-                    } catch (NumberFormatException nfe) {
-                        throw new IllegalArgumentException(
-                                tr("Expected integer number for option {0}, but got ''{1}''", "--max-image-size", getopt.getOptarg()), nfe);
-                    }
-                    if (argMaxImageSize < 0) throw new IllegalArgumentException(
-                            tr("Expected integer number >= 0 for option {0}, but got ''{1}''", "--max-image-size", getopt.getOptarg()));
-                    break;
-                default:
-                    throw new AssertionError("Unexpected option index: " + getopt.getLongind());
-                }
-                break;
-            case '?':
-                throw new IllegalArgumentException();   // getopt error
-            default:
-                throw new AssertionError("Unrecognized option: " + c);
             }
+            break;
+
+        case SETTING:
+            String keyval = arg;
+            String[] comp = keyval.split(":", 2);
+            if (comp.length != 2) {
+                throw new OptionParseException(
+                        tr("Expected key and value, separated by '':'' character for option {0}, but got ''{1}''",
+                                "--setting", arg));
+            }
+            argCurrentStyle.settings.put(comp[0].trim(), comp[1].trim());
+            break;
+        case SCALE:
+            try {
+                argScale = JosmDecimalFormatSymbolsProvider.parseDouble(arg);
+            } catch (NumberFormatException nfe) {
+                throw new OptionParseException(
+                        tr("Expected floating point number for option {0}, but got ''{1}''", "--scale", arg), nfe);
+            }
+            break;
+        case ANCHOR:
+            String[] parts = arg.split(",");
+            if (parts.length != 2)
+                throw new OptionParseException(
+                        tr("Expected two coordinates, separated by comma, for option {0}, but got ''{1}''", "--anchor",
+                                arg));
+            try {
+                double lon = LatLonParser.parseCoordinate(parts[0]);
+                double lat = LatLonParser.parseCoordinate(parts[1]);
+                argAnchor = new LatLon(lat, lon);
+            } catch (IllegalArgumentException iae) { // NOPMD
+                throw new OptionParseException(tr("In option {0}: {1}", "--anchor", iae.getMessage()), iae);
+            }
+            break;
+        case WIDTH_M:
+            try {
+                argWidthM = JosmDecimalFormatSymbolsProvider.parseDouble(arg);
+            } catch (NumberFormatException nfe) {
+                throw new OptionParseException(
+                        tr("Expected floating point number for option {0}, but got ''{1}''", "--width-m", arg), nfe);
+            }
+            if (argWidthM <= 0)
+                throw new OptionParseException(
+                        tr("Expected floating point number > 0 for option {0}, but got ''{1}''", "--width-m", arg));
+            break;
+        case HEIGHT_M:
+            try {
+                argHeightM = JosmDecimalFormatSymbolsProvider.parseDouble(arg);
+            } catch (NumberFormatException nfe) {
+                throw new OptionParseException(
+                        tr("Expected floating point number for option {0}, but got ''{1}''", "--height-m", arg), nfe);
+            }
+            if (argHeightM <= 0)
+                throw new OptionParseException(
+                        tr("Expected floating point number > 0 for option {0}, but got ''{1}''", "--width-m", arg));
+            break;
+        case WIDTH_PX:
+            try {
+                argWidthPx = Integer.valueOf(arg);
+            } catch (NumberFormatException nfe) {
+                throw new OptionParseException(
+                        tr("Expected integer number for option {0}, but got ''{1}''", "--width-px", arg), nfe);
+            }
+            if (argWidthPx <= 0)
+                throw new OptionParseException(
+                        tr("Expected integer number > 0 for option {0}, but got ''{1}''", "--width-px", arg));
+            break;
+        case HEIGHT_PX:
+            try {
+                argHeightPx = Integer.valueOf(arg);
+            } catch (NumberFormatException nfe) {
+                throw new OptionParseException(
+                        tr("Expected integer number for option {0}, but got ''{1}''", "--height-px", arg), nfe);
+            }
+            if (argHeightPx <= 0) {
+                throw new OptionParseException(
+                        tr("Expected integer number > 0 for option {0}, but got ''{1}''", "--height-px", arg));
+            }
+            break;
+        case PROJECTION:
+            argProjection = arg;
+            break;
+        case MAX_IMAGE_SIZE:
+            try {
+                argMaxImageSize = Integer.valueOf(arg);
+            } catch (NumberFormatException nfe) {
+                throw new OptionParseException(
+                        tr("Expected integer number for option {0}, but got ''{1}''", "--max-image-size", arg), nfe);
+            }
+            if (argMaxImageSize < 0) {
+                throw new OptionParseException(
+                        tr("Expected integer number >= 0 for option {0}, but got ''{1}''", "--max-image-size", arg));
+            }
+            break;
+        default:
+            throw new AssertionError("Unexpected option index: " + o);
         }
-        if (currentStyle.styleUrl != null) {
-            argStyles.add(currentStyle);
-        }
     }
 
     /**
@@ -361,56 +358,59 @@
     }
 
     private static String getHelp() {
-        return tr("JOSM rendering command line interface")+"\n\n"+
-                tr("Usage")+":\n"+
-                "\tjava -jar josm.jar render <options>\n\n"+
-                tr("Description")+":\n"+
-                tr("Renders data and saves the result to an image file.")+"\n\n"+
-                tr("Options")+":\n"+
-                "\t--help|-h                 "+tr("Show this help")+"\n"+
-                "\t--input|-i <file>         "+tr("Input data file name (.osm)")+"\n"+
-                "\t--output|-o <file>        "+tr("Output image file name (.png); defaults to ''{0}''", "out.png")+"\n"+
-                "\t--style|-s <file>         "+tr("Style file to use for rendering (.mapcss or .zip)")+"\n"+
-                "\t                          "+tr("This option can be repeated to load multiple styles.")+"\n"+
-                "\t--setting <key>:<value>   "+tr("Style setting (in JOSM accessible in the style list dialog right click menu)")+"\n"+
-                "\t                          "+tr("Applies to the last style loaded with the {0} option.", "--style")+"\n"+
-                "\t--zoom|-z <lvl>           "+tr("Select zoom level to render. (integer value, 0=entire earth, 18=street level)")+"\n"+
-                "\t--scale <scale>           "+tr("Select the map scale")+"\n"+
-                "\t                          "+tr("A value of 10000 denotes a scale of 1:10000 (1 cm on the map equals 100 m on the ground; "
-                                                + "display resolution: 96 dpi)")+"\n"+
-                "\t                          "+tr("Options {0} and {1} are mutually exclusive.", "--zoom", "--scale")+"\n"+
-                "\t--bounds|-b auto|<min_lon>,<min_lat>,<max_lon>,<max_lat>\n"+
-                "\t                          "+tr("Area to render, default value is ''{0}''", "auto")+"\n"+
-                "\t                          "+tr("With keyword ''{0}'', the downloaded area in the .osm input file will be used (if recorded).",
-                                                     "auto")+"\n"+
-                "\t--anchor <lon>,<lat>      "+tr("Specify bottom left corner of the rendering area")+"\n"+
-                "\t                          "+tr("Used in combination with width and height options to determine the area to render.")+"\n"+
-                "\t--width-m <number>        "+tr("Width of the rendered area, in meter")+"\n"+
-                "\t--height-m <number>       "+tr("Height of the rendered area, in meter")+"\n"+
-                "\t--width-px <number>       "+tr("Width of the target image, in pixel")+"\n"+
-                "\t--height-px <number>      "+tr("Height of the target image, in pixel")+"\n"+
-                "\t--projection <code>       "+tr("Projection to use, default value ''{0}'' (web-Mercator)", "epsg:3857")+"\n"+
-                "\t--max-image-size <number> "+tr("Maximum image width/height in pixel (''{0}'' means no limit), default value: {1}",
-                                                    0, Integer.toString(DEFAULT_MAX_IMAGE_SIZE))+"\n"+
-                "\n"+
-                tr("To specify the rendered area and scale, the options can be combined in various ways")+":\n"+
-                "  * --bounds (--zoom|--scale|--width-px|--height-px)\n"+
-                "  * --anchor (--width-m|--width-px) (--height-m|--height-px) (--zoom|--scale)\n"+
-                "  * --anchor --width-m --height-m (--width-px|--height-px)\n"+
-                "  * --anchor --width-px --height-px (--width-m|--height-m)\n"+
-                tr("If neither ''{0}'' nor ''{1}'' is given, the default value {2} takes effect "
-                        + "and the bounds of the download area in the .osm input file are used.",
-                        "bounds", "anchor", "--bounds=auto")+"\n\n"+
-                tr("Examples")+":\n"+
-                "  java -jar josm.jar render -i data.osm -s style.mapcss -z 16\n"+
-                "  josm render -i data.osm -s style.mapcss --scale 5000\n"+
-                "  josm render -i data.osm -s style.mapcss -z 16 -o image.png\n"+
-                "  josm render -i data.osm -s elemstyles.mapcss --setting hide_icons:false -z 16\n"+
-                "  josm render -i data.osm -s style.mapcss -s another_style.mapcss -z 16 -o image.png\n"+
-                "  josm render -i data.osm -s style.mapcss --bounds 21.151,51.401,21.152,51.402 -z 16\n"+
-                "  josm render -i data.osm -s style.mapcss --anchor 21.151,51.401 --width-m 500 --height-m 300 -z 16\n"+
-                "  josm render -i data.osm -s style.mapcss --anchor 21.151,51.401 --width-m 500 --height-m 300 --width-px 1800\n"+
-                "  josm render -i data.osm -s style.mapcss --scale 5000 --projection epsg:4326\n";
+        return tr("JOSM rendering command line interface") + "\n\n" + tr("Usage") + ":\n"
+                + "\tjava -jar josm.jar render <options>\n\n" + tr("Description") + ":\n"
+                + tr("Renders data and saves the result to an image file.") + "\n\n" + tr("Options") + ":\n"
+                + "\t--help|-h                 " + tr("Show this help") + "\n" + "\t--input|-i <file>         "
+                + tr("Input data file name (.osm)") + "\n" + "\t--output|-o <file>        "
+                + tr("Output image file name (.png); defaults to ''{0}''", "out.png") + "\n"
+                + "\t--style|-s <file>         " + tr("Style file to use for rendering (.mapcss or .zip)") + "\n"
+                + "\t                          " + tr("This option can be repeated to load multiple styles.") + "\n"
+                + "\t--setting <key>:<value>   "
+                + tr("Style setting (in JOSM accessible in the style list dialog right click menu)") + "\n"
+                + "\t                          "
+                + tr("Applies to the last style loaded with the {0} option.", "--style") + "\n"
+                + "\t--zoom|-z <lvl>           "
+                + tr("Select zoom level to render. (integer value, 0=entire earth, 18=street level)") + "\n"
+                + "\t--scale <scale>           " + tr("Select the map scale") + "\n" + "\t                          "
+                + tr("A value of 10000 denotes a scale of 1:10000 (1 cm on the map equals 100 m on the ground; "
+                        + "display resolution: 96 dpi)")
+                + "\n" + "\t                          "
+                + tr("Options {0} and {1} are mutually exclusive.", "--zoom", "--scale") + "\n"
+                + "\t--bounds|-b auto|<min_lon>,<min_lat>,<max_lon>,<max_lat>\n" + "\t                          "
+                + tr("Area to render, default value is ''{0}''", "auto") + "\n" + "\t                          "
+                + tr("With keyword ''{0}'', the downloaded area in the .osm input file will be used (if recorded).",
+                        "auto")
+                + "\n" + "\t--anchor <lon>,<lat>      " + tr("Specify bottom left corner of the rendering area") + "\n"
+                + "\t                          "
+                + tr("Used in combination with width and height options to determine the area to render.") + "\n"
+                + "\t--width-m <number>        " + tr("Width of the rendered area, in meter") + "\n"
+                + "\t--height-m <number>       " + tr("Height of the rendered area, in meter") + "\n"
+                + "\t--width-px <number>       " + tr("Width of the target image, in pixel") + "\n"
+                + "\t--height-px <number>      " + tr("Height of the target image, in pixel") + "\n"
+                + "\t--projection <code>       "
+                + tr("Projection to use, default value ''{0}'' (web-Mercator)", "epsg:3857") + "\n"
+                + "\t--max-image-size <number> "
+                + tr("Maximum image width/height in pixel (''{0}'' means no limit), default value: {1}", 0,
+                        Integer.toString(DEFAULT_MAX_IMAGE_SIZE))
+                + "\n" + "\n"
+                + tr("To specify the rendered area and scale, the options can be combined in various ways") + ":\n"
+                + "  * --bounds (--zoom|--scale|--width-px|--height-px)\n"
+                + "  * --anchor (--width-m|--width-px) (--height-m|--height-px) (--zoom|--scale)\n"
+                + "  * --anchor --width-m --height-m (--width-px|--height-px)\n"
+                + "  * --anchor --width-px --height-px (--width-m|--height-m)\n"
+                + tr("If neither ''{0}'' nor ''{1}'' is given, the default value {2} takes effect "
+                        + "and the bounds of the download area in the .osm input file are used.", "bounds", "anchor",
+                        "--bounds=auto")
+                + "\n\n" + tr("Examples") + ":\n" + "  java -jar josm.jar render -i data.osm -s style.mapcss -z 16\n"
+                + "  josm render -i data.osm -s style.mapcss --scale 5000\n"
+                + "  josm render -i data.osm -s style.mapcss -z 16 -o image.png\n"
+                + "  josm render -i data.osm -s elemstyles.mapcss --setting hide_icons:false -z 16\n"
+                + "  josm render -i data.osm -s style.mapcss -s another_style.mapcss -z 16 -o image.png\n"
+                + "  josm render -i data.osm -s style.mapcss --bounds 21.151,51.401,21.152,51.402 -z 16\n"
+                + "  josm render -i data.osm -s style.mapcss --anchor 21.151,51.401 --width-m 500 --height-m 300 -z 16\n"
+                + "  josm render -i data.osm -s style.mapcss --anchor 21.151,51.401 --width-m 500 --height-m 300 --width-px 1800\n"
+                + "  josm render -i data.osm -s style.mapcss --scale 5000 --projection epsg:4326\n";
     }
 
     /**
@@ -451,7 +451,8 @@
         Projection proj = ProjectionRegistry.getProjection();
         Double scale = null; // scale in east-north units per pixel
         if (argZoom != null) {
-            scale = OsmMercator.EARTH_RADIUS * Math.PI * 2 / Math.pow(2, argZoom) / OsmMercator.DEFAUL_TILE_SIZE / proj.getMetersPerUnit();
+            scale = OsmMercator.EARTH_RADIUS * Math.PI * 2 / Math.pow(2, argZoom) / OsmMercator.DEFAUL_TILE_SIZE
+                    / proj.getMetersPerUnit();
         }
         Bounds bounds = argBounds;
         ProjectionBounds pb = null;
@@ -463,8 +464,8 @@
                 double enPerMeter = Double.NaN;
                 DoubleSupplier getEnPerMeter = () -> {
                     double shiftMeter = 10;
-                    EastNorth projAnchorShifted = projAnchor.add(
-                            shiftMeter / proj.getMetersPerUnit(), shiftMeter / proj.getMetersPerUnit());
+                    EastNorth projAnchorShifted = projAnchor.add(shiftMeter / proj.getMetersPerUnit(),
+                            shiftMeter / proj.getMetersPerUnit());
                     LatLon anchorShifted = proj.eastNorth2latlon(projAnchorShifted);
                     return projAnchor.distance(projAnchorShifted) / argAnchor.greatCircleDistance(anchorShifted);
                 };
@@ -481,7 +482,8 @@
                         scale = argHeightM / argHeightPx * enPerMeter;
                     } else {
                         throw new IllegalArgumentException(
-                                tr("Argument {0} given, but scale cannot be determined from remaining arguments", "--anchor"));
+                                tr("Argument {0} given, but scale cannot be determined from remaining arguments",
+                                        "--anchor"));
                     }
                 }
 
@@ -516,7 +518,8 @@
                 bounds.extend(proj.eastNorth2latlon(pb.getMax()));
             } else {
                 if (ds.getDataSourceBounds().isEmpty()) {
-                    throw new IllegalArgumentException(tr("{0} mode, but no bounds found in osm data input file", "--bounds=auto"));
+                    throw new IllegalArgumentException(
+                            tr("{0} mode, but no bounds found in osm data input file", "--bounds=auto"));
                 }
                 bounds = ds.getDataSourceBounds().get(0);
             }
@@ -530,7 +533,8 @@
 
         if (scale == null) {
             if (argScale != null) {
-                double enPerMeter = pb.getMin().distance(pb.getMax()) / bounds.getMin().greatCircleDistance(bounds.getMax());
+                double enPerMeter = pb.getMin().distance(pb.getMax())
+                        / bounds.getMin().greatCircleDistance(bounds.getMax());
                 scale = argScale * enPerMeter / PIXEL_PER_METER;
             } else if (argWidthPx != null) {
                 scale = (pb.maxEast - pb.minEast) / argWidthPx;
@@ -538,8 +542,8 @@
                 scale = (pb.maxNorth - pb.minNorth) / argHeightPx;
             } else {
                 throw new IllegalArgumentException(
-                        tr("Unable to determine scale, one of the options {0}, {1}, {2} or {3} expected",
-                                "--zoom", "--scale", "--width-px", "--height-px"));
+                        tr("Unable to determine scale, one of the options {0}, {1}, {2} or {3} expected", "--zoom",
+                                "--scale", "--width-px", "--height-px"));
             }
         }
 
Index: src/org/openstreetmap/josm/tools/OptionParser.java
===================================================================
--- src/org/openstreetmap/josm/tools/OptionParser.java	(nicht existent)
+++ src/org/openstreetmap/josm/tools/OptionParser.java	(Arbeitskopie)
@@ -0,0 +1,328 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.tools;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+/**
+ * A replacement of getopt.
+ * <p>
+ * Allows parsing command line options
+ *
+ * @author Michael Zangl
+ */
+public class OptionParser {
+
+    private HashMap<String, AvailableOption> availableOptions = new HashMap<>();
+    private final String program;
+
+    /**
+     * Create a new option parser.
+     * @param program The program name.
+     */
+    public OptionParser(String program) {
+        Objects.requireNonNull(program, "program name must be provided");
+        this.program = program;
+    }
+
+    /**
+     * Adds an alias for the long option --optionName to the short version -name
+     * @param optionName The long option
+     * @param shortName The short version
+      * @return this {@link OptionParser}
+    */
+    public OptionParser addShortAlias(String optionName, String shortName) {
+        if (!shortName.matches("\\w")) {
+            throw new IllegalArgumentException("Short name " + shortName + " must be one character");
+        }
+        if (availableOptions.containsKey("-" + shortName)) {
+            throw new IllegalArgumentException("Short name " + shortName + " is already used");
+        }
+        AvailableOption longDefinition = availableOptions.get("--" + optionName);
+        if (longDefinition == null) {
+            throw new IllegalArgumentException("No long definition for " + optionName
+                    + " was defined. Define the long definition first before creating " + "a short definition for it.");
+        }
+        availableOptions.put("-" + shortName, longDefinition);
+        return this;
+    }
+
+    /**
+     * Adds an option that may be used as a flag, e.g. --debug
+     * @param optionName The parameter name
+     * @param handler The handler that is called when the flag is encountered.
+     * @return this {@link OptionParser}
+     */
+    public OptionParser addFlagParameter(String optionName, Runnable handler) {
+        checkOptionName(optionName);
+        availableOptions.put("--" + optionName, new AvailableOption() {
+            @Override
+            public void runFor(String parameter) {
+                handler.run();
+            }
+        });
+        return this;
+    }
+
+    private void checkOptionName(String optionName) {
+        if (!optionName.matches("\\w([\\w-]*\\w)?")) {
+            throw new IllegalArgumentException("Illegal option name: " + optionName);
+        }
+        if (availableOptions.containsKey("--" + optionName)) {
+            throw new IllegalArgumentException("The option --" + optionName + " is already registered");
+        }
+    }
+
+    /**
+     * Add a parameter that expects a string attribute. E.g.: --config=/path/to/file
+     * @param optionName The name of the parameter.
+     * @param count The number of times the parameter may occur.
+     * @param handler A function that gets the current object and the parameter. It should throw an {@link OptionParseException} if the parameter cannot be handled / is invalid.
+     * @return this {@link OptionParser}
+     */
+    public OptionParser addArgumentParameter(String optionName, OptionCount count, Consumer<String> handler) {
+        checkOptionName(optionName);
+        availableOptions.put("--" + optionName, new AvailableOption() {
+            @Override
+            public boolean requiresParameter() {
+                return true;
+            }
+
+            @Override
+            public OptionCount getRequiredCount() {
+                return count;
+            }
+
+            @Override
+            public void runFor(String parameter) {
+                Objects.requireNonNull(parameter, "parameter");
+                handler.accept(parameter);
+            }
+        });
+        return this;
+    }
+
+    /**
+     * Same as {@link #parseOptions(List)}, but exits if option parsing fails.
+     * @param arguments The options
+     * @return The remaining program arguments that are no options.
+     */
+    public List<String> parseOptionsOrExit(List<String> arguments) {
+        try {
+            return parseOptions(arguments);
+        } catch (OptionParseException e) {
+            System.err.println(e.getLocalizedMessage());
+            System.exit(1);
+            // unreachable, but makes compilers happy
+            throw e;
+        }
+    }
+
+    /**
+     * Parses the options.
+     * <p>
+     * It first checks if all required options are present, if all options are known and validates the option count.
+     * <p>
+     * Then, all option handlers are called in the order in which the options are encountered.
+     * @param arguments Program arguments
+     * @return The remaining program arguments that are no options.
+     * @throws OptionParseException The error to display if option parsing failed.
+     */
+    public List<String> parseOptions(List<String> arguments) {
+        LinkedList<String> toHandle = new LinkedList<>(arguments);
+        List<String> remainingArguments = new LinkedList<>();
+        boolean argumentOnlyMode = false;
+        List<FoundOption> options = new LinkedList<>();
+
+        while (!toHandle.isEmpty()) {
+            String next = toHandle.removeFirst();
+            if (argumentOnlyMode || !next.matches("-.+")) {
+                // argument found, add it to arguments list
+                remainingArguments.add(next);
+            } else if ("--".equals(next)) {
+                // we are done, the remaining should be used as arguments.
+                argumentOnlyMode = true;
+            } else {
+                if (next.matches("-\\w\\w+")) {
+                    // special case: concatenated short options like -hv
+                    // We handle them as if the user wrote -h -v by just scheduling the remainder for the next loop.
+                    toHandle.addFirst("-" + next.substring(2));
+                    next = next.substring(0, 2);
+                }
+
+                String[] split = next.split("=", 2);
+                String optionName = split[0];
+                AvailableOption definition = findParameter(optionName);
+                String parameter = null;
+                if (definition.requiresParameter()) {
+                    if (split.length > 1) {
+                        parameter = split[1];
+                    } else {
+                        if (toHandle.isEmpty() || toHandle.getFirst().equals("--")) {
+                            throw new OptionParseException(tr("{0}: option ''{1}'' requires an argument", program));
+                        }
+                        parameter = toHandle.removeFirst();
+                    }
+                } else if (split.length > 1) {
+                    throw new OptionParseException(
+                            tr("{0}: option ''{1}'' does not allow an argument", program, optionName));
+                }
+                options.add(new FoundOption(optionName, definition, parameter));
+            }
+        }
+
+        // Count how often they are used
+        availableOptions.values().stream().distinct().forEach(def -> {
+            long count = options.stream().filter(p -> def.equals(p.option)).count();
+            if (count < def.getRequiredCount().min) {
+                // min may be 0 or 1 at the moment
+                throw new OptionParseException(tr("{0}: option ''{1}'' is required"));
+            } else if (count > def.getRequiredCount().max) {
+                // max may be 1 or MAX_INT at the moment
+                throw new OptionParseException(tr("{0}: option ''{1}'' may not appear multiple times"));
+            }
+        });
+
+        // Actually apply the parameters.
+        for (FoundOption option : options) {
+            try {
+                option.option.runFor(option.parameter);
+            } catch (OptionParseException e) {
+                String message;
+                // Just add a nicer error message
+                if (option.parameter == null) {
+                    message = tr("{0}: Error while handling option ''{1}''", program, option.optionName);
+                } else {
+                    message = tr("{0}: Invalid value {2} for option ''{1}''", program, option.optionName,
+                            option.parameter);
+                }
+                if (!e.getLocalizedMessage().isEmpty()) {
+                    message += ": " + e.getLocalizedMessage().isEmpty();
+                }
+                throw new OptionParseException(message);
+            }
+        }
+        return remainingArguments;
+    }
+
+    private AvailableOption findParameter(String optionName) {
+        AvailableOption exactMatch = availableOptions.get(optionName);
+        if (exactMatch != null) {
+            return exactMatch;
+        } else if (optionName.startsWith("--")) {
+            List<AvailableOption> alternatives = availableOptions.entrySet().stream()
+                    .filter(entry -> entry.getKey().startsWith(optionName)).map(Entry::getValue).distinct()
+                    .collect(Collectors.toList());
+
+            if (alternatives.size() == 1) {
+                return alternatives.get(0);
+            } else if (alternatives.size() > 1) {
+                throw new OptionParseException(tr("{0}: option ''{1}'' is ambiguous", program));
+            }
+        }
+        throw new OptionParseException(tr("{0}: unrecognized option ''{1}''", program, optionName));
+    }
+
+    /**
+     * How often an option may / must be specified on the command line.
+     * @author Michael Zangl
+     */
+    public enum OptionCount {
+        /**
+         * The option may be specified once
+         */
+        OPTIONAL(0, 1),
+        /**
+         * The option is required exactly once
+         */
+        REQUIRED(1, 1),
+        /**
+         * The option may be specified multiple times
+         */
+        MULTIPLE(0, Integer.MAX_VALUE);
+
+        private int min;
+        private int max;
+
+        OptionCount(int min, int max) {
+            this.min = min;
+            this.max = max;
+
+        }
+    }
+
+    protected abstract class AvailableOption {
+
+        public boolean requiresParameter() {
+            return false;
+        }
+
+        public OptionCount getRequiredCount() {
+            return OptionCount.OPTIONAL;
+        }
+
+        /**
+         * Called once if the parameter is encountered, afer basic validation.
+         * @param parameter The parameter if {@link #requiresParameter()} is true, <code>null</code> otherwise.
+         */
+        public abstract void runFor(String parameter);
+
+    }
+
+    private static class FoundOption {
+        private final String optionName;
+        private final AvailableOption option;
+        private final String parameter;
+
+        FoundOption(String optionName, AvailableOption option, String parameter) {
+            this.optionName = optionName;
+            this.option = option;
+            this.parameter = parameter;
+        }
+    }
+
+    /**
+     * @author Michael Zangl
+     */
+    public static class OptionParseException extends RuntimeException {
+        // Don't rely on JAVA handling this correctly.
+        private final String localizedMessage;
+
+        /**
+         * Create an empty error with no description
+         */
+        public OptionParseException() {
+            super();
+            localizedMessage = "";
+        }
+
+        /**
+         * @param localizedMessage
+         */
+        public OptionParseException(String localizedMessage) {
+            super(localizedMessage);
+            this.localizedMessage = localizedMessage;
+        }
+
+        /**
+         * @param localizedMessage
+         * @param t
+         */
+        public OptionParseException(String localizedMessage, Throwable t) {
+            super(localizedMessage, t);
+            this.localizedMessage = localizedMessage;
+        }
+
+        @Override
+        public String getLocalizedMessage() {
+            return localizedMessage;
+        }
+    }
+}
Index: test/unit/org/openstreetmap/josm/tools/OptionParserTest.java
===================================================================
--- test/unit/org/openstreetmap/josm/tools/OptionParserTest.java	(nicht existent)
+++ test/unit/org/openstreetmap/josm/tools/OptionParserTest.java	(Arbeitskopie)
@@ -0,0 +1,367 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.tools;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.junit.Test;
+import org.openstreetmap.josm.tools.OptionParser.OptionParseException;
+import org.openstreetmap.josm.tools.OptionParser.OptionCount;
+
+/**
+ * Test for {@link OptionParser}
+ * @author Michael Zangl
+ */
+public class OptionParserTest {
+
+    // A reason for moving to jupter...
+    @Test(expected = OptionParseException.class)
+    public void testEmptyParserRejectsLongopt() {
+        new OptionParser("test").parseOptions(Arrays.asList("--long"));
+    }
+
+    @Test(expected = OptionParseException.class)
+    public void testEmptyParserRejectsShortopt() {
+        new OptionParser("test").parseOptions(Arrays.asList("-s"));
+    }
+
+    @Test(expected = OptionParseException.class)
+    public void testParserRejectsWrongShortopt() {
+        new OptionParser("test").addFlagParameter("test", this::nop).addShortAlias("test", "t")
+                .parseOptions(Arrays.asList("-s"));
+    }
+
+    @Test(expected = OptionParseException.class)
+    public void testParserRejectsWrongLongopt() {
+        new OptionParser("test").addFlagParameter("test", this::nop).parseOptions(Arrays.asList("--wrong"));
+    }
+
+    @Test
+    public void testparserOption() {
+        AtomicReference<String> argFound = new AtomicReference<>();
+        OptionParser parser = new OptionParser("test")
+                .addArgumentParameter("test", OptionCount.REQUIRED, argFound::set);
+
+        parser.parseOptions(Arrays.asList("--test", "arg"));
+        assertEquals("arg", argFound.get());
+    }
+
+    @Test(expected = OptionParseException.class)
+    public void testparserOptionFailsIfMissing() {
+        AtomicReference<String> argFound = new AtomicReference<>();
+        OptionParser parser = new OptionParser("test")
+                .addArgumentParameter("test", OptionCount.REQUIRED, argFound::set);
+
+        parser.parseOptions(Arrays.asList("--test2", "arg"));
+    }
+
+    @Test(expected = OptionParseException.class)
+    public void testparserOptionFailsIfMissingArgument() {
+        AtomicReference<String> argFound = new AtomicReference<>();
+        OptionParser parser = new OptionParser("test")
+                .addArgumentParameter("test", OptionCount.REQUIRED, argFound::set);
+
+        parser.parseOptions(Arrays.asList("--test2", "--other"));
+    }
+
+    @Test(expected = OptionParseException.class)
+    public void testparserOptionFailsIfMissing2() {
+        AtomicReference<String> argFound = new AtomicReference<>();
+        OptionParser parser = new OptionParser("test")
+                .addArgumentParameter("test", OptionCount.REQUIRED, argFound::set);
+
+        parser.parseOptions(Arrays.asList("--", "--test", "arg"));
+    }
+
+    @Test(expected = OptionParseException.class)
+    public void testparserOptionFailsIfTwice() {
+        AtomicReference<String> argFound = new AtomicReference<>();
+        OptionParser parser = new OptionParser("test")
+                .addArgumentParameter("test", OptionCount.REQUIRED, argFound::set);
+
+        parser.parseOptions(Arrays.asList("--test", "arg", "--test", "arg"));
+    }
+
+    @Test(expected = OptionParseException.class)
+    public void testparserOptionFailsIfTwiceForAlias() {
+        AtomicReference<String> argFound = new AtomicReference<>();
+        OptionParser parser = new OptionParser("test")
+                .addArgumentParameter("test", OptionCount.REQUIRED, argFound::set)
+                .addShortAlias("test", "t");
+
+        parser.parseOptions(Arrays.asList("--test", "arg", "-t", "arg"));
+    }
+
+    @Test(expected = OptionParseException.class)
+    public void testOptionalOptionFailsIfTwice() {
+        OptionParser parser = new OptionParser("test")
+                .addFlagParameter("test", this::nop);
+        parser.parseOptions(Arrays.asList("--test", "--test"));
+    }
+
+    @Test(expected = OptionParseException.class)
+    public void testOptionalOptionFailsIfTwiceForAlias() {
+        OptionParser parser = new OptionParser("test")
+                .addFlagParameter("test", this::nop)
+                .addShortAlias("test", "t");
+        parser.parseOptions(Arrays.asList("-t", "-t"));
+    }
+
+    @Test(expected = OptionParseException.class)
+    public void testOptionalOptionFailsIfTwiceForAlias2() {
+        OptionParser parser = new OptionParser("test")
+                .addFlagParameter("test", this::nop)
+                .addShortAlias("test", "t");
+        parser.parseOptions(Arrays.asList("-tt"));
+    }
+
+    @Test
+    public void testLongArgumentsUsingEqualSign() {
+        AtomicReference<String> argFound = new AtomicReference<>();
+        OptionParser parser = new OptionParser("test")
+                .addArgumentParameter("test", OptionCount.REQUIRED, argFound::set);
+
+        List<String> remaining = parser.parseOptions(Arrays.asList("--test=arg", "value"));
+
+        assertEquals(Arrays.asList("value"), remaining);
+        assertEquals("arg", argFound.get());
+
+        remaining = parser.parseOptions(Arrays.asList("--test=", "value"));
+
+        assertEquals(Arrays.asList("value"), remaining);
+        assertEquals("", argFound.get());
+
+        remaining = parser.parseOptions(Arrays.asList("--test=with space and=equals", "value"));
+
+        assertEquals(Arrays.asList("value"), remaining);
+        assertEquals("with space and=equals", argFound.get());
+    }
+
+    @Test(expected = OptionParseException.class)
+    public void testLongArgumentsMissingOption() {
+        OptionParser parser = new OptionParser("test")
+                .addArgumentParameter("test", OptionCount.REQUIRED, this::nop);
+
+        parser.parseOptions(Arrays.asList("--test"));
+    }
+
+    @Test(expected = OptionParseException.class)
+    public void testLongArgumentsMissingOption2() {
+        OptionParser parser = new OptionParser("test")
+                .addArgumentParameter("test", OptionCount.REQUIRED, this::nop);
+
+        parser.parseOptions(Arrays.asList("--test", "--", "x"));
+    }
+
+
+    @Test(expected = OptionParseException.class)
+    public void testShortArgumentsMissingOption() {
+        OptionParser parser = new OptionParser("test")
+                .addArgumentParameter("test", OptionCount.REQUIRED, this::nop)
+                .addShortAlias("test", "t");
+
+        parser.parseOptions(Arrays.asList("-t"));
+    }
+
+    @Test(expected = OptionParseException.class)
+    public void testShortArgumentsMissingOption2() {
+        OptionParser parser = new OptionParser("test")
+                .addArgumentParameter("test", OptionCount.REQUIRED, this::nop)
+                .addShortAlias("test", "t");
+
+        parser.parseOptions(Arrays.asList("-t", "--", "x"));
+    }
+
+    @Test(expected = OptionParseException.class)
+    public void testLongFlagHasOption() {
+        OptionParser parser = new OptionParser("test")
+                .addFlagParameter("test", this::nop);
+
+        parser.parseOptions(Arrays.asList("--test=arg"));
+    }
+
+    @Test(expected = OptionParseException.class)
+    public void testShortFlagHasOption() {
+        OptionParser parser = new OptionParser("test")
+                .addFlagParameter("test", this::nop)
+                .addShortAlias("test", "t");
+
+        parser.parseOptions(Arrays.asList("-t=arg"));
+    }
+
+    @Test
+    public void testShortArgumentsUsingEqualSign() {
+        AtomicReference<String> argFound = new AtomicReference<>();
+        OptionParser parser = new OptionParser("test")
+                .addArgumentParameter("test", OptionCount.REQUIRED, argFound::set)
+                .addShortAlias("test", "t");
+
+        List<String> remaining = parser.parseOptions(Arrays.asList("-t=arg", "value"));
+
+        assertEquals(Arrays.asList("value"), remaining);
+        assertEquals("arg", argFound.get());
+    }
+
+    @Test
+    public void testMultipleArguments() {
+        AtomicReference<String> argFound = new AtomicReference<>();
+        List<String> multiFound = new ArrayList<>();
+        AtomicBoolean usedFlag = new AtomicBoolean();
+        AtomicBoolean unusedFlag = new AtomicBoolean();
+        OptionParser parser = new OptionParser("test")
+                .addArgumentParameter("test", OptionCount.REQUIRED, argFound::set)
+                .addShortAlias("test", "t")
+                .addArgumentParameter("multi", OptionCount.MULTIPLE, multiFound::add)
+                .addFlagParameter("flag", () -> usedFlag.set(true))
+                .addFlagParameter("flag2", () -> unusedFlag.set(true));
+
+        List<String> remaining = parser.parseOptions(Arrays.asList("-t=arg", "--multi", "m1", "x1", "--flag", "--multi", "m2", "x2", "--", "x3", "--x4", "x5"));
+
+        assertEquals(Arrays.asList("x1", "x2", "x3", "--x4", "x5"), remaining);
+        assertEquals("arg", argFound.get());
+        assertEquals(Arrays.asList("m1", "m2"), multiFound);
+        assertEquals(true, usedFlag.get());
+        assertEquals(false, unusedFlag.get());
+    }
+
+    @Test
+    public void testUseAlternatives() {
+        AtomicReference<String> argFound = new AtomicReference<>();
+        AtomicBoolean usedFlag = new AtomicBoolean();
+        AtomicBoolean unusedFlag = new AtomicBoolean();
+
+        OptionParser parser = new OptionParser("test")
+                .addArgumentParameter("test", OptionCount.REQUIRED, argFound::set)
+                .addFlagParameter("flag", () -> usedFlag.set(true))
+                .addFlagParameter("fleg", () -> unusedFlag.set(true));
+
+        List<String> remaining = parser.parseOptions(Arrays.asList("--te=arg", "--fla"));
+
+        assertEquals(Arrays.asList(), remaining);
+        assertEquals("arg", argFound.get());
+        assertEquals(true, usedFlag.get());
+        assertEquals(false, unusedFlag.get());
+    }
+
+    @Test(expected = OptionParseException.class)
+    public void testAbigiousAlternatives() {
+        AtomicReference<String> argFound = new AtomicReference<>();
+        AtomicBoolean usedFlag = new AtomicBoolean();
+        AtomicBoolean unusedFlag = new AtomicBoolean();
+
+        OptionParser parser = new OptionParser("test")
+                .addArgumentParameter("test", OptionCount.REQUIRED, argFound::set)
+                .addFlagParameter("flag", () -> usedFlag.set(true))
+                .addFlagParameter("fleg", () -> unusedFlag.set(true));
+
+        parser.parseOptions(Arrays.asList("--te=arg", "--fl"));
+    }
+
+    @Test(expected = OptionParseException.class)
+    public void testMultipleShort() {
+        AtomicReference<String> argFound = new AtomicReference<>();
+        AtomicBoolean usedFlag = new AtomicBoolean();
+        AtomicBoolean unusedFlag = new AtomicBoolean();
+
+        OptionParser parser = new OptionParser("test")
+                .addArgumentParameter("test", OptionCount.REQUIRED, argFound::set)
+                .addShortAlias("test", "t")
+                .addFlagParameter("flag", () -> usedFlag.set(true))
+                .addShortAlias("flag", "f")
+                .addFlagParameter("fleg", () -> unusedFlag.set(true));
+
+        List<String> remaining = parser.parseOptions(Arrays.asList("-ft=arg", "x"));
+
+        assertEquals(Arrays.asList("x"), remaining);
+        assertEquals("arg", argFound.get());
+        assertEquals(true, usedFlag.get());
+        assertEquals(false, unusedFlag.get());
+
+        remaining = parser.parseOptions(Arrays.asList("-ft", "arg", "x"));
+
+        assertEquals(Arrays.asList("x"), remaining);
+        assertEquals("arg", argFound.get());
+        assertEquals(true, usedFlag.get());
+        assertEquals(false, unusedFlag.get());
+
+        remaining = parser.parseOptions(Arrays.asList("-f", "-t=arg", "x"));
+
+        assertEquals(Arrays.asList("x"), remaining);
+        assertEquals("arg", argFound.get());
+        assertEquals(true, usedFlag.get());
+        assertEquals(false, unusedFlag.get());
+    }
+
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testIllegalOptionName() {
+        new OptionParser("test").addFlagParameter("", this::nop);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testIllegalOptionName2() {
+        new OptionParser("test").addFlagParameter("-", this::nop);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testIllegalOptionName3() {
+        new OptionParser("test").addFlagParameter("-test", this::nop);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testIllegalOptionName4() {
+        new OptionParser("test").addFlagParameter("$", this::nop);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testDupplicateOptionName() {
+        new OptionParser("test").addFlagParameter("test", this::nop).addFlagParameter("test", this::nop);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testDupplicateOptionName2() {
+        new OptionParser("test").addFlagParameter("test", this::nop)
+        .addArgumentParameter("test", OptionCount.OPTIONAL,  this::nop);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidShortAlias() {
+        new OptionParser("test").addFlagParameter("test", this::nop).addShortAlias("test", "$");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidShortAlias2() {
+        new OptionParser("test").addFlagParameter("test", this::nop).addShortAlias("test", "");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidShortAlias3() {
+        new OptionParser("test").addFlagParameter("test", this::nop).addShortAlias("test", "xx");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testDupplicateShortAlias() {
+        new OptionParser("test").addFlagParameter("test", this::nop)
+        .addFlagParameter("test2", this::nop)
+        .addShortAlias("test", "t")
+        .addShortAlias("test2", "t");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidShortNoLong() {
+        new OptionParser("test").addFlagParameter("test", this::nop).addShortAlias("test2", "t");
+    }
+
+    private void nop() {
+        // nop
+    }
+
+    private void nop(String arg) {
+        // nop
+    }
+}
