/* 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 StringBuilder 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");

  /**
   * 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(StringBuilder 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(StringBuilder app, Locale loc)
  {
    this.out = app == null ? new StringBuilder() : app;
    this.locale = 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;
    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();
  }

  /**
   * 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.ZERO) != 0
	&& (flags & FormattableFlags.LEFT_JUSTIFY) == 0)
      throw new IllegalFormatFlagsException(getName(flags));
    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)).intValue();
  }

  /**
   * 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 StringBuilder 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();
  }
}
