/* Formatter.java -- printf-style formatting
   Copyright (C) 2005 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
 
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.util;

import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.Flushable;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.text.DateFormatSymbols;
import java.text.DecimalFormatSymbols;

import gnu.classpath.SystemProperties;

/** 
 * <p>
 * A Java formatter for <code>printf</code>-style format strings,
 * as seen in the C programming language.   This differs from the
 * C interpretation of such strings by performing much stricter
 * checking of format specifications and their corresponding
 * arguments.  While unknown conversions will be ignored in C,
 * and invalid conversions will only produce compiler warnings,
 * the Java version utilises a full range of run-time exceptions to
 * handle these cases.  The Java version is also more customisable
 * by virtue of the provision of the {@link Formattable} interface,
 * which allows an arbitrary class to be formatted by the formatter.
 * </p>
 * <p>
 * The formatter is accessible by more convienient static methods.
 * For example, streams now have appropriate format methods
 * (the equivalent of <code>fprintf</code>) as do <code>String</code>
 * objects (the equivalent of <code>sprintf</code>).
 * </p>
 * <p>
 * <strong>Note</strong>: the formatter is not thread-safe.  For
 * multi-threaded access, external synchronization should be provided.
 * </p>
 *  
 * @author Tom Tromey (tromey@redhat.com)
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 * @since 1.5 
 */
