/* 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 gnu.java.lang.CPStringBuilder;

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 out 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(CPStringBuilder 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 CPStringBuilder 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 CPStringBuilder(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;

    CPStringBuilder 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
  {
    CPStringBuilder 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(CPStringBuilder 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);

    CPStringBuilder result = new CPStringBuilder();
    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 format 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();
  }
}