public final class Formatter 
  implements Closeable, Flushable
{

  /**
   * The output of the formatter.
   */
  private Appendable out;

  /**
   * The locale used by the formatter.
   */
  private Locale locale;

  /**
   * Whether or not the formatter is closed.
   */
  private boolean closed;

  /**
   * The last I/O exception thrown by the output stream.
   */
  private IOException ioException;

  // Some state used when actually formatting.
  /**
   * The format string.
   */
  private String format;

  /**
   * The current index into the string.
   */
  private int index;

  /**
   * The length of the format string.
   */
  private int length;

  /**
   * The formatting locale.
   */
  private Locale fmtLocale;

  // Note that we include '-' twice.  The flags are ordered to
  // correspond to the values in FormattableFlags, and there is no
  // flag (in the sense of this field used when parsing) for
  // UPPERCASE; the second '-' serves as a placeholder.
  /**
   * A string used to index into the formattable flags.
   */
  private static final String FLAGS = "--#+ 0,(";

  /**
   * The system line separator.
   */
  private static final String lineSeparator
    = SystemProperties.getProperty("line.separator");

  /**
   * The type of numeric output format for a {@link BigDecimal}.
   */
  public enum BigDecimalLayoutForm
  {
    DECIMAL_FLOAT,
    SCIENTIFIC
  }

  /**
   * Constructs a new <code>Formatter</code> using the default
   * locale and a {@link StringBuilder} as the output stream.
   */
  public Formatter()
  {
    this(null, Locale.getDefault());
  }

  /**
   * Constructs a new <code>Formatter</code> using the specified
   * locale and a {@link StringBuilder} as the output stream.
   * If the locale is <code>null</code>, then no localization
   * is applied.
   *
   * @param loc the locale to use.
   */
  public Formatter(Locale loc)
  {
    this(null, loc);
  }

  /**
   * Constructs a new <code>Formatter</code> using the default
   * locale and the specified output stream.
   *
   * @param app the output stream to use.
   */
  public Formatter(Appendable app)
  {
    this(app, Locale.getDefault());
  }

  /**
   * Constructs a new <code>Formatter</code> using the specified
   * locale and the specified output stream.  If the locale is
   * <code>null</code>, then no localization is applied.
   *
   * @param app the output stream to use.
   * @param loc the locale to use.
   */
  public Formatter(Appendable app, Locale loc)
  {
    this.out = app == null ? new StringBuilder() : app;
    this.locale = loc;
  }

  /**
   * Constructs a new <code>Formatter</code> using the default
   * locale and character set, with the specified file as the
   * output stream.
   *
   * @param file the file to use for output.
   * @throws FileNotFoundException if the file does not exist
   *                               and can not be created.
   * @throws SecurityException if a security manager is present
   *                           and doesn't allow writing to the file.
   */
  public Formatter(File file) 
    throws FileNotFoundException
  {
    this(new OutputStreamWriter(new FileOutputStream(file)));
  }

  /**
   * Constructs a new <code>Formatter</code> using the default
   * locale, with the specified file as the output stream
   * and the supplied character set.
   *
   * @param file the file to use for output.
   * @param charset the character set to use for output.
   * @throws FileNotFoundException if the file does not exist
   *                               and can not be created.
   * @throws SecurityException if a security manager is present
   *                           and doesn't allow writing to the file.
   * @throws UnsupportedEncodingException if the supplied character
   *                                      set is not supported.
   */
  public Formatter(File file, String charset)
    throws FileNotFoundException, UnsupportedEncodingException
  {
    this(file, charset, Locale.getDefault());
  }

  /**
   * Constructs a new <code>Formatter</code> using the specified
   * file as the output stream with the supplied character set
   * and locale.  If the locale is <code>null</code>, then no
   * localization is applied.
   *
   * @param file the file to use for output.
   * @param charset the character set to use for output.
   * @param loc the locale to use.
   * @throws FileNotFoundException if the file does not exist
   *                               and can not be created.
   * @throws SecurityException if a security manager is present
   *                           and doesn't allow writing to the file.
   * @throws UnsupportedEncodingException if the supplied character
   *                                      set is not supported.
   */
  public Formatter(File file, String charset, Locale loc)
    throws FileNotFoundException, UnsupportedEncodingException
  {
    this(new OutputStreamWriter(new FileOutputStream(file), charset),
	 loc);
  }

  /**
   * Constructs a new <code>Formatter</code> using the default
   * locale and character set, with the specified output stream.
   *
   * @param out the output stream to use.
   */
  public Formatter(OutputStream out)
  {
    this(new OutputStreamWriter(out));
  }

  /**
   * Constructs a new <code>Formatter</code> using the default
   * locale, with the specified file output stream and the
   * supplied character set.
   *
   * @param out the output stream.
   * @param charset the character set to use for output.
   * @throws UnsupportedEncodingException if the supplied character
   *                                      set is not supported.
   */
  public Formatter(OutputStream out, String charset)
    throws UnsupportedEncodingException
  {
    this(out, charset, Locale.getDefault());
  }

  /**
   * Constructs a new <code>Formatter</code> using the specified
   * output stream with the supplied character set and locale.
   * If the locale is <code>null</code>, then no localization is
   * applied.
   *
   * @param file the output stream.
   * @param charset the character set to use for output.
   * @param loc the locale to use.
   * @throws UnsupportedEncodingException if the supplied character
   *                                      set is not supported.
   */
  public Formatter(OutputStream out, String charset, Locale loc)
    throws UnsupportedEncodingException
  {
    this(new OutputStreamWriter(out, charset), loc);
  }

  /**
   * Constructs a new <code>Formatter</code> using the default
   * locale with the specified output stream.  The character
   * set used is that of the output stream.
   *
   * @param out the output stream to use.
   */
  public Formatter(PrintStream out)
  {
    this((Appendable) out);
  }

  /**
   * Constructs a new <code>Formatter</code> using the default
   * locale and character set, with the specified file as the
   * output stream.
   *
   * @param file the file to use for output.
   * @throws FileNotFoundException if the file does not exist
   *                               and can not be created.
   * @throws SecurityException if a security manager is present
   *                           and doesn't allow writing to the file.
   */
  public Formatter(String file) throws FileNotFoundException
  {
    this(new OutputStreamWriter(new FileOutputStream(file)));
  }

  /**
   * Constructs a new <code>Formatter</code> using the default
   * locale, with the specified file as the output stream
   * and the supplied character set.
   *
   * @param file the file to use for output.
   * @param charset the character set to use for output.
   * @throws FileNotFoundException if the file does not exist
   *                               and can not be created.
   * @throws SecurityException if a security manager is present
   *                           and doesn't allow writing to the file.
   * @throws UnsupportedEncodingException if the supplied character
   *                                      set is not supported.
   */
  public Formatter(String file, String charset)
    throws FileNotFoundException, UnsupportedEncodingException
  {
    this(file, charset, Locale.getDefault());
  }

  /**
   * Constructs a new <code>Formatter</code> using the specified
   * file as the output stream with the supplied character set
   * and locale.  If the locale is <code>null</code>, then no
   * localization is applied.
   *
   * @param file the file to use for output.
   * @param charset the character set to use for output.
   * @param loc the locale to use.
   * @throws FileNotFoundException if the file does not exist
   *                               and can not be created.
   * @throws SecurityException if a security manager is present
   *                           and doesn't allow writing to the file.
   * @throws UnsupportedEncodingException if the supplied character
   *                                      set is not supported.
   */
  public Formatter(String file, String charset, Locale loc)
    throws FileNotFoundException, UnsupportedEncodingException
  {
    this(new OutputStreamWriter(new FileOutputStream(file), charset),
	 loc);
  }

  /**
   * Closes the formatter, so as to release used resources.
   * If the underlying output stream supports the {@link Closeable}
   * interface, then this is also closed.  Attempts to use
   * a formatter instance, via any method other than
   * {@link #ioException()}, after closure results in a
   * {@link FormatterClosedException}.
   */
  public void close()
  {
    if (closed)
      return;
    try
      {
	if (out instanceof Closeable)
	  ((Closeable) out).close();
      }
    catch (IOException _)
      {
	// FIXME: do we ignore these or do we set ioException?
	// The docs seem to indicate that we should ignore.
      }
    closed = true;
  }

  /**
   * Flushes the formatter, writing any cached data to the output
   * stream.  If the underlying output stream supports the
   * {@link Flushable} interface, it is also flushed.
   *
   * @throws FormatterClosedException if the formatter is closed.
   */
  public void flush()
  {
    if (closed)
      throw new FormatterClosedException();
    try
      {
	if (out instanceof Flushable)
	  ((Flushable) out).flush();
      }
    catch (IOException _)
      {
	// FIXME: do we ignore these or do we set ioException?
	// The docs seem to indicate that we should ignore.
      }
  }

  /**
   * Return the name corresponding to a flag.
   *
   * @param flags the flag to return the name of.
   * @return the name of the flag.
   */
  private String getName(int flags)
  {
    // FIXME: do we want all the flags in here?
    // Or should we redo how this is reported?
    int bit = Integer.numberOfTrailingZeros(flags);
    return FLAGS.substring(bit, bit + 1);
  }

  /**
   * Verify the flags passed to a conversion.
   *
   * @param flags the flags to verify.
   * @param allowed the allowed flags mask.
   * @param conversion the conversion character.
   */
  private void checkFlags(int flags, int allowed, char conversion)
  {
    flags &= ~allowed;
    if (flags != 0)
      throw new FormatFlagsConversionMismatchException(getName(flags),
						       conversion);
  }

  /**
   * Throw an exception if a precision was specified.
   *
   * @param precision the precision value (-1 indicates not specified).
   */
  private void noPrecision(int precision)
  {
    if (precision != -1)
      throw new IllegalFormatPrecisionException(precision);
  }

  /**
   * Apply the numeric localization algorithm to a StringBuilder.
   *
   * @param builder the builder to apply to.
   * @param flags the formatting flags to use.
   * @param width the width of the numeric value.
   * @param isNegative true if the value is negative.
   */
  private void applyLocalization(StringBuilder builder, int flags, int width,
				 boolean isNegative)
  {
    DecimalFormatSymbols dfsyms;
    if (fmtLocale == null)
      dfsyms = new DecimalFormatSymbols();
    else
      dfsyms = new DecimalFormatSymbols(fmtLocale);

    // First replace each digit.
    char zeroDigit = dfsyms.getZeroDigit();
    int decimalOffset = -1;
    for (int i = builder.length() - 1; i >= 0; --i)
      {
	char c = builder.charAt(i);
	if (c >= '0' && c <= '9')
	  builder.setCharAt(i, (char) (c - '0' + zeroDigit));
	else if (c == '.')
	  {
	    assert decimalOffset == -1;
	    decimalOffset = i;
	  }
      }

    // Localize the decimal separator.
    if (decimalOffset != -1)
      {
	builder.deleteCharAt(decimalOffset);
	builder.insert(decimalOffset, dfsyms.getDecimalSeparator());
      }
	
    // Insert the grouping separators.
    if ((flags & FormattableFlags.COMMA) != 0)
      {
	char groupSeparator = dfsyms.getGroupingSeparator();
	int groupSize = 3;	// FIXME
	int offset = (decimalOffset == -1) ? builder.length() : decimalOffset;
	// We use '>' because we don't want to insert a separator
	// before the first digit.
	for (int i = offset - groupSize; i > 0; i -= groupSize)
	  builder.insert(i, groupSeparator);
      }

    if ((flags & FormattableFlags.ZERO) != 0)
      {
	// Zero fill.  Note that according to the algorithm we do not
	// insert grouping separators here.
	for (int i = width - builder.length(); i > 0; --i)
	  builder.insert(0, zeroDigit);
      }

    if (isNegative)
      {
	if ((flags & FormattableFlags.PAREN) != 0)
	  {
	    builder.insert(0, '(');
	    builder.append(')');
	  }
	else
	  builder.insert(0, '-');
      }
    else if ((flags & FormattableFlags.PLUS) != 0)
      builder.insert(0, '+');
    else if ((flags & FormattableFlags.SPACE) != 0)
      builder.insert(0, ' ');
  }

  /**
   * A helper method that handles emitting a String after applying
   * precision, width, justification, and upper case flags.
   *
   * @param arg the string to emit.
   * @param flags the formatting flags to use.
   * @param width the width to use.
   * @param precision the precision to use.
   * @throws IOException if the output stream throws an I/O error.
   */
  private void genericFormat(String arg, int flags, int width, int precision)
    throws IOException
  {
    if ((flags & FormattableFlags.UPPERCASE) != 0)
      {
	if (fmtLocale == null)
	  arg = arg.toUpperCase();
	else
	  arg = arg.toUpperCase(fmtLocale);
      }

    if (precision >= 0 && arg.length() > precision)
      arg = arg.substring(0, precision);

    boolean leftJustify = (flags & FormattableFlags.LEFT_JUSTIFY) != 0;
    if (leftJustify && width == -1)
      throw new MissingFormatWidthException("fixme");
    if (! leftJustify && arg.length() < width)
      {
	for (int i = width - arg.length(); i > 0; --i)
	  out.append(' ');
      }
    out.append(arg);
    if (leftJustify && arg.length() < width)
      {
	for (int i = width - arg.length(); i > 0; --i)
	  out.append(' ');
      }
  }

  /** 
   * Emit a boolean.  
   *
   * @param arg the boolean to emit.
   * @param flags the formatting flags to use.
   * @param width the width to use.
   * @param precision the precision to use.
   * @param conversion the conversion character.
   * @throws IOException if the output stream throws an I/O error.
   */
  private void booleanFormat(Object arg, int flags, int width, int precision,
			     char conversion)
    throws IOException
  {
    checkFlags(flags,
	       FormattableFlags.LEFT_JUSTIFY | FormattableFlags.UPPERCASE,
	       conversion);
    String result;
    if (arg instanceof Boolean)
      result = String.valueOf((Boolean) arg);
    else
      result = arg == null ? "false" : "true";
    genericFormat(result, flags, width, precision);
  }

  /** 
   * Emit a hash code.  
   *
   * @param arg the hash code to emit.
   * @param flags the formatting flags to use.
   * @param width the width to use.
   * @param precision the precision to use.
   * @param conversion the conversion character.
   * @throws IOException if the output stream throws an I/O error.
   */
  private void hashCodeFormat(Object arg, int flags, int width, int precision,
			      char conversion)
    throws IOException
  {
    checkFlags(flags,
	       FormattableFlags.LEFT_JUSTIFY | FormattableFlags.UPPERCASE,
	       conversion);
    genericFormat(arg == null ? "null" : Integer.toHexString(arg.hashCode()),
		  flags, width, precision);
  }

  /** 
   * Emit a String or Formattable conversion.  
   *
   * @param arg the String or Formattable to emit.
   * @param flags the formatting flags to use.
   * @param width the width to use.
   * @param precision the precision to use.
   * @param conversion the conversion character.
   * @throws IOException if the output stream throws an I/O error.
   */
  private void stringFormat(Object arg, int flags, int width, int precision,
			    char conversion)
    throws IOException
  {
    if (arg instanceof Formattable)
      {
	checkFlags(flags,
		   (FormattableFlags.LEFT_JUSTIFY
		    | FormattableFlags.UPPERCASE
		    | FormattableFlags.ALTERNATE),
		   conversion);
	Formattable fmt = (Formattable) arg;
	fmt.formatTo(this, flags, width, precision);
      }
    else
      {
	checkFlags(flags,
		   FormattableFlags.LEFT_JUSTIFY | FormattableFlags.UPPERCASE,
		   conversion);
	genericFormat(arg == null ? "null" : arg.toString(), flags, width,
		      precision);
      }
  }

  /** 
   * Emit a character.  
   *
   * @param arg the character to emit.
   * @param flags the formatting flags to use.
   * @param width the width to use.
   * @param precision the precision to use.
   * @param conversion the conversion character.
   * @throws IOException if the output stream throws an I/O error.
   */
  private void characterFormat(Object arg, int flags, int width, int precision,
			       char conversion)
    throws IOException
  {
    checkFlags(flags,
	       FormattableFlags.LEFT_JUSTIFY | FormattableFlags.UPPERCASE,
	       conversion);
    noPrecision(precision);

    int theChar;
    if (arg instanceof Character)
      theChar = ((Character) arg).charValue();
    else if (arg instanceof Byte)
      theChar = (char) (((Byte) arg).byteValue ());
    else if (arg instanceof Short)
      theChar = (char) (((Short) arg).shortValue ());
    else if (arg instanceof Integer)
      {
	theChar = ((Integer) arg).intValue();
	if (! Character.isValidCodePoint(theChar))
	  throw new IllegalFormatCodePointException(theChar);
      }
    else
      throw new IllegalFormatConversionException(conversion, arg.getClass());
    String result = new String(Character.toChars(theChar));
    genericFormat(result, flags, width, precision);
  }

  /** 
   * Emit a '%'.
   *
   * @param flags the formatting flags to use.
   * @param width the width to use.
   * @param precision the precision to use.
   * @throws IOException if the output stream throws an I/O error.
   */
  private void percentFormat(int flags, int width, int precision)
    throws IOException
  {
    checkFlags(flags, FormattableFlags.LEFT_JUSTIFY, '%');
    noPrecision(precision);
    genericFormat("%", flags, width, precision);
  }

  /** 
   * Emit a newline.
   *
   * @param flags the formatting flags to use.
   * @param width the width to use.
   * @param precision the precision to use.
   * @throws IOException if the output stream throws an I/O error.
   */
  private void newLineFormat(int flags, int width, int precision)
    throws IOException
  {
    checkFlags(flags, 0, 'n');
    noPrecision(precision);
    if (width != -1)
      throw new IllegalFormatWidthException(width);
    genericFormat(lineSeparator, flags, width, precision);
  }

  /**
   * Helper method to do initial formatting and checking for integral
   * conversions.
   *
   * @param arg the formatted argument.
   * @param flags the formatting flags to use.
   * @param width the width to use.
   * @param precision the precision to use.
   * @param radix the radix of the number.
   * @param conversion the conversion character.
   * @return the result.
   */
  private StringBuilder basicIntegralConversion(Object arg, int flags,
						int width, int precision,
						int radix, char conversion)
  {
    assert radix == 8 || radix == 10 || radix == 16;
    noPrecision(precision);

    // Some error checking.
    if ((flags & FormattableFlags.PLUS) != 0
	&& (flags & FormattableFlags.SPACE) != 0)
      throw new IllegalFormatFlagsException(getName(flags));

    if ((flags & FormattableFlags.LEFT_JUSTIFY) != 0 && width == -1)
      throw new MissingFormatWidthException("fixme");

    // Do the base translation of the value to a string.
    String result;
    int basicFlags = (FormattableFlags.LEFT_JUSTIFY
		      // We already handled any possible error when
		      // parsing.
		      | FormattableFlags.UPPERCASE
		      | FormattableFlags.ZERO);
    if (radix == 10)
      basicFlags |= (FormattableFlags.PLUS
		     | FormattableFlags.SPACE
		     | FormattableFlags.COMMA
		     | FormattableFlags.PAREN);
    else
      basicFlags |= FormattableFlags.ALTERNATE;

    if (arg instanceof BigInteger)
      {
	checkFlags(flags,
		   (basicFlags
		    | FormattableFlags.PLUS
		    | FormattableFlags.SPACE
		    | FormattableFlags.PAREN),
		   conversion);
	BigInteger bi = (BigInteger) arg;
	result = bi.toString(radix);
      }
    else if (arg instanceof Number
	     && ! (arg instanceof Float)
	     && ! (arg instanceof Double))
      {
	checkFlags(flags, basicFlags, conversion);
	long value = ((Number) arg).longValue ();
	if (radix == 8)
	  result = Long.toOctalString(value);
	else if (radix == 16)
	  result = Long.toHexString(value);
	else
	  result = Long.toString(value);
      }
    else
      throw new IllegalFormatConversionException(conversion, arg.getClass());

    return new StringBuilder(result);
  }

  /** 
   * Emit a hex or octal value.  
   * 
   * @param arg the hexadecimal or octal value.
   * @param flags the formatting flags to use.
   * @param width the width to use.
   * @param precision the precision to use.
   * @param radix the radix of the number.
   * @param conversion the conversion character.
   * @throws IOException if the output stream throws an I/O error.
   */
  private void hexOrOctalConversion(Object arg, int flags, int width,
				    int precision, int radix,
				    char conversion)
    throws IOException
  {
    assert radix == 8 || radix == 16;

    StringBuilder builder = basicIntegralConversion(arg, flags, width,
						    precision, radix,
						    conversion);
    int insertPoint = 0;

    // Insert the sign.
    if (builder.charAt(0) == '-')
      {
	// Already inserted.  Note that we don't insert a sign, since
	// the only case where it is needed it BigInteger, and it has
	// already been inserted by toString.
	++insertPoint;
      }
    else if ((flags & FormattableFlags.PLUS) != 0)
      {
	builder.insert(insertPoint, '+');
	++insertPoint;
      }
    else if ((flags & FormattableFlags.SPACE) != 0)
      {
	builder.insert(insertPoint, ' ');
	++insertPoint;
      }

    // Insert the radix prefix.
    if ((flags & FormattableFlags.ALTERNATE) != 0)
      {
	builder.insert(insertPoint, radix == 8 ? "0" : "0x");
	insertPoint += radix == 8 ? 1 : 2;
      }

    // Now justify the result.
    int resultWidth = builder.length();
    if (resultWidth < width)
      {
	char fill = ((flags & FormattableFlags.ZERO) != 0) ? '0' : ' ';
	if ((flags & FormattableFlags.LEFT_JUSTIFY) != 0)
	  {
	    // Left justify.  
	    if (fill == ' ')
	      insertPoint = builder.length();
	  }
	else
	  {
	    // Right justify.  Insert spaces before the radix prefix
	    // and sign.
	    insertPoint = 0;
	  }
	while (resultWidth++ < width)
	  builder.insert(insertPoint, fill);
      }

    String result = builder.toString();
    if ((flags & FormattableFlags.UPPERCASE) != 0)
      {
	if (fmtLocale == null)
	  result = result.toUpperCase();
	else
	  result = result.toUpperCase(fmtLocale);
      }

    out.append(result);
  }

  /** 
   * Emit a decimal value.  
   * 
   * @param arg the hexadecimal or octal value.
   * @param flags the formatting flags to use.
   * @param width the width to use.
   * @param precision the precision to use.
   * @param conversion the conversion character.
   * @throws IOException if the output stream throws an I/O error.
   */
  private void decimalConversion(Object arg, int flags, int width,
				 int precision, char conversion)
    throws IOException
  {
    StringBuilder builder = basicIntegralConversion(arg, flags, width,
						    precision, 10,
						    conversion);
    boolean isNegative = false;
    if (builder.charAt(0) == '-')
      {
	// Sign handling is done during localization.
	builder.deleteCharAt(0);
	isNegative = true;
      }

    applyLocalization(builder, flags, width, isNegative);
    genericFormat(builder.toString(), flags, width, precision);
  }

  /** 
   * Emit a single date or time conversion to a StringBuilder.  
   *
   * @param builder the builder to write to.
   * @param cal the calendar to use in the conversion.
   * @param conversion the formatting character to specify the type of data.
   * @param syms the date formatting symbols.
   */
  private void singleDateTimeConversion(StringBuilder builder, Calendar cal,
					char conversion,
					DateFormatSymbols syms)
  {
    int oldLen = builder.length();
    int digits = -1;
    switch (conversion)
      {
      case 'H':
	builder.append(cal.get(Calendar.HOUR_OF_DAY));
	digits = 2;
	break;
      case 'I':
	builder.append(cal.get(Calendar.HOUR));
	digits = 2;
	break;
      case 'k':
	builder.append(cal.get(Calendar.HOUR_OF_DAY));
	break;
      case 'l':
	builder.append(cal.get(Calendar.HOUR));
	break;
      case 'M':
	builder.append(cal.get(Calendar.MINUTE));
	digits = 2;
	break;
      case 'S':
	builder.append(cal.get(Calendar.SECOND));
	digits = 2;
	break;
      case 'N':
	// FIXME: nanosecond ...
	digits = 9;
	break;
      case 'p':
	{
	  int ampm = cal.get(Calendar.AM_PM);
	  builder.append(syms.getAmPmStrings()[ampm]);
	}
	break;
      case 'z':
	{
	  int zone = cal.get(Calendar.ZONE_OFFSET) / (1000 * 60);
	  builder.append(zone);
	  digits = 4;
	  // Skip the '-' sign.
	  if (zone < 0)
	    ++oldLen;
	}
	break;
      case 'Z':
	{
	  // FIXME: DST?
	  int zone = cal.get(Calendar.ZONE_OFFSET) / (1000 * 60 * 60);
	  String[][] zs = syms.getZoneStrings();
	  builder.append(zs[zone + 12][1]);
	}
	break;
      case 's':
	{
	  long val = cal.getTime().getTime();
	  builder.append(val / 1000);
	}
	break;
      case 'Q':
	{
	  long val = cal.getTime().getTime();
	  builder.append(val);
	}
	break;
      case 'B':
	{
	  int month = cal.get(Calendar.MONTH);
	  builder.append(syms.getMonths()[month]);
	}
	break;
      case 'b':
      case 'h':
	{
	  int month = cal.get(Calendar.MONTH);
	  builder.append(syms.getShortMonths()[month]);
	}
	break;
      case 'A':
	{
	  int day = cal.get(Calendar.DAY_OF_WEEK);
	  builder.append(syms.getWeekdays()[day]);
	}
	break;
      case 'a':
	{
	  int day = cal.get(Calendar.DAY_OF_WEEK);
	  builder.append(syms.getShortWeekdays()[day]);
	}
	break;
      case 'C':
	builder.append(cal.get(Calendar.YEAR) / 100);
	digits = 2;
	break;
      case 'Y':
	builder.append(cal.get(Calendar.YEAR));
	digits = 4;
	break;
      case 'y':
	builder.append(cal.get(Calendar.YEAR) % 100);
	digits = 2;
	break;
      case 'j':
	builder.append(cal.get(Calendar.DAY_OF_YEAR));
	digits = 3;
	break;
      case 'm':
	builder.append(cal.get(Calendar.MONTH) + 1);
	digits = 2;
	break;
      case 'd':
	builder.append(cal.get(Calendar.DAY_OF_MONTH));
	digits = 2;
	break;
      case 'e':
	builder.append(cal.get(Calendar.DAY_OF_MONTH));
	break;
      case 'R':
	singleDateTimeConversion(builder, cal, 'H', syms);
	builder.append(':');
	singleDateTimeConversion(builder, cal, 'M', syms);
	break;
      case 'T':
	singleDateTimeConversion(builder, cal, 'H', syms);
	builder.append(':');
	singleDateTimeConversion(builder, cal, 'M', syms);
	builder.append(':');
	singleDateTimeConversion(builder, cal, 'S', syms);
	break;
      case 'r':
	singleDateTimeConversion(builder, cal, 'I', syms);
	builder.append(':');
	singleDateTimeConversion(builder, cal, 'M', syms);
	builder.append(':');
	singleDateTimeConversion(builder, cal, 'S', syms);
	builder.append(' ');
	singleDateTimeConversion(builder, cal, 'p', syms);
	break;
      case 'D':
	singleDateTimeConversion(builder, cal, 'm', syms);
	builder.append('/');
    	singleDateTimeConversion(builder, cal, 'd', syms);
	builder.append('/');
	singleDateTimeConversion(builder, cal, 'y', syms);
	break;
      case 'F':
	singleDateTimeConversion(builder, cal, 'Y', syms);
	builder.append('-');
	singleDateTimeConversion(builder, cal, 'm', syms);
	builder.append('-');
	singleDateTimeConversion(builder, cal, 'd', syms);
	break;
      case 'c':
	singleDateTimeConversion(builder, cal, 'a', syms);
	builder.append(' ');
	singleDateTimeConversion(builder, cal, 'b', syms);
	builder.append(' ');
	singleDateTimeConversion(builder, cal, 'd', syms);
	builder.append(' ');
	singleDateTimeConversion(builder, cal, 'T', syms);
	builder.append(' ');
	singleDateTimeConversion(builder, cal, 'Z', syms);
	builder.append(' ');
	singleDateTimeConversion(builder, cal, 'Y', syms);
	break;
      default:
	throw new UnknownFormatConversionException(String.valueOf(conversion));
      }

    if (digits > 0)
      {
	int newLen = builder.length();
	int delta = newLen - oldLen;
	while (delta++ < digits)
	  builder.insert(oldLen, '0');
      }
  }

  /**
   * Emit a date or time value.
   *
   * @param arg the date or time value.
   * @param flags the formatting flags to use.
   * @param width the width to use.
   * @param precision the precision to use.
   * @param conversion the conversion character.
   * @param subConversion the sub conversion character.
   * @throws IOException if the output stream throws an I/O error.
   */
  private void dateTimeConversion(Object arg, int flags, int width,
				  int precision, char conversion,
				  char subConversion)
    throws IOException
  {
    noPrecision(precision);
    checkFlags(flags,
	       FormattableFlags.LEFT_JUSTIFY | FormattableFlags.UPPERCASE,
	       conversion);

    Calendar cal;
    if (arg instanceof Calendar)
      cal = (Calendar) arg;
    else
      {
	Date date;
	if (arg instanceof Date)
	  date = (Date) arg;
	else if (arg instanceof Long)
	  date = new Date(((Long) arg).longValue());
	else
	  throw new IllegalFormatConversionException(conversion,
						     arg.getClass());
	if (fmtLocale == null)
	  cal = Calendar.getInstance();
	else
	  cal = Calendar.getInstance(fmtLocale);
	cal.setTime(date);
      }

    // We could try to be more efficient by computing this lazily.
    DateFormatSymbols syms;
    if (fmtLocale == null)
      syms = new DateFormatSymbols();
    else
      syms = new DateFormatSymbols(fmtLocale);

    StringBuilder result = new StringBuilder();
    singleDateTimeConversion(result, cal, subConversion, syms);

    genericFormat(result.toString(), flags, width, precision);
  }

  /**
   * Advance the internal parsing index, and throw an exception
   * on overrun.
   *
   * @throws IllegalArgumentException on overrun.
   */
  private void advance()
  {
    ++index;
    if (index >= length)
      {
	// FIXME: what exception here?
	throw new IllegalArgumentException();
      }
  }

  /**
   * Parse an integer appearing in the format string.  Will return -1
   * if no integer was found.
   *
   * @return the parsed integer.
   */
  private int parseInt()
  {
    int start = index;
    while (Character.isDigit(format.charAt(index)))
      advance();
    if (start == index)
      return -1;
    return Integer.decode(format.substring(start, index));
  }

  /**
   * Parse the argument index.  Returns -1 if there was no index, 0 if
   * we should re-use the previous index, and a positive integer to
   * indicate an absolute index.
   *
   * @return the parsed argument index.
   */
  private int parseArgumentIndex()
  {
    int result = -1;
    int start = index;
    if (format.charAt(index) == '<')
      {
	result = 0;
	advance();
      }
    else if (Character.isDigit(format.charAt(index)))
      {
	result = parseInt();
	if (format.charAt(index) == '$')
	  advance();
	else
	  {
	    // Reset.
	    index = start;
	    result = -1;
	  }
      }
    return result;
  }

  /**
   * Parse a set of flags and return a bit mask of values from
   * FormattableFlags.  Will throw an exception if a flag is
   * duplicated.
   *
   * @return the parsed flags.
   */
  private int parseFlags()
  {
    int value = 0;
    int start = index;
    while (true)
      {
	int x = FLAGS.indexOf(format.charAt(index));
	if (x == -1)
	  break;
	int newValue = 1 << x;
	if ((value & newValue) != 0)
	  throw new DuplicateFormatFlagsException(format.substring(start,
								   index + 1));
	value |= newValue;
	advance();
      }
    return value;
  }

  /**
   * Parse the width part of a format string.  Returns -1 if no width
   * was specified.
   *
   * @return the parsed width.
   */
  private int parseWidth()
  {
    return parseInt();
  }

  /**
   * If the current character is '.', parses the precision part of a
   * format string.  Returns -1 if no precision was specified.
   *
   * @return the parsed precision.
   */
  private int parsePrecision()
  {
    if (format.charAt(index) != '.')
      return -1;
    advance();
    int precision = parseInt();
    if (precision == -1)
      // FIXME
      throw new IllegalArgumentException();
    return precision;
  }

  /**
   * Outputs a formatted string based on the supplied specification,
   * <code>fmt</code>, and its arguments using the specified locale.
   * The locale of the formatter does not change as a result; the
   * specified locale is just used for this particular formatting
   * operation.  If the locale is <code>null</code>, then no
   * localization is applied.
   *
   * @param loc the locale to use for this format.
   * @param fmt the format specification.
   * @param args the arguments to apply to the specification.
   * @throws IllegalFormatException if there is a problem with
   *                                the syntax of the format
   *                                specification or a mismatch
   *                                between it and the arguments.
   * @throws FormatterClosedException if the formatter is closed.
   */ 
  public Formatter format(Locale loc, String fmt, Object... args)
  {
    if (closed)
      throw new FormatterClosedException();

    // Note the arguments are indexed starting at 1.
    int implicitArgumentIndex = 1;
    int previousArgumentIndex = 0;

    try
      {
	fmtLocale = loc;
	format = fmt;
	length = format.length();
	for (index = 0; index < length; ++index)
	  {
	    char c = format.charAt(index);
	    if (c != '%')
	      {
		out.append(c);
		continue;
	      }

	    int start = index;
	    advance();

	    // We do the needed post-processing of this later, when we
	    // determine whether an argument is actually needed by
	    // this conversion.
	    int argumentIndex = parseArgumentIndex();

	    int flags = parseFlags();
	    int width = parseWidth();
	    int precision = parsePrecision();
	    char origConversion = format.charAt(index);
	    char conversion = origConversion;
	    if (Character.isUpperCase(conversion))
	      {
		flags |= FormattableFlags.UPPERCASE;
		conversion = Character.toLowerCase(conversion);
	      }

	    Object argument = null;
	    if (conversion == '%' || conversion == 'n')
	      {
		if (argumentIndex != -1)
		  {
		    // FIXME: not sure about this.
		    throw new UnknownFormatConversionException("FIXME");
		  }
	      }
	    else
	      {
		if (argumentIndex == -1)
		  argumentIndex = implicitArgumentIndex++;
		else if (argumentIndex == 0)
		  argumentIndex = previousArgumentIndex;
		// Argument indices start at 1 but array indices at 0.
		--argumentIndex;
		if (argumentIndex < 0 || argumentIndex >= args.length)
		  throw new MissingFormatArgumentException(format.substring(start, index));
		argument = args[argumentIndex];
	      }

	    switch (conversion)
	      {
	      case 'b':
		booleanFormat(argument, flags, width, precision,
			      origConversion);
		break;
	      case 'h':
		hashCodeFormat(argument, flags, width, precision,
			       origConversion);
		break;
	      case 's':
		stringFormat(argument, flags, width, precision,
			     origConversion);
		break;
	      case 'c':
		characterFormat(argument, flags, width, precision,
				origConversion);
		break;
	      case 'd':
		checkFlags(flags & FormattableFlags.UPPERCASE, 0, 'd');
		decimalConversion(argument, flags, width, precision,
				  origConversion);
		break;
	      case 'o':
		checkFlags(flags & FormattableFlags.UPPERCASE, 0, 'o');
		hexOrOctalConversion(argument, flags, width, precision, 8,
				     origConversion);
		break;
	      case 'x':
		hexOrOctalConversion(argument, flags, width, precision, 16,
				     origConversion);
	      case 'e':
		// scientificNotationConversion();
		break;
	      case 'f':
		// floatingDecimalConversion();
		break;
	      case 'g':
		// smartFloatingConversion();
		break;
	      case 'a':
		// hexFloatingConversion();
		break;
	      case 't':
		advance();
		char subConversion = format.charAt(index);
		dateTimeConversion(argument, flags, width, precision,
				   origConversion, subConversion);
		break;
	      case '%':
		percentFormat(flags, width, precision);
		break;
	      case 'n':
		newLineFormat(flags, width, precision);
		break;
	      default:
		throw new UnknownFormatConversionException(String.valueOf(origConversion));
	      }
	  }
      }
    catch (IOException exc)
      {
	ioException = exc;
      }
    return this;
  }

  /**
   * Outputs a formatted string based on the supplied specification,
   * <code>fmt</code>, and its arguments using the formatter's locale.
   *
   * @param fmt the format specification.
   * @param args the arguments to apply to the specification.
   * @throws IllegalFormatException if there is a problem with
   *                                the syntax of the format
   *                                specification or a mismatch
   *                                between it and the arguments.
   * @throws FormatterClosedException if the formatter is closed.
   */
  public Formatter format(String format, Object... args)
  {
    return format(locale, format, args);
  }

  /**
   * Returns the last I/O exception thrown by the
   * <code>append()</code> operation of the underlying
   * output stream.
   *
   * @return the last I/O exception.
   */
  public IOException ioException()
  {
    return ioException;
  }

  /**
   * Returns the locale used by this formatter.
   *
   * @return the formatter's locale.
   * @throws FormatterClosedException if the formatter is closed.
   */
  public Locale locale()
  {
    if (closed)
      throw new FormatterClosedException();
    return locale;
  }

  /**
   * Returns the output stream used by this formatter.
   *
   * @return the formatter's output stream.
   * @throws FormatterClosedException if the formatter is closed.
   */
  public Appendable out()
  {
    if (closed)
      throw new FormatterClosedException();
    return out;
  }

  /**
   * Returns the result of applying {@link Object#toString()}
   * to the underlying output stream.  The results returned
   * depend on the particular {@link Appendable} being used.
   * For example, a {@link StringBuilder} will return the
   * formatted output but an I/O stream will not.
   *
   * @throws FormatterClosedException if the formatter is closed.
   */
  public String toString()
  {
    if (closed)
      throw new FormatterClosedException();
    return out.toString();
  }
}
