View Javadoc

1   /*
2    * Copyright (c) 2003-2008 by Cosylab d. d.
3    *
4    * This file is part of Java-Common.
5    *
6    * Java-Common is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU General Public License as published by
8    * the Free Software Foundation, either version 3 of the License, or
9    * (at your option) any later version.
10   *
11   * Java-Common is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU General Public License for more details.
15   *
16   * You should have received a copy of the GNU General Public License
17   * along with Java-Common.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  
20  package com.cosylab.util;
21  //
22  // (c) 2000 Sun Microsystems, Inc.
23  // ALL RIGHTS RESERVED
24  // 
25  // License Grant-
26  // 
27  // 
28  // Permission to use, copy, modify, and distribute this Software and its 
29  // documentation for NON-COMMERCIAL or COMMERCIAL purposes and without fee is 
30  // hereby granted.  
31  // 
32  // This Software is provided "AS IS".  All express warranties, including any 
33  // implied warranty of merchantability, satisfactory quality, fitness for a 
34  // particular purpose, or non-infringement, are disclaimed, except to the extent 
35  // that such disclaimers are held to be legally invalid.
36  // 
37  // You acknowledge that Software is not designed, licensed or intended for use in 
38  // the design, construction, operation or maintenance of any nuclear facility 
39  // ("High Risk Activities").  Sun disclaims any express or implied warranty of 
40  // fitness for such uses.  
41  //
42  // Please refer to the file http://www.sun.com/policies/trademarks/ for further 
43  // important trademark information and to 
44  // http://java.sun.com/nav/business/index.html for further important licensing 
45  // information for the Java Technology.
46  //
47  
48  import java.text.DecimalFormatSymbols;
49  import java.util.Enumeration;
50  import java.util.Locale;
51  import java.util.Vector;
52  
53  /**
54   * PrintfFormat allows the formatting of an array of
55   * objects embedded within a string.  Primitive types
56   * must be passed using wrapper types.  The formatting
57   * is controlled by a control string.
58   *<p>
59   * A control string is a Java string that contains a
60   * control specification.  The control specification
61   * starts at the first percent sign (%) in the string,
62   * provided that this percent sign
63   *<ol>
64   *<li>is not escaped protected by a matching % or is
65   * not an escape % character,
66   *<li>is not at the end of the format string, and
67   *<li>precedes a sequence of characters that parses as
68   * a valid control specification.
69   *</ol>
70   *</p><p>
71   * A control specification usually takes the form:
72   *<pre> % ['-+ #0]* [0..9]* { . [0..9]* }+
73   *                { [hlL] }+ [idfgGoxXeEcs]
74   *</pre>
75   * There are variants of this basic form that are
76   * discussed below.</p>
77   *<p>
78   * The format is composed of zero or more directives
79   * defined as follows:
80   *<ul>
81   *<li>ordinary characters, which are simply copied to
82   * the output stream;
83   *<li>escape sequences, which represent non-graphic
84   * characters; and
85   *<li>conversion specifications,  each of which
86   * results in the fetching of zero or more arguments.
87   *</ul></p>
88   *<p>
89   * The results are undefined if there are insufficient
90   * arguments for the format.  Usually an unchecked
91   * exception will be thrown.  If the format is
92   * exhausted while arguments remain, the excess
93   * arguments are evaluated but are otherwise ignored.
94   * In format strings containing the % form of
95   * conversion specifications, each argument in the
96   * argument list is used exactly once.</p>
97   * <p>
98   * Conversions can be applied to the <code>n</code>th
99   * argument after the format in the argument list,
100  * rather than to the next unused argument.  In this
101  * case, the conversion characer % is replaced by the
102  * sequence %<code>n</code>$, where <code>n</code> is
103  * a decimal integer giving the position of the
104  * argument in the argument list.</p>
105  * <p>
106  * In format strings containing the %<code>n</code>$
107  * form of conversion specifications, each argument
108  * in the argument list is used exactly once.</p>
109  *
110  *<h4>Escape Sequences</h4>
111  *<p>
112  * The following table lists escape sequences and
113  * associated actions on display devices capable of
114  * the action.
115  *<table>
116  *<tr><th align=left>Sequence</th>
117  *    <th align=left>Name</th>
118  *    <th align=left>Description</th></tr>
119  *<tr><td>\\</td><td>backlash</td><td>None.
120  *</td></tr>
121  *<tr><td>\a</td><td>alert</td><td>Attempts to alert
122  *          the user through audible or visible
123  *          notification.
124  *</td></tr>
125  *<tr><td>\b</td><td>backspace</td><td>Moves the
126  *          printing position to one column before
127  *          the current position, unless the
128  *          current position is the start of a line.
129  *</td></tr>
130  *<tr><td>\f</td><td>form-feed</td><td>Moves the
131  *          printing position to the initial 
132  *          printing position of the next logical
133  *          page.
134  *</td></tr>
135  *<tr><td>\n</td><td>newline</td><td>Moves the
136  *          printing position to the start of the
137  *          next line.
138  *</td></tr>
139  *<tr><td>\r</td><td>carriage-return</td><td>Moves
140  *          the printing position to the start of
141  *          the current line.
142  *</td></tr>
143  *<tr><td>\t</td><td>tab</td><td>Moves the printing
144  *          position to the next implementation-
145  *          defined horizontal tab position.
146  *</td></tr>
147  *<tr><td>\v</td><td>vertical-tab</td><td>Moves the
148  *          printing position to the start of the
149  *          next implementation-defined vertical
150  *          tab position.
151  *</td></tr>
152  *</table></p>
153  *<h4>Conversion Specifications</h4>
154  *<p>
155  * Each conversion specification is introduced by
156  * the percent sign character (%).  After the character
157  * %, the following appear in sequence:</p>
158  *<p>
159  * Zero or more flags (in any order), which modify the
160  * meaning of the conversion specification.</p>
161  *<p>
162  * An optional minimum field width.  If the converted
163  * value has fewer characters than the field width, it
164  * will be padded with spaces by default on the left;
165  * t will be padded on the right, if the left-
166  * adjustment flag (-), described below, is given to
167  * the field width.  The field width takes the form
168  * of a decimal integer.  If the conversion character
169  * is s, the field width is the the minimum number of
170  * characters to be printed.</p>
171  *<p>
172  * An optional precision that gives the minumum number
173  * of digits to appear for the d, i, o, x or X
174  * conversions (the field is padded with leading
175  * zeros); the number of digits to appear after the
176  * radix character for the e, E, and f conversions,
177  * the maximum number of significant digits for the g
178  * and G conversions; or the maximum number of
179  * characters to be written from a string is s and S
180  * conversions.  The precision takes the form of an
181  * optional decimal digit string, where a null digit
182  * string is treated as 0.  If a precision appears
183  * with a c conversion character the precision is
184  * ignored.
185  * </p>
186  *<p>
187  * An optional h specifies that a following d, i, o,
188  * x, or X conversion character applies to a type 
189  * short argument (the argument will be promoted
190  * according to the integral promotions and its value
191  * converted to type short before printing).</p>
192  *<p>
193  * An optional l (ell) specifies that a following
194  * d, i, o, x, or X conversion character applies to a
195  * type long argument.</p>
196  *<p>
197  * A field width or precision may be indicated by an
198  * asterisk (*) instead of a digit string.  In this
199  * case, an integer argument supplised the field width
200  * precision.  The argument that is actually converted
201  * is not fetched until the conversion letter is seen,
202  * so the the arguments specifying field width or
203  * precision must appear before the argument (if any)
204  * to be converted.  If the precision argument is
205  * negative, it will be changed to zero.  A negative
206  * field width argument is taken as a - flag, followed
207  * by a positive field width.</p>
208  * <p>
209  * In format strings containing the %<code>n</code>$
210  * form of a conversion specification, a field width
211  * or precision may be indicated by the sequence
212  * *<code>m</code>$, where m is a decimal integer
213  * giving the position in the argument list (after the
214  * format argument) of an integer argument containing
215  * the field width or precision.</p>
216  * <p>
217  * The format can contain either numbered argument
218  * specifications (that is, %<code>n</code>$ and
219  * *<code>m</code>$), or unnumbered argument
220  * specifications (that is % and *), but normally not
221  * both.  The only exception to this is that %% can
222  * be mixed with the %<code>n</code>$ form.  The
223  * results of mixing numbered and unnumbered argument
224  * specifications in a format string are undefined.</p>
225  *
226  *<h4>Flag Characters</h4>
227  *<p>
228  * The flags and their meanings are:</p>
229  *<dl>
230  * <dt>'<dd> integer portion of the result of a
231  *      decimal conversion (%i, %d, %f, %g, or %G) will
232  *      be formatted with thousands' grouping
233  *      characters.  For other conversions the flag
234  *      is ignored.  The non-monetary grouping
235  *      character is used.
236  * <dt>-<dd> result of the conversion is left-justified
237  *      within the field.  (It will be right-justified
238  *      if this flag is not specified).
239  * <dt>+<dd> result of a signed conversion always
240  *      begins with a sign (+ or -).  (It will begin
241  *      with a sign only when a negative value is
242  *      converted if this flag is not specified.)
243  * <dt>&lt;space&gt;<dd> If the first character of a
244  *      signed conversion is not a sign, a space
245  *      character will be placed before the result.
246  *      This means that if the space character and +
247  *      flags both appear, the space flag will be
248  *      ignored.
249  * <dt>#<dd> value is to be converted to an alternative
250  *      form.  For c, d, i, and s conversions, the flag
251  *      has no effect.  For o conversion, it increases
252  *      the precision to force the first digit of the
253  *      result to be a zero.  For x or X conversion, a
254  *      non-zero result has 0x or 0X prefixed to it,
255  *      respectively.  For e, E, f, g, and G
256  *      conversions, the result always contains a radix
257  *      character, even if no digits follow the radix
258  *      character (normally, a decimal point appears in
259  *      the result of these conversions only if a digit
260  *      follows it).  For g and G conversions, trailing
261  *      zeros will not be removed from the result as
262  *      they normally are.
263  * <dt>0<dd> d, i, o, x, X, e, E, f, g, and G
264  *      conversions, leading zeros (following any
265  *      indication of sign or base) are used to pad to
266  *      the field width;  no space padding is
267  *      performed.  If the 0 and - flags both appear,
268  *      the 0 flag is ignored.  For d, i, o, x, and X
269  *      conversions, if a precision is specified, the
270  *      0 flag will be ignored. For c conversions,
271  *      the flag is ignored.
272  *</dl>
273  *
274  *<h4>Conversion Characters</h4>
275  *<p>
276  * Each conversion character results in fetching zero
277  * or more arguments.  The results are undefined if
278  * there are insufficient arguments for the format.
279  * Usually, an unchecked exception will be thrown.
280  * If the format is exhausted while arguments remain,
281  * the excess arguments are ignored.</p>
282  *
283  *<p>
284  * The conversion characters and their meanings are:
285  *</p>
286  *<dl>
287  * <dt>d,i<dd>The int argument is converted to a
288  *        signed decimal in the style [-]dddd.  The
289  *        precision specifies the minimum number of
290  *        digits to appear;  if the value being
291  *        converted can be represented in fewer
292  *        digits, it will be expanded with leading
293  *        zeros.  The default precision is 1.  The
294  *        result of converting 0 with an explicit
295  *        precision of 0 is no characters.
296  * <dt>o<dd> The int argument is converted to unsigned
297  *        octal format in the style ddddd.  The
298  *        precision specifies the minimum number of
299  *        digits to appear;  if the value being
300  *        converted can be represented in fewer
301  *        digits, it will be expanded with leading
302  *        zeros.  The default precision is 1.  The
303  *        result of converting 0 with an explicit
304  *        precision of 0 is no characters.
305  * <dt>x<dd> The int argument is converted to unsigned
306  *        hexadecimal format in the style dddd;  the
307  *        letters abcdef are used.  The precision
308  *        specifies the minimum numberof digits to
309  *        appear; if the value being converted can be
310  *        represented in fewer digits, it will be
311  *        expanded with leading zeros.  The default
312  *        precision is 1.  The result of converting 0
313  *        with an explicit precision of 0 is no
314  *        characters.
315  * <dt>X<dd> Behaves the same as the x conversion
316  *        character except that letters ABCDEF are
317  *        used instead of abcdef.
318  * <dt>f<dd> The floating point number argument is
319  *        written in decimal notation in the style
320  *        [-]ddd.ddd, where the number of digits after
321  *        the radix character (shown here as a decimal
322  *        point) is equal to the precision
323  *        specification.  A Locale is used to determine
324  *        the radix character to use in this format.
325  *        If the precision is omitted from the
326  *        argument, six digits are written after the
327  *        radix character;  if the precision is
328  *        explicitly 0 and the # flag is not specified,
329  *        no radix character appears.  If a radix
330  *        character appears, at least 1 digit appears
331  *        before it.  The value is rounded to the
332  *        appropriate number of digits.
333  * <dt>e,E<dd>The floating point number argument is
334  *        written in the style [-]d.ddde{+-}dd
335  *        (the symbols {+-} indicate either a plus or
336  *        minus sign), where there is one digit before
337  *        the radix character (shown here as a decimal
338  *        point) and the number of digits after it is
339  *        equal to the precision.  A Locale is used to
340  *        determine the radix character to use in this
341  *        format.  When the precision is missing, six
342  *        digits are written after the radix character;
343  *        if the precision is 0 and the # flag is not
344  *        specified, no radix character appears.  The
345  *        E conversion will produce a number with E
346  *        instead of e introducing the exponent.  The
347  *        exponent always contains at least two digits.
348  *        However, if the value to be written requires
349  *        an exponent greater than two digits,
350  *        additional exponent digits are written as
351  *        necessary.  The value is rounded to the
352  *        appropriate number of digits.
353  * <dt>g,G<dd>The floating point number argument is
354  *        written in style f or e (or in sytle E in the
355  *        case of a G conversion character), with the
356  *        precision specifying the number of
357  *        significant digits.  If the precision is
358  *        zero, it is taken as one.  The style used
359  *        depends on the value converted:  style e
360  *        (or E) will be used only if the exponent
361  *        resulting from the conversion is less than
362  *        -4 or greater than or equal to the precision.
363  *        Trailing zeros are removed from the result.
364  *        A radix character appears only if it is
365  *        followed by a digit.
366  * <dt>c,C<dd>The integer argument is converted to a
367  *        char and the result is written.
368  *
369  * <dt>s,S<dd>The argument is taken to be a string and
370  *        bytes from the string are written until the
371  *        end of the string or the number of bytes 
372  *        indicated by the precision specification of
373  *        the argument is reached.  If the precision
374  *        is omitted from the argument, it is taken to
375  *        be infinite, so all characters up to the end
376  *        of the string are written.
377  * <dt>%<dd>Write a % character;  no argument is
378  *        converted.
379  *</dl>
380  *<p>
381  * If a conversion specification does not match one of
382  * the above forms, an IllegalArgumentException is
383  * thrown and the instance of PrintfFormat is not
384  * created.</p>
385  *<p>
386  * If a floating point value is the internal
387  * representation for infinity, the output is
388  * [+]Infinity, where Infinity is either Infinity or
389  * Inf, depending on the desired output string length.
390  * Printing of the sign follows the rules described
391  * above.</p>
392  *<p>
393  * If a floating point value is the internal
394  * representation for "not-a-number," the output is
395  * [+]NaN.  Printing of the sign follows the rules
396  * described above.</p>
397  *<p>
398  * In no case does a non-existent or small field width
399  * cause truncation of a field;  if the result of a
400  * conversion is wider than the field width, the field
401  * is simply expanded to contain the conversion result.
402  *</p>
403  *<p>
404  * The behavior is like printf.  One exception is that
405  * the minimum number of exponent digits is 3 instead
406  * of 2 for e and E formats when the optional L is used
407  * before the e, E, g, or G conversion character.  The
408  * optional L does not imply conversion to a long long
409  * double. </p>
410  * <p>
411  * The biggest divergence from the C printf
412  * specification is in the use of 16 bit characters.
413  * This allows the handling of characters beyond the
414  * small ASCII character set and allows the utility to
415  * interoperate correctly with the rest of the Java
416  * runtime environment.</p>
417  *<p>
418  * Omissions from the C printf specification are
419  * numerous.  All the known omissions are present
420  * because Java never uses bytes to represent
421  * characters and does not have pointers:</p>
422  *<ul>
423  * <li>%c is the same as %C.
424  * <li>%s is the same as %S.
425  * <li>u, p, and n conversion characters. 
426  * <li>%ws format.
427  * <li>h modifier applied to an n conversion character.
428  * <li>l (ell) modifier applied to the c, n, or s
429  * conversion characters.
430  * <li>ll (ell ell) modifier to d, i, o, u, x, or X
431  * conversion characters.
432  * <li>ll (ell ell) modifier to an n conversion
433  * character.
434  * <li>c, C, d,i,o,u,x, and X conversion characters
435  * apply to Byte, Character, Short, Integer, Long
436  * types.
437  * <li>f, e, E, g, and G conversion characters apply
438  * to Float and Double types.
439  * <li>s and S conversion characters apply to String
440  * types.
441  * <li>All other reference types can be formatted
442  * using the s or S conversion characters only.
443  *</ul>
444  * <p>
445  * Most of this specification is quoted from the Unix
446  * man page for the sprintf utility.</p>
447  *
448  * @author Allan Jacobs
449  * @version 1
450  * Release 1: Initial release.
451  * Release 2: Asterisk field widths and precisions    
452  *            %n$ and *m$
453  *            Bug fixes
454  *              g format fix (2 digits in e form corrupt)
455  *              rounding in f format implemented
456  *              round up when digit not printed is 5
457  *              formatting of -0.0f
458  *              round up/down when last digits are 50000...
459  */
460 public class PrintfFormat {
461 	/**
462 	 * Constructs an array of control specifications
463 	 * possibly preceded, separated, or followed by
464 	 * ordinary strings.  Control strings begin with
465 	 * unpaired percent signs.  A pair of successive
466 	 * percent signs designates a single percent sign in
467 	 * the format.
468 	 * @param fmtArg  Control string.
469 	 * @exception IllegalArgumentException if the control
470 	 * string is null, zero length, or otherwise
471 	 * malformed.
472 	 */
473 	public PrintfFormat(String fmtArg) throws IllegalArgumentException {
474 		this(Locale.getDefault(), fmtArg);
475 	}
476 	/**
477 	 * Constructs an array of control specifications
478 	 * possibly preceded, separated, or followed by
479 	 * ordinary strings.  Control strings begin with
480 	 * unpaired percent signs.  A pair of successive
481 	 * percent signs designates a single percent sign in
482 	 * the format.
483 	 * @param fmtArg  Control string.
484 	 * @exception IllegalArgumentException if the control
485 	 * string is null, zero length, or otherwise
486 	 * malformed.
487 	 */
488 	public PrintfFormat(Locale locale, String fmtArg) throws IllegalArgumentException {
489 		dfs = new DecimalFormatSymbols(locale);
490 		int ePos = 0;
491 		ConversionSpecification sFmt = null;
492 		String unCS = this.nonControl(fmtArg, 0);
493 		if (unCS != null) {
494 			sFmt = new ConversionSpecification();
495 			sFmt.setLiteral(unCS);
496 			vFmt.addElement(sFmt);
497 		}
498 		while (cPos != -1 && cPos < fmtArg.length()) {
499 			for (ePos = cPos + 1; ePos < fmtArg.length(); ePos++) {
500 				char c = 0;
501 				c = fmtArg.charAt(ePos);
502 				if (c == 'i')
503 					break;
504 				if (c == 'd')
505 					break;
506 				if (c == 'f')
507 					break;
508 				if (c == 'g')
509 					break;
510 				if (c == 'G')
511 					break;
512 				if (c == 'o')
513 					break;
514 				if (c == 'x')
515 					break;
516 				if (c == 'X')
517 					break;
518 				if (c == 'e')
519 					break;
520 				if (c == 'E')
521 					break;
522 				if (c == 'c')
523 					break;
524 				if (c == 's')
525 					break;
526 				if (c == '%')
527 					break;
528 			}
529 			ePos = Math.min(ePos + 1, fmtArg.length());
530 			/*
531 			 * Workaround for crappy e format formatting. It will ignore exponent precision
532 			 * and at least will not print it
533 			 */
534 			if (ePos < fmtArg.length() && ( fmtArg.charAt(ePos-1)=='e' || fmtArg.charAt(ePos-1)=='E')) {
535 				if (Character.isDigit(fmtArg.charAt(ePos))) {
536 					ePos++;
537 				}
538 			}
539 			
540 			
541 			sFmt = new ConversionSpecification(fmtArg.substring(cPos, ePos));
542 			vFmt.addElement(sFmt);
543 			unCS = this.nonControl(fmtArg, ePos);
544 			if (unCS != null) {
545 				sFmt = new ConversionSpecification();
546 				sFmt.setLiteral(unCS);
547 				vFmt.addElement(sFmt);
548 			}
549 		}
550 	}
551 	/**
552 	 * Return a substring starting at
553 	 * <code>start</code> and ending at either the end
554 	 * of the String <code>s</code>, the next unpaired
555 	 * percent sign, or at the end of the String if the
556 	 * last character is a percent sign.
557 	 * @param s  Control string.
558 	 * @param start Position in the string
559 	 *     <code>s</code> to begin looking for the start
560 	 *     of a control string.
561 	 * @return the substring from the start position
562 	 *     to the beginning of the control string.
563 	 */
564 	private String nonControl(String s, int start) {
565 //		String ret = "";
566 		cPos = s.indexOf("%", start);
567 		if (cPos == -1)
568 			cPos = s.length();
569 		return s.substring(start, cPos);
570 	}
571 	/**
572 	 * Format an array of objects.  Byte, Short,
573 	 * Integer, Long, Float, Double, and Character
574 	 * arguments are treated as wrappers for primitive
575 	 * types.
576 	 * @param o The array of objects to format.
577 	 * @return  The formatted String.
578 	 */
579 	public String sprintf(Object[] o) {
580 		Enumeration e = vFmt.elements();
581 		ConversionSpecification cs = null;
582 		char c = 0;
583 		int i = 0;
584 		StringBuffer sb = new StringBuffer();
585 		while (e.hasMoreElements()) {
586 			cs = (ConversionSpecification) e.nextElement();
587 			c = cs.getConversionCharacter();
588 			if (c == '\0')
589 				sb.append(cs.getLiteral());
590 			else if (c == '%')
591 				sb.append("%");
592 			else {
593 				if (cs.isPositionalSpecification()) {
594 					i = cs.getArgumentPosition() - 1;
595 					if (cs.isPositionalFieldWidth()) {
596 						int ifw = cs.getArgumentPositionForFieldWidth() - 1;
597 						cs.setFieldWidthWithArg(((Integer) o[ifw]).intValue());
598 					}
599 					if (cs.isPositionalPrecision()) {
600 						int ipr = cs.getArgumentPositionForPrecision() - 1;
601 						cs.setPrecisionWithArg(((Integer) o[ipr]).intValue());
602 					}
603 				} else {
604 					if (cs.isVariableFieldWidth()) {
605 						cs.setFieldWidthWithArg(((Integer) o[i]).intValue());
606 						i++;
607 					}
608 					if (cs.isVariablePrecision()) {
609 						cs.setPrecisionWithArg(((Integer) o[i]).intValue());
610 						i++;
611 					}
612 				}
613 				if (o[i] instanceof Byte)
614 					sb.append(cs.internalsprintf(((Byte) o[i]).byteValue()));
615 				else if (o[i] instanceof Short)
616 					sb.append(cs.internalsprintf(((Short) o[i]).shortValue()));
617 				else if (o[i] instanceof Integer)
618 					sb.append(cs.internalsprintf(((Integer) o[i]).intValue()));
619 				else if (o[i] instanceof Long)
620 					sb.append(cs.internalsprintf(((Long) o[i]).longValue()));
621 				else if (o[i] instanceof Float)
622 					sb.append(cs.internalsprintf(((Float) o[i]).floatValue()));
623 				else if (o[i] instanceof Double)
624 					sb.append(cs.internalsprintf(((Double) o[i]).doubleValue()));
625 				else if (o[i] instanceof Character)
626 					sb.append(cs.internalsprintf(((Character) o[i]).charValue()));
627 				else if (o[i] instanceof String)
628 					sb.append(cs.internalsprintf((String) o[i]));
629 				else
630 					sb.append(cs.internalsprintf(o[i]));
631 				if (!cs.isPositionalSpecification())
632 					i++;
633 			}
634 		}
635 		return sb.toString();
636 	}
637 	/**
638 	 * Format nothing.  Just use the control string.
639 	 * @return  the formatted String.
640 	 */
641 	public String sprintf() {
642 		Enumeration e = vFmt.elements();
643 		ConversionSpecification cs = null;
644 		char c = 0;
645 		StringBuffer sb = new StringBuffer();
646 		while (e.hasMoreElements()) {
647 			cs = (ConversionSpecification) e.nextElement();
648 			c = cs.getConversionCharacter();
649 			if (c == '\0')
650 				sb.append(cs.getLiteral());
651 			else if (c == '%')
652 				sb.append("%");
653 		}
654 		return sb.toString();
655 	}
656 	/**
657 	 * Format an int.
658 	 * @param x The int to format.
659 	 * @return  The formatted String.
660 	 * @exception IllegalArgumentException if the
661 	 *     conversion character is f, e, E, g, G, s,
662 	 *     or S.
663 	 */
664 	public String sprintf(int x) throws IllegalArgumentException {
665 		Enumeration e = vFmt.elements();
666 		ConversionSpecification cs = null;
667 		char c = 0;
668 		StringBuffer sb = new StringBuffer();
669 		while (e.hasMoreElements()) {
670 			cs = (ConversionSpecification) e.nextElement();
671 			c = cs.getConversionCharacter();
672 			if (c == '\0')
673 				sb.append(cs.getLiteral());
674 			else if (c == '%')
675 				sb.append("%");
676 			else
677 				sb.append(cs.internalsprintf(x));
678 		}
679 		return sb.toString();
680 	}
681 	/**
682 	 * Format an long.
683 	 * @param x The long to format.
684 	 * @return  The formatted String.
685 	 * @exception IllegalArgumentException if the
686 	 *     conversion character is f, e, E, g, G, s,
687 	 *     or S.
688 	 */
689 	public String sprintf(long x) throws IllegalArgumentException {
690 		Enumeration e = vFmt.elements();
691 		ConversionSpecification cs = null;
692 		char c = 0;
693 		StringBuffer sb = new StringBuffer();
694 		while (e.hasMoreElements()) {
695 			cs = (ConversionSpecification) e.nextElement();
696 			c = cs.getConversionCharacter();
697 			if (c == '\0')
698 				sb.append(cs.getLiteral());
699 			else if (c == '%')
700 				sb.append("%");
701 			else
702 				sb.append(cs.internalsprintf(x));
703 		}
704 		return sb.toString();
705 	}
706 	/**
707 	 * Format a double.
708 	 * @param x The double to format.
709 	 * @return  The formatted String.
710 	 * @exception IllegalArgumentException if the
711 	 *     conversion character is c, C, s, S,
712 	 *     d, d, x, X, or o.
713 	 */
714 	public String sprintf(double x) throws IllegalArgumentException {
715 		Enumeration e = vFmt.elements();
716 		ConversionSpecification cs = null;
717 		char c = 0;
718 		StringBuffer sb = new StringBuffer();
719 		while (e.hasMoreElements()) {
720 			cs = (ConversionSpecification) e.nextElement();
721 			c = cs.getConversionCharacter();
722 			if (c == '\0')
723 				sb.append(cs.getLiteral());
724 			else if (c == '%')
725 				sb.append("%");
726 			else
727 				sb.append(cs.internalsprintf(x));
728 		}
729 		return sb.toString();
730 	}
731 	/**
732 	 * Format a String.
733 	 * @param x The String to format.
734 	 * @return  The formatted String.
735 	 * @exception IllegalArgumentException if the
736 	 *   conversion character is neither s nor S.
737 	 */
738 	public String sprintf(String x) throws IllegalArgumentException {
739 		Enumeration e = vFmt.elements();
740 		ConversionSpecification cs = null;
741 		char c = 0;
742 		StringBuffer sb = new StringBuffer();
743 		while (e.hasMoreElements()) {
744 			cs = (ConversionSpecification) e.nextElement();
745 			c = cs.getConversionCharacter();
746 			if (c == '\0')
747 				sb.append(cs.getLiteral());
748 			else if (c == '%')
749 				sb.append("%");
750 			else
751 				sb.append(cs.internalsprintf(x));
752 		}
753 		return sb.toString();
754 	}
755 	/**
756 	 * Format an Object.  Convert wrapper types to
757 	 * their primitive equivalents and call the
758 	 * appropriate internal formatting method. Convert
759 	 * Strings using an internal formatting method for
760 	 * Strings. Otherwise use the default formatter
761 	 * (use toString).
762 	 * @param x the Object to format.
763 	 * @return  the formatted String.
764 	 * @exception IllegalArgumentException if the
765 	 *    conversion character is inappropriate for
766 	 *    formatting an unwrapped value.
767 	 */
768 	public String sprintf(Object x) throws IllegalArgumentException {
769 		Enumeration e = vFmt.elements();
770 		ConversionSpecification cs = null;
771 		char c = 0;
772 		StringBuffer sb = new StringBuffer();
773 		while (e.hasMoreElements()) {
774 			cs = (ConversionSpecification) e.nextElement();
775 			c = cs.getConversionCharacter();
776 			if (c == '\0')
777 				sb.append(cs.getLiteral());
778 			else if (c == '%')
779 				sb.append("%");
780 			else {
781 				if (x instanceof Byte)
782 					sb.append(cs.internalsprintf(((Byte) x).byteValue()));
783 				else if (x instanceof Short)
784 					sb.append(cs.internalsprintf(((Short) x).shortValue()));
785 				else if (x instanceof Integer)
786 					sb.append(cs.internalsprintf(((Integer) x).intValue()));
787 				else if (x instanceof Long)
788 					sb.append(cs.internalsprintf(((Long) x).longValue()));
789 				else if (x instanceof Float)
790 					sb.append(cs.internalsprintf(((Float) x).floatValue()));
791 				else if (x instanceof Double)
792 					sb.append(cs.internalsprintf(((Double) x).doubleValue()));
793 				else if (x instanceof Character)
794 					sb.append(cs.internalsprintf(((Character) x).charValue()));
795 				else if (x instanceof String)
796 					sb.append(cs.internalsprintf((String) x));
797 				else
798 					sb.append(cs.internalsprintf(x));
799 			}
800 		}
801 		return sb.toString();
802 	}
803 	/**
804 	 *<p>
805 	 * ConversionSpecification allows the formatting of
806 	 * a single primitive or object embedded within a
807 	 * string.  The formatting is controlled by a
808 	 * format string.  Only one Java primitive or
809 	 * object can be formatted at a time.
810 	 *<p>
811 	 * A format string is a Java string that contains
812 	 * a control string.  The control string starts at
813 	 * the first percent sign (%) in the string,
814 	 * provided that this percent sign
815 	 *<ol>
816 	 *<li>is not escaped protected by a matching % or
817 	 *     is not an escape % character,
818 	 *<li>is not at the end of the format string, and
819 	 *<li>precedes a sequence of characters that parses
820 	 *     as a valid control string.
821 	 *</ol>
822 	 *<p>
823 	 * A control string takes the form:
824 	 *<pre> % ['-+ #0]* [0..9]* { . [0..9]* }+
825 	 *                { [hlL] }+ [idfgGoxXeEcs]
826 	 *</pre>
827 	 *<p>
828 	 * The behavior is like printf.  One (hopefully the
829 	 * only) exception is that the minimum number of
830 	 * exponent digits is 3 instead of 2 for e and E
831 	 * formats when the optional L is used before the
832 	 * e, E, g, or G conversion character.  The 
833 	 * optional L does not imply conversion to a long
834 	 * long double.
835 	 */
836 	private class ConversionSpecification {
837 		/**
838 		 * Constructor.  Used to prepare an instance
839 		 * to hold a literal, not a control string.
840 		 */
841 		ConversionSpecification() {
842 		}
843 		/**
844 		 * Constructor for a conversion specification.
845 		 * The argument must begin with a % and end
846 		 * with the conversion character for the
847 		 * conversion specification.
848 		  * @param fmtArg  String specifying the
849 		 *     conversion specification.
850 		  * @exception IllegalArgumentException if the
851 		 *     input string is null, zero length, or
852 		 *     otherwise malformed.
853 		 */
854 		ConversionSpecification(String fmtArg) throws IllegalArgumentException {
855 			if (fmtArg == null)
856 				throw new NullPointerException();
857 			if (fmtArg.length() == 0)
858 				throw new IllegalArgumentException("Control strings must have positive" + " lengths.");
859 			if (fmtArg.charAt(0) == '%') {
860 				fmt = fmtArg;
861 				pos = 1;
862 				setArgPosition();
863 				setFlagCharacters();
864 				setFieldWidth();
865 				setPrecision();
866 				setOptionalHL();
867 				if (setConversionCharacter()) {
868 					setPrecisionE();
869 					if (pos == fmtArg.length()) {
870 						if (leadingZeros && leftJustify)
871 							leadingZeros = false;
872 						if (precisionSet && leadingZeros) {
873 							if (conversionCharacter == 'd'
874 								|| conversionCharacter == 'i'
875 								|| conversionCharacter == 'o'
876 								|| conversionCharacter == 'x') {
877 								leadingZeros = false;
878 							}
879 						}
880 					} else
881 						throw new IllegalArgumentException("Malformed conversion specification=" + fmtArg);
882 				} else
883 					throw new IllegalArgumentException("Malformed conversion specification=" + fmtArg);
884 			} else
885 				throw new IllegalArgumentException("Control strings must begin with %.");
886 		}
887 		/**
888 		 * Set the String for this instance.
889 		 * @param s the String to store.
890 		 */
891 		void setLiteral(String s) {
892 			fmt = s;
893 		}
894 		/**
895 		 * Get the String for this instance.  Translate
896 		 * any escape sequences.
897 		 *
898 		 * @return s the stored String.
899 		 */
900 		String getLiteral() {
901 			StringBuffer sb = new StringBuffer();
902 			int i = 0;
903 			while (i < fmt.length()) {
904 				if (fmt.charAt(i) == '\\') {
905 					i++;
906 					if (i < fmt.length()) {
907 						char c = fmt.charAt(i);
908 						switch (c) {
909 							case 'a' :
910 								sb.append((char) 0x07);
911 								break;
912 							case 'b' :
913 								sb.append('\b');
914 								break;
915 							case 'f' :
916 								sb.append('\f');
917 								break;
918 							case 'n' :
919 								sb.append(System.getProperty("line.separator"));
920 								break;
921 							case 'r' :
922 								sb.append('\r');
923 								break;
924 							case 't' :
925 								sb.append('\t');
926 								break;
927 							case 'v' :
928 								sb.append((char) 0x0b);
929 								break;
930 							case '\\' :
931 								sb.append('\\');
932 								break;
933 						}
934 						i++;
935 					} else
936 						sb.append('\\');
937 				} else
938 					i++;
939 			}
940 			return fmt;
941 		}
942 		/**
943 		 * Get the conversion character that tells what
944 		 * type of control character this instance has.
945 		 *
946 		 * @return the conversion character.
947 		 */
948 		char getConversionCharacter() {
949 			return conversionCharacter;
950 		}
951 		/**
952 		 * Check whether the specifier has a variable
953 		 * field width that is going to be set by an
954 		 * argument.
955 		 * @return <code>true</code> if the conversion
956 		 *   uses an * field width; otherwise
957 		 *   <code>false</code>.
958 		 */
959 		boolean isVariableFieldWidth() {
960 			return variableFieldWidth;
961 		}
962 		/**
963 		 * Set the field width with an argument.  A
964 		 * negative field width is taken as a - flag
965 		 * followed by a positive field width.
966 		 * @param fw the field width.
967 		 */
968 		void setFieldWidthWithArg(int fw) {
969 			if (fw < 0)
970 				leftJustify = true;
971 			fieldWidthSet = true;
972 			fieldWidth = Math.abs(fw);
973 		}
974 		/**
975 		 * Check whether the specifier has a variable
976 		 * precision that is going to be set by an
977 		 * argument.
978 		 * @return <code>true</code> if the conversion
979 		 *   uses an * precision; otherwise
980 		 *   <code>false</code>.
981 		 */
982 		boolean isVariablePrecision() {
983 			return variablePrecision;
984 		}
985 		/**
986 		 * Set the precision with an argument.  A
987 		 * negative precision will be changed to zero.
988 		 * @param pr the precision.
989 		 */
990 		void setPrecisionWithArg(int pr) {
991 			precisionSet = true;
992 			precision = Math.max(pr, 0);
993 		}
994 		/**
995 		 * Format an int argument using this conversion
996 		  * specification.
997 		 * @param s the int to format.
998 		 * @return the formatted String.
999 		 * @exception IllegalArgumentException if the
1000 		 *     conversion character is f, e, E, g, or G.
1001 		 */
1002 		String internalsprintf(int s) throws IllegalArgumentException {
1003 			String s2 = "";
1004 			switch (conversionCharacter) {
1005 				case 'd' :
1006 				case 'i' :
1007 					if (optionalh)
1008 						s2 = printDFormat((short) s);
1009 					else if (optionall)
1010 						s2 = printDFormat((long) s);
1011 					else
1012 						s2 = printDFormat(s);
1013 					break;
1014 				case 'x' :
1015 				case 'X' :
1016 					if (optionalh)
1017 						s2 = printXFormat((short) s);
1018 					else if (optionall)
1019 						s2 = printXFormat((long) s);
1020 					else
1021 						s2 = printXFormat(s);
1022 					break;
1023 				case 'o' :
1024 					if (optionalh)
1025 						s2 = printOFormat((short) s);
1026 					else if (optionall)
1027 						s2 = printOFormat((long) s);
1028 					else
1029 						s2 = printOFormat(s);
1030 					break;
1031 				case 'c' :
1032 				case 'C' :
1033 					s2 = printCFormat((char) s);
1034 					break;
1035 				default :
1036 					throw new IllegalArgumentException(
1037 						"Cannot format a int with a format using a " + conversionCharacter + " conversion character.");
1038 			}
1039 			return s2;
1040 		}
1041 		/**
1042 		 * Format a long argument using this conversion
1043 		 * specification.
1044 		 * @param s the long to format.
1045 		 * @return the formatted String.
1046 		 * @exception IllegalArgumentException if the
1047 		 *     conversion character is f, e, E, g, or G.
1048 		 */
1049 		String internalsprintf(long s) throws IllegalArgumentException {
1050 			String s2 = "";
1051 			switch (conversionCharacter) {
1052 				case 'd' :
1053 				case 'i' :
1054 					if (optionalh)
1055 						s2 = printDFormat((short) s);
1056 					else if (optionall)
1057 						s2 = printDFormat(s);
1058 					else
1059 						s2 = printDFormat((int) s);
1060 					break;
1061 				case 'x' :
1062 				case 'X' :
1063 					if (optionalh)
1064 						s2 = printXFormat((short) s);
1065 					else if (optionall)
1066 						s2 = printXFormat(s);
1067 					else
1068 						s2 = printXFormat((int) s);
1069 					break;
1070 				case 'o' :
1071 					if (optionalh)
1072 						s2 = printOFormat((short) s);
1073 					else if (optionall)
1074 						s2 = printOFormat(s);
1075 					else
1076 						s2 = printOFormat((int) s);
1077 					break;
1078 				case 'c' :
1079 				case 'C' :
1080 					s2 = printCFormat((char) s);
1081 					break;
1082 				default :
1083 					throw new IllegalArgumentException(
1084 						"Cannot format a long with a format using a " + conversionCharacter + " conversion character.");
1085 			}
1086 			return s2;
1087 		}
1088 		/**
1089 		 * Format a double argument using this conversion
1090 		 * specification.
1091 		 * @param s the double to format.
1092 		 * @return the formatted String.
1093 		 * @exception IllegalArgumentException if the
1094 		 *     conversion character is c, C, s, S, i,
1095 		 *     x, X, or o.
1096 		 */
1097 		String internalsprintf(double s) throws IllegalArgumentException {
1098 			String s2 = "";
1099 			switch (conversionCharacter) {
1100 				case 'f' :
1101 					s2 = printFFormat(s);
1102 					break;
1103 				case 'E' :
1104 				case 'e' :
1105 					s2 = printEFormat(s);
1106 					break;
1107 				case 'G' :
1108 				case 'g' :
1109 					s2 = printGFormat(s);
1110 					break;
1111 				case 'D' :
1112 				case 'd' :
1113 					s2 = printDFormat(Math.round(s));
1114 					break;
1115 				default :
1116 					throw new IllegalArgumentException(
1117 						"Cannot "
1118 							+ "format a double with a format using a "
1119 							+ conversionCharacter
1120 							+ " conversion character.");
1121 			}
1122 			return s2;
1123 		}
1124 		/**
1125 		 * Format a String argument using this conversion
1126 		 * specification.
1127 		 * @param s the String to format.
1128 		 * @return the formatted String.
1129 		 * @exception IllegalArgumentException if the
1130 		 *   conversion character is neither s nor S.
1131 		 */
1132 		String internalsprintf(String s) throws IllegalArgumentException {
1133 			String s2 = "";
1134 			if (conversionCharacter == 's' || conversionCharacter == 'S')
1135 				s2 = printSFormat(s);
1136 			else
1137 				throw new IllegalArgumentException(
1138 					"Cannot "
1139 						+ "format a String with a format using a "
1140 						+ conversionCharacter
1141 						+ " conversion character.");
1142 			return s2;
1143 		}
1144 		/**
1145 		 * Format an Object argument using this conversion
1146 		 * specification.
1147 		 * @param s the Object to format.
1148 		 * @return the formatted String.
1149 		 * @exception IllegalArgumentException if the
1150 		 *     conversion character is neither s nor S.
1151 		 */
1152 		String internalsprintf(Object s) {
1153 			String s2 = "";
1154 			if (conversionCharacter == 's' || conversionCharacter == 'S')
1155 				s2 = printSFormat(s.toString());
1156 			else
1157 				throw new IllegalArgumentException(
1158 					"Cannot format a String with a format using"
1159 						+ " a "
1160 						+ conversionCharacter
1161 						+ " conversion character.");
1162 			return s2;
1163 		}
1164 		/**
1165 		 * For f format, the flag character '-', means that
1166 		 * the output should be left justified within the
1167 		 * field.  The default is to pad with blanks on the
1168 		 * left.  '+' character means that the conversion
1169 		 * will always begin with a sign (+ or -).  The
1170 		 * blank flag character means that a non-negative
1171 		 * input will be preceded with a blank.  If both
1172 		 * a '+' and a ' ' are specified, the blank flag
1173 		 * is ignored.  The '0' flag character implies that
1174 		 * padding to the field width will be done with
1175 		 * zeros instead of blanks.
1176 		 *
1177 		 * The field width is treated as the minimum number
1178 		 * of characters to be printed.  The default is to
1179 		 * add no padding.  Padding is with blanks by
1180 		 * default.
1181 		 *
1182 		 * The precision, if set, is the number of digits
1183 		 * to appear after the radix character.  Padding is
1184 		 * with trailing 0s.
1185 		 */
1186 		private char[] fFormatDigits(double x) {
1187 			// int defaultDigits=6;
1188 			String sx; //, sxOut;
1189 			int i, j, k;
1190 			int n1In, n2In;
1191 			int expon = 0;
1192 			boolean minusSign = false;
1193 			if (x > 0.0)
1194 				sx = Double.toString(x);
1195 			else if (x < 0.0) {
1196 				sx = Double.toString(-x);
1197 				minusSign = true;
1198 			} else {
1199 				sx = Double.toString(x);
1200 				if (sx.charAt(0) == '-') {
1201 					minusSign = true;
1202 					sx = sx.substring(1);
1203 				}
1204 			}
1205 			int ePos = sx.indexOf('E');
1206 			int rPos = sx.indexOf('.');
1207 			if (rPos != -1)
1208 				n1In = rPos;
1209 			else if (ePos != -1)
1210 				n1In = ePos;
1211 			else
1212 				n1In = sx.length();
1213 			if (rPos != -1) {
1214 				if (ePos != -1)
1215 					n2In = ePos - rPos - 1;
1216 				else
1217 					n2In = sx.length() - rPos - 1;
1218 			} else
1219 				n2In = 0;
1220 			if (ePos != -1) {
1221 				int ie = ePos + 1;
1222 				expon = 0;
1223 				if (sx.charAt(ie) == '-') {
1224 					for (++ie; ie < sx.length(); ie++)
1225 						if (sx.charAt(ie) != '0')
1226 							break;
1227 					if (ie < sx.length())
1228 						expon = -Integer.parseInt(sx.substring(ie));
1229 				} else {
1230 					if (sx.charAt(ie) == '+')
1231 						++ie;
1232 					for (; ie < sx.length(); ie++)
1233 						if (sx.charAt(ie) != '0')
1234 							break;
1235 					if (ie < sx.length())
1236 						expon = Integer.parseInt(sx.substring(ie));
1237 				}
1238 			}
1239 			int p;
1240 			if (precisionSet)
1241 				p = precision;
1242 			else
1243 				p = defaultDigits - 1;
1244 			char[] ca1 = sx.toCharArray();
1245 			char[] ca2 = new char[n1In + n2In];
1246 			char[] ca3, ca4, ca5;
1247 			for (j = 0; j < n1In; j++)
1248 				ca2[j] = ca1[j];
1249 			i = j + 1;
1250 			for (k = 0; k < n2In; j++, i++, k++)
1251 				ca2[j] = ca1[i];
1252 			if (n1In + expon <= 0) {
1253 				ca3 = new char[-expon + n2In];
1254 				for (j = 0, k = 0; k < (-n1In - expon); k++, j++)
1255 					ca3[j] = '0';
1256 				for (i = 0; i < (n1In + n2In); i++, j++)
1257 					ca3[j] = ca2[i];
1258 			} else
1259 				ca3 = ca2;
1260 			boolean carry = false;
1261 			if (p < -expon + n2In) {
1262 				if (expon < 0)
1263 					i = p;
1264 				else
1265 					i = p + n1In;
1266 				carry = checkForCarry(ca3, i);
1267 				if (carry)
1268 					carry = startSymbolicCarry(ca3, i - 1, 0);
1269 			}
1270 			if (n1In + expon <= 0) {
1271 				ca4 = new char[2 + p];
1272 				if (!carry)
1273 					ca4[0] = '0';
1274 				else
1275 					ca4[0] = '1';
1276 				if (alternateForm || !precisionSet || precision != 0) {
1277 					ca4[1] = '.';
1278 					for (i = 0, j = 2; i < Math.min(p, ca3.length); i++, j++)
1279 						ca4[j] = ca3[i];
1280 					for (; j < ca4.length; j++)
1281 						ca4[j] = '0';
1282 				}
1283 			} else {
1284 				if (!carry) {
1285 					if (alternateForm || !precisionSet || precision != 0)
1286 						ca4 = new char[n1In + expon + p + 1];
1287 					else
1288 						ca4 = new char[n1In + expon];
1289 					j = 0;
1290 				} else {
1291 					if (alternateForm || !precisionSet || precision != 0)
1292 						ca4 = new char[n1In + expon + p + 2];
1293 					else
1294 						ca4 = new char[n1In + expon + 1];
1295 					ca4[0] = '1';
1296 					j = 1;
1297 				}
1298 				for (i = 0; i < Math.min(n1In + expon, ca3.length); i++, j++)
1299 					ca4[j] = ca3[i];
1300 				for (; i < n1In + expon; i++, j++)
1301 					ca4[j] = '0';
1302 				if (alternateForm || !precisionSet || precision != 0) {
1303 					ca4[j] = '.';
1304 					j++;
1305 					for (k = 0; i < ca3.length && k < p; i++, j++, k++)
1306 						ca4[j] = ca3[i];
1307 					for (; j < ca4.length; j++)
1308 						ca4[j] = '0';
1309 				}
1310 			}
1311 			int nZeros = 0;
1312 			if (!leftJustify && leadingZeros) {
1313 				int xThousands = 0;
1314 				if (thousands) {
1315 					int xlead = 0;
1316 					if (ca4[0] == '+' || ca4[0] == '-' || ca4[0] == ' ')
1317 						xlead = 1;
1318 					int xdp = xlead;
1319 					for (; xdp < ca4.length; xdp++)
1320 						if (ca4[xdp] == '.')
1321 							break;
1322 					xThousands = (xdp - xlead) / 3;
1323 				}
1324 				if (fieldWidthSet)
1325 					nZeros = fieldWidth - ca4.length;
1326 				if ((!minusSign && (leadingSign || leadingSpace)) || minusSign)
1327 					nZeros--;
1328 				nZeros -= xThousands;
1329 				if (nZeros < 0)
1330 					nZeros = 0;
1331 			}
1332 			j = 0;
1333 			if ((!minusSign && (leadingSign || leadingSpace)) || minusSign) {
1334 				ca5 = new char[ca4.length + nZeros + 1];
1335 				j++;
1336 			} else
1337 				ca5 = new char[ca4.length + nZeros];
1338 			if (!minusSign) {
1339 				if (leadingSign)
1340 					ca5[0] = '+';
1341 				if (leadingSpace)
1342 					ca5[0] = ' ';
1343 			} else
1344 				ca5[0] = '-';
1345 			for (i = 0; i < nZeros; i++, j++)
1346 				ca5[j] = '0';
1347 			for (i = 0; i < ca4.length; i++, j++)
1348 				ca5[j] = ca4[i];
1349 
1350 			int lead = 0;
1351 			if (ca5[0] == '+' || ca5[0] == '-' || ca5[0] == ' ')
1352 				lead = 1;
1353 			int dp = lead;
1354 			for (; dp < ca5.length; dp++)
1355 				if (ca5[dp] == '.')
1356 					break;
1357 			int nThousands = (dp - lead) / 3;
1358 			// Localize the decimal point.
1359 			if (dp < ca5.length)
1360 				ca5[dp] = dfs.getDecimalSeparator();
1361 			char[] ca6 = ca5;
1362 			if (thousands && nThousands > 0) {
1363 				ca6 = new char[ca5.length + nThousands + lead];
1364 				ca6[0] = ca5[0];
1365 				for (i = lead, k = lead; i < dp; i++) {
1366 					if (i > 0 && (dp - i) % 3 == 0) {
1367 						// ca6[k]=',';
1368 						ca6[k] = dfs.getGroupingSeparator();
1369 						ca6[k + 1] = ca5[i];
1370 						k += 2;
1371 					} else {
1372 						ca6[k] = ca5[i];
1373 						k++;
1374 					}
1375 				}
1376 				for (; i < ca5.length; i++, k++) {
1377 					ca6[k] = ca5[i];
1378 				}
1379 			}
1380 			return ca6;
1381 		}
1382 		/**
1383 		 * An intermediate routine on the way to creating
1384 		 * an f format String.  The method decides whether
1385 		 * the input double value is an infinity,
1386 		 * not-a-number, or a finite double and formats
1387 		 * each type of input appropriately.
1388 		 * @param x the double value to be formatted.
1389 		 * @return the converted double value.
1390 		 */
1391 		private String fFormatString(double x) {
1392 //			boolean noDigits = false;
1393 			char[] ca6, ca7;
1394 			if (Double.isInfinite(x)) {
1395 				if (x == Double.POSITIVE_INFINITY) {
1396 					if (leadingSign)
1397 						ca6 = "+Inf".toCharArray();
1398 					else if (leadingSpace)
1399 						ca6 = " Inf".toCharArray();
1400 					else
1401 						ca6 = "Inf".toCharArray();
1402 				} else
1403 					ca6 = "-Inf".toCharArray();
1404 //				noDigits = true;
1405 			} else if (Double.isNaN(x)) {
1406 				if (leadingSign)
1407 					ca6 = "+NaN".toCharArray();
1408 				else if (leadingSpace)
1409 					ca6 = " NaN".toCharArray();
1410 				else
1411 					ca6 = "NaN".toCharArray();
1412 //				noDigits = true;
1413 			} else
1414 				ca6 = fFormatDigits(x);
1415 			ca7 = applyFloatPadding(ca6, false);
1416 			return new String(ca7);
1417 		}
1418 		/**
1419 		 * For e format, the flag character '-', means that
1420 		 * the output should be left justified within the
1421 		 * field.  The default is to pad with blanks on the
1422 		 * left.  '+' character means that the conversion
1423 		 * will always begin with a sign (+ or -).  The
1424 		 * blank flag character means that a non-negative
1425 		 * input will be preceded with a blank.  If both a
1426 		 * '+' and a ' ' are specified, the blank flag is
1427 		 * ignored.  The '0' flag character implies that
1428 		 * padding to the field width will be done with
1429 		 * zeros instead of blanks.
1430 		 *
1431 		 * The field width is treated as the minimum number
1432 		 * of characters to be printed.  The default is to
1433 		 * add no padding.  Padding is with blanks by
1434 		 * default.
1435 		 *
1436 		 * The precision, if set, is the minimum number of
1437 		 * digits to appear after the radix character.
1438 		 * Padding is with trailing 0s.
1439 		 *
1440 		 * The behavior is like printf.  One (hopefully the
1441 		 * only) exception is that the minimum number of
1442 		 * exponent digits is 3 instead of 2 for e and E
1443 		 * formats when the optional L is used before the
1444 		 * e, E, g, or G conversion character. The optional
1445 		 * L does not imply conversion to a long long
1446 		 * double.
1447 		 */
1448 		private char[] eFormatDigits(double x, char eChar) {
1449 			char[] ca1, ca2, ca3;
1450 			// int defaultDigits=6;
1451 			String sx;// sxOut;
1452 			int i, j, k, p;
1453 //			int n1In; //, n2In;
1454 			int expon = 0;
1455 			int ePos, rPos, eSize;
1456 			boolean minusSign = false;
1457 			if (x > 0.0)
1458 				sx = Double.toString(x);
1459 			else if (x < 0.0) {
1460 				sx = Double.toString(-x);
1461 				minusSign = true;
1462 			} else {
1463 				sx = Double.toString(x);
1464 				if (sx.charAt(0) == '-') {
1465 					minusSign = true;
1466 					sx = sx.substring(1);
1467 				}
1468 			}
1469 			ePos = sx.indexOf('E');
1470 			if (ePos == -1)
1471 				ePos = sx.indexOf('e');
1472 			rPos = sx.indexOf('.');
1473 /*
1474 			if (rPos != -1)
1475 				n1In = rPos;
1476 			else if (ePos != -1)
1477 				n1In = ePos;
1478 			else
1479 				n1In = sx.length();
1480 /*
1481 			if (rPos != -1) {
1482 				if (ePos != -1)
1483 					n2In = ePos - rPos - 1;
1484 				else
1485 					n2In = sx.length() - rPos - 1;
1486 			} else
1487 				n2In = 0;
1488 */
1489 			if (ePos != -1) {
1490 				int ie = ePos + 1;
1491 				expon = 0;
1492 				if (sx.charAt(ie) == '-') {
1493 					for (++ie; ie < sx.length(); ie++)
1494 						if (sx.charAt(ie) != '0')
1495 							break;
1496 					if (ie < sx.length())
1497 						expon = -Integer.parseInt(sx.substring(ie));
1498 				} else {
1499 					if (sx.charAt(ie) == '+')
1500 						++ie;
1501 					for (; ie < sx.length(); ie++)
1502 						if (sx.charAt(ie) != '0')
1503 							break;
1504 					if (ie < sx.length())
1505 						expon = Integer.parseInt(sx.substring(ie));
1506 				}
1507 			}
1508 			if (rPos != -1)
1509 				expon += rPos - 1;
1510 			if (precisionSet)
1511 				p = precision;
1512 			else
1513 				p = defaultDigits - 1;
1514 			if (rPos != -1 && ePos != -1)
1515 				ca1 = (sx.substring(0, rPos) + sx.substring(rPos + 1, ePos)).toCharArray();
1516 			else if (rPos != -1)
1517 				ca1 = (sx.substring(0, rPos) + sx.substring(rPos + 1)).toCharArray();
1518 			else if (ePos != -1)
1519 				ca1 = sx.substring(0, ePos).toCharArray();
1520 			else
1521 				ca1 = sx.toCharArray();
1522 			boolean carry = false;
1523 			int i0 = 0;
1524 			if (ca1[0] != '0')
1525 				i0 = 0;
1526 			else
1527 				for (i0 = 0; i0 < ca1.length; i0++)
1528 					if (ca1[i0] != '0')
1529 						break;
1530 			if (i0 + p < ca1.length - 1) {
1531 				carry = checkForCarry(ca1, i0 + p + 1);
1532 				if (carry)
1533 					carry = startSymbolicCarry(ca1, i0 + p, i0);
1534 				if (carry) {
1535 					ca2 = new char[i0 + p + 1];
1536 					ca2[i0] = '1';
1537 					for (j = 0; j < i0; j++)
1538 						ca2[j] = '0';
1539 					for (i = i0, j = i0 + 1; j < p + 1; i++, j++)
1540 						ca2[j] = ca1[i];
1541 					expon++;
1542 					ca1 = ca2;
1543 				}
1544 			}
1545 			if (Math.abs(expon) < 10 && !optionalL) {
1546 				// ike workaround
1547 				eSize= precisionE + 2;
1548 			} else
1549 			if (Math.abs(expon) < 100 && !optionalL && precisionE>1) {
1550 				// ike workaround
1551 				//eSize = 4;
1552 				eSize= precisionE + 2;
1553 			} else
1554 				eSize = 5;
1555 			if (alternateForm || !precisionSet || precision != 0)
1556 				ca2 = new char[2 + p + eSize];
1557 			else
1558 				ca2 = new char[1 + eSize];
1559 			if (ca1[0] != '0') {
1560 				ca2[0] = ca1[0];
1561 				j = 1;
1562 			} else {
1563 				for (j = 1; j < (ePos == -1 ? ca1.length : ePos); j++)
1564 					if (ca1[j] != '0')
1565 						break;
1566 				if ((ePos != -1 && j < ePos) || (ePos == -1 && j < ca1.length)) {
1567 					ca2[0] = ca1[j];
1568 					expon -= j;
1569 					j++;
1570 				} else {
1571 					ca2[0] = '0';
1572 					j = 2;
1573 				}
1574 			}
1575 			if (alternateForm || !precisionSet || precision != 0) {
1576 				ca2[1] = '.';
1577 				i = 2;
1578 			} else
1579 				i = 1;
1580 			for (k = 0; k < p && j < ca1.length; j++, i++, k++)
1581 				ca2[i] = ca1[j];
1582 			for (; i < ca2.length - eSize; i++)
1583 				ca2[i] = '0';
1584 			ca2[i++] = eChar;
1585 			if (expon < 0)
1586 				ca2[i++] = '-';
1587 			else
1588 				ca2[i++] = '+';
1589 			expon = Math.abs(expon);
1590 			if (eSize==5) {
1591 				switch (expon / 100) {
1592 					case 0 :
1593 						ca2[i] = '0';
1594 						break;
1595 					case 1 :
1596 						ca2[i] = '1';
1597 						break;
1598 					case 2 :
1599 						ca2[i] = '2';
1600 						break;
1601 					case 3 :
1602 						ca2[i] = '3';
1603 						break;
1604 					case 4 :
1605 						ca2[i] = '4';
1606 						break;
1607 					case 5 :
1608 						ca2[i] = '5';
1609 						break;
1610 					case 6 :
1611 						ca2[i] = '6';
1612 						break;
1613 					case 7 :
1614 						ca2[i] = '7';
1615 						break;
1616 					case 8 :
1617 						ca2[i] = '8';
1618 						break;
1619 					case 9 :
1620 						ca2[i] = '9';
1621 						break;
1622 				}
1623 				i++;
1624 			}
1625 			if (eSize>=4) {
1626 			switch ((expon % 100) / 10) {
1627 				case 0 :
1628 					ca2[i] = '0';
1629 					break;
1630 				case 1 :
1631 					ca2[i] = '1';
1632 					break;
1633 				case 2 :
1634 					ca2[i] = '2';
1635 					break;
1636 				case 3 :
1637 					ca2[i] = '3';
1638 					break;
1639 				case 4 :
1640 					ca2[i] = '4';
1641 					break;
1642 				case 5 :
1643 					ca2[i] = '5';
1644 					break;
1645 				case 6 :
1646 					ca2[i] = '6';
1647 					break;
1648 				case 7 :
1649 					ca2[i] = '7';
1650 					break;
1651 				case 8 :
1652 					ca2[i] = '8';
1653 					break;
1654 				case 9 :
1655 					ca2[i] = '9';
1656 					break;
1657 			}
1658 			i++;
1659 			}
1660 			switch (expon % 10) {
1661 				case 0 :
1662 					ca2[i] = '0';
1663 					break;
1664 				case 1 :
1665 					ca2[i] = '1';
1666 					break;
1667 				case 2 :
1668 					ca2[i] = '2';
1669 					break;
1670 				case 3 :
1671 					ca2[i] = '3';
1672 					break;
1673 				case 4 :
1674 					ca2[i] = '4';
1675 					break;
1676 				case 5 :
1677 					ca2[i] = '5';
1678 					break;
1679 				case 6 :
1680 					ca2[i] = '6';
1681 					break;
1682 				case 7 :
1683 					ca2[i] = '7';
1684 					break;
1685 				case 8 :
1686 					ca2[i] = '8';
1687 					break;
1688 				case 9 :
1689 					ca2[i] = '9';
1690 					break;
1691 			}
1692 			int nZeros = 0;
1693 			if (!leftJustify && leadingZeros) {
1694 				int xThousands = 0;
1695 				if (thousands) {
1696 					int xlead = 0;
1697 					if (ca2[0] == '+' || ca2[0] == '-' || ca2[0] == ' ')
1698 						xlead = 1;
1699 					int xdp = xlead;
1700 					for (; xdp < ca2.length; xdp++)
1701 						if (ca2[xdp] == '.')
1702 							break;
1703 					xThousands = (xdp - xlead) / 3;
1704 				}
1705 				if (fieldWidthSet)
1706 					nZeros = fieldWidth - ca2.length;
1707 				if ((!minusSign && (leadingSign || leadingSpace)) || minusSign)
1708 					nZeros--;
1709 				nZeros -= xThousands;
1710 				if (nZeros < 0)
1711 					nZeros = 0;
1712 			}
1713 			j = 0;
1714 			if ((!minusSign && (leadingSign || leadingSpace)) || minusSign) {
1715 				ca3 = new char[ca2.length + nZeros + 1];
1716 				j++;
1717 			} else
1718 				ca3 = new char[ca2.length + nZeros];
1719 			if (!minusSign) {
1720 				if (leadingSign)
1721 					ca3[0] = '+';
1722 				if (leadingSpace)
1723 					ca3[0] = ' ';
1724 			} else
1725 				ca3[0] = '-';
1726 			for (k = 0; k < nZeros; j++, k++)
1727 				ca3[j] = '0';
1728 			for (i = 0; i < ca2.length && j < ca3.length; i++, j++)
1729 				ca3[j] = ca2[i];
1730 
1731 			int lead = 0;
1732 			if (ca3[0] == '+' || ca3[0] == '-' || ca3[0] == ' ')
1733 				lead = 1;
1734 			int dp = lead;
1735 			for (; dp < ca3.length; dp++)
1736 				if (ca3[dp] == '.')
1737 					break;
1738 			int nThousands = dp / 3;
1739 			// Localize the decimal point.
1740 			if (dp < ca3.length)
1741 				ca3[dp] = dfs.getDecimalSeparator();
1742 			char[] ca4 = ca3;
1743 			if (thousands && nThousands > 0) {
1744 				ca4 = new char[ca3.length + nThousands + lead];
1745 				ca4[0] = ca3[0];
1746 				for (i = lead, k = lead; i < dp; i++) {
1747 					if (i > 0 && (dp - i) % 3 == 0) {
1748 						// ca4[k]=',';
1749 						ca4[k] = dfs.getGroupingSeparator();
1750 						ca4[k + 1] = ca3[i];
1751 						k += 2;
1752 					} else {
1753 						ca4[k] = ca3[i];
1754 						k++;
1755 					}
1756 				}
1757 				for (; i < ca3.length; i++, k++)
1758 					ca4[k] = ca3[i];
1759 			}
1760 			return ca4;
1761 		}
1762 		/**
1763 		 * Check to see if the digits that are going to
1764 		 * be truncated because of the precision should
1765 		 * force a round in the preceding digits.
1766 		 * @param ca1 the array of digits
1767 		 * @param icarry the index of the first digit that
1768 		 *     is to be truncated from the print
1769 		 * @return <code>true</code> if the truncation forces
1770 		 *     a round that will change the print
1771 		 */
1772 		private boolean checkForCarry(char[] ca1, int icarry) {
1773 			boolean carry = false;
1774 			if (icarry < ca1.length) {
1775 				if (ca1[icarry] == '6' || ca1[icarry] == '7' || ca1[icarry] == '8' || ca1[icarry] == '9')
1776 					carry = true;
1777 				else if (ca1[icarry] == '5') {
1778 					int ii = icarry + 1;
1779 					for (; ii < ca1.length; ii++)
1780 						if (ca1[ii] != '0')
1781 							break;
1782 					carry = ii < ca1.length;
1783 					if (!carry && icarry > 0) {
1784 						carry =
1785 							(ca1[icarry - 1] == '1'
1786 								|| ca1[icarry - 1] == '3'
1787 								|| ca1[icarry - 1] == '5'
1788 								|| ca1[icarry - 1] == '7'
1789 								|| ca1[icarry - 1] == '9');
1790 					}
1791 				}
1792 			}
1793 			return carry;
1794 		}
1795 		/**
1796 		 * Start the symbolic carry process.  The process
1797 		 * is not quite finished because the symbolic
1798 		 * carry may change the length of the string and
1799 		 * change the exponent (in e format).
1800 		 * @param cLast index of the last digit changed
1801 		 *     by the round
1802 		 * @param cFirst index of the first digit allowed
1803 		 *     to be changed by this phase of the round
1804 		 * @return <code>true</code> if the carry forces
1805 		 *     a round that will change the print still
1806 		 *     more
1807 		 */
1808 		private boolean startSymbolicCarry(char[] ca, int cLast, int cFirst) {
1809 			boolean carry = true;
1810 			for (int i = cLast; carry && i >= cFirst; i--) {
1811 				carry = false;
1812 				switch (ca[i]) {
1813 					case '0' :
1814 						ca[i] = '1';
1815 						break;
1816 					case '1' :
1817 						ca[i] = '2';
1818 						break;
1819 					case '2' :
1820 						ca[i] = '3';
1821 						break;
1822 					case '3' :
1823 						ca[i] = '4';
1824 						break;
1825 					case '4' :
1826 						ca[i] = '5';
1827 						break;
1828 					case '5' :
1829 						ca[i] = '6';
1830 						break;
1831 					case '6' :
1832 						ca[i] = '7';
1833 						break;
1834 					case '7' :
1835 						ca[i] = '8';
1836 						break;
1837 					case '8' :
1838 						ca[i] = '9';
1839 						break;
1840 					case '9' :
1841 						ca[i] = '0';
1842 						carry = true;
1843 						break;
1844 				}
1845 			}
1846 			return carry;
1847 		}
1848 		/**
1849 		 * An intermediate routine on the way to creating
1850 		 * an e format String.  The method decides whether
1851 		 * the input double value is an infinity,
1852 		 * not-a-number, or a finite double and formats
1853 		 * each type of input appropriately.
1854 		 * @param x the double value to be formatted.
1855 		 * @param eChar an 'e' or 'E' to use in the
1856 		 *     converted double value.
1857 		 * @return the converted double value.
1858 		 */
1859 		private String eFormatString(double x, char eChar) {
1860 //			boolean noDigits = false;
1861 			char[] ca4, ca5;
1862 			if (Double.isInfinite(x)) {
1863 				if (x == Double.POSITIVE_INFINITY) {
1864 					if (leadingSign)
1865 						ca4 = "+Inf".toCharArray();
1866 					else if (leadingSpace)
1867 						ca4 = " Inf".toCharArray();
1868 					else
1869 						ca4 = "Inf".toCharArray();
1870 				} else
1871 					ca4 = "-Inf".toCharArray();
1872 //				noDigits = true;
1873 			} else if (Double.isNaN(x)) {
1874 				if (leadingSign)
1875 					ca4 = "+NaN".toCharArray();
1876 				else if (leadingSpace)
1877 					ca4 = " NaN".toCharArray();
1878 				else
1879 					ca4 = "NaN".toCharArray();
1880 //				noDigits = true;
1881 			} else
1882 				ca4 = eFormatDigits(x, eChar);
1883 			ca5 = applyFloatPadding(ca4, false);
1884 			return new String(ca5);
1885 		}
1886 		/**
1887 		 * Apply zero or blank, left or right padding.
1888 		 * @param ca4 array of characters before padding is
1889 		 *     finished
1890 		 * @param noDigits NaN or signed Inf
1891 		 * @return a padded array of characters
1892 		 */
1893 		private char[] applyFloatPadding(char[] ca4, boolean noDigits) {
1894 			char[] ca5 = ca4;
1895 			if (fieldWidthSet) {
1896 				int i, j, nBlanks;
1897 				if (leftJustify) {
1898 					nBlanks = fieldWidth - ca4.length;
1899 					if (nBlanks > 0) {
1900 						ca5 = new char[ca4.length + nBlanks];
1901 						for (i = 0; i < ca4.length; i++)
1902 							ca5[i] = ca4[i];
1903 						for (j = 0; j < nBlanks; j++, i++)
1904 							ca5[i] = ' ';
1905 					}
1906 				} else if (!leadingZeros || noDigits) {
1907 					nBlanks = fieldWidth - ca4.length;
1908 					if (nBlanks > 0) {
1909 						ca5 = new char[ca4.length + nBlanks];
1910 						for (i = 0; i < nBlanks; i++)
1911 							ca5[i] = ' ';
1912 						for (j = 0; j < ca4.length; i++, j++)
1913 							ca5[i] = ca4[j];
1914 					}
1915 				} else if (leadingZeros) {
1916 					nBlanks = fieldWidth - ca4.length;
1917 					if (nBlanks > 0) {
1918 						ca5 = new char[ca4.length + nBlanks];
1919 						i = 0;
1920 						j = 0;
1921 						if (ca4[0] == '-') {
1922 							ca5[0] = '-';
1923 							i++;
1924 							j++;
1925 						}
1926 						for (int k = 0; k < nBlanks; i++, k++)
1927 							ca5[i] = '0';
1928 						for (; j < ca4.length; i++, j++)
1929 							ca5[i] = ca4[j];
1930 					}
1931 				}
1932 			}
1933 			return ca5;
1934 		}
1935 		/**
1936 		 * Format method for the f conversion character.
1937 		 * @param x the double to format.
1938 		 * @return the formatted String.
1939 		 */
1940 		private String printFFormat(double x) {
1941 			return fFormatString(x);
1942 		}
1943 		/**
1944 		 * Format method for the e or E conversion
1945 		 * character.
1946 		 * @param x the double to format.
1947 		 * @return the formatted String.
1948 		 */
1949 		private String printEFormat(double x) {
1950 			if (conversionCharacter == 'e')
1951 				return eFormatString(x, 'e');
1952 			else
1953 				return eFormatString(x, 'E');
1954 		}
1955 		/**
1956 		 * Format method for the g conversion character.
1957 		 *
1958 		 * For g format, the flag character '-', means that
1959 		 *  the output should be left justified within the
1960 		 * field.  The default is to pad with blanks on the
1961 		 * left.  '+' character means that the conversion
1962 		 * will always begin with a sign (+ or -).  The
1963 		 * blank flag character means that a non-negative
1964 		 * input will be preceded with a blank.  If both a
1965 		 * '+' and a ' ' are specified, the blank flag is
1966 		 * ignored.  The '0' flag character implies that
1967 		 * padding to the field width will be done with
1968 		 * zeros instead of blanks.
1969 		 *
1970 		 * The field width is treated as the minimum number
1971 		 * of characters to be printed.  The default is to
1972 		 * add no padding.  Padding is with blanks by
1973 		 * default.
1974 		 *
1975 		 * The precision, if set, is the minimum number of
1976 		 * digits to appear after the radix character.
1977 		 * Padding is with trailing 0s.
1978 		 * @param x the double to format.
1979 		 * @return the formatted String.
1980 		 */
1981 		private String printGFormat(double x) {
1982 			String sx, sy, sz, ret;
1983 			int savePrecision = precision;
1984 			int i;
1985 			char[] ca4, ca5;
1986 //			boolean noDigits = false;
1987 			if (Double.isInfinite(x)) {
1988 				if (x == Double.POSITIVE_INFINITY) {
1989 					if (leadingSign)
1990 						ca4 = "+Inf".toCharArray();
1991 					else if (leadingSpace)
1992 						ca4 = " Inf".toCharArray();
1993 					else
1994 						ca4 = "Inf".toCharArray();
1995 				} else
1996 					ca4 = "-Inf".toCharArray();
1997 //				noDigits = true;
1998 			} else if (Double.isNaN(x)) {
1999 				if (leadingSign)
2000 					ca4 = "+NaN".toCharArray();
2001 				else if (leadingSpace)
2002 					ca4 = " NaN".toCharArray();
2003 				else
2004 					ca4 = "NaN".toCharArray();
2005 //				noDigits = true;
2006 			} else {
2007 				if (!precisionSet)
2008 					precision = defaultDigits;
2009 				if (precision == 0)
2010 					precision = 1;
2011 				int ePos = -1;
2012 				if (conversionCharacter == 'g') {
2013 					sx = eFormatString(x, 'e').trim();
2014 					ePos = sx.indexOf('e');
2015 				} else {
2016 					sx = eFormatString(x, 'E').trim();
2017 					ePos = sx.indexOf('E');
2018 				}
2019 				i = ePos + 1;
2020 				int expon = 0;
2021 				if (sx.charAt(i) == '-') {
2022 					for (++i; i < sx.length(); i++)
2023 						if (sx.charAt(i) != '0')
2024 							break;
2025 					if (i < sx.length())
2026 						expon = -Integer.parseInt(sx.substring(i));
2027 				} else {
2028 					if (sx.charAt(i) == '+')
2029 						++i;
2030 					for (; i < sx.length(); i++)
2031 						if (sx.charAt(i) != '0')
2032 							break;
2033 					if (i < sx.length())
2034 						expon = Integer.parseInt(sx.substring(i));
2035 				}
2036 				// Trim trailing zeros.
2037 				// If the radix character is not followed by
2038 				// a digit, trim it, too.
2039 				if (!alternateForm) {
2040 					if (expon >= -4 && expon < precision)
2041 						sy = fFormatString(x).trim();
2042 					else
2043 						sy = sx.substring(0, ePos);
2044 					i = sy.length() - 1;
2045 					for (; i >= 0; i--)
2046 						if (sy.charAt(i) != '0')
2047 							break;
2048 					if (i >= 0 && sy.charAt(i) == '.')
2049 						i--;
2050 					if (i == -1)
2051 						sz = "0";
2052 					else if (!Character.isDigit(sy.charAt(i)))
2053 						sz = sy.substring(0, i + 1) + "0";
2054 					else
2055 						sz = sy.substring(0, i + 1);
2056 					if (expon >= -4 && expon < precision)
2057 						ret = sz;
2058 					else
2059 						ret = sz + sx.substring(ePos);
2060 				} else {
2061 					if (expon >= -4 && expon < precision)
2062 						ret = fFormatString(x).trim();
2063 					else
2064 						ret = sx;
2065 				}
2066 				// leading space was trimmed off during
2067 				// construction
2068 				if (leadingSpace)
2069 					if (x >= 0)
2070 						ret = " " + ret;
2071 				ca4 = ret.toCharArray();
2072 			}
2073 			// Pad with blanks or zeros.
2074 			ca5 = applyFloatPadding(ca4, false);
2075 			precision = savePrecision;
2076 			return new String(ca5);
2077 		}
2078 		/**
2079 		 * Format method for the d conversion specifer and
2080 		 * short argument.
2081 		 *
2082 		 * For d format, the flag character '-', means that
2083 		 * the output should be left justified within the
2084 		 * field.  The default is to pad with blanks on the
2085 		 * left.  A '+' character means that the conversion
2086 		 * will always begin with a sign (+ or -).  The
2087 		 * blank flag character means that a non-negative
2088 		 * input will be preceded with a blank.  If both a
2089 		 * '+' and a ' ' are specified, the blank flag is
2090 		 * ignored.  The '0' flag character implies that
2091 		 * padding to the field width will be done with
2092 		 * zeros instead of blanks.
2093 		 *
2094 		 * The field width is treated as the minimum number
2095 		 * of characters to be printed.  The default is to
2096 		 * add no padding.  Padding is with blanks by
2097 		 * default.
2098 		 *
2099 		 * The precision, if set, is the minimum number of
2100 		 * digits to appear.  Padding is with leading 0s.
2101 		 * @param x the short to format.
2102 		 * @return the formatted String.
2103 		 */
2104 		private String printDFormat(short x) {
2105 			return printDFormat(Short.toString(x));
2106 		}
2107 		/**
2108 		 * Format method for the d conversion character and
2109 		 * long argument.
2110 		 *
2111 		 * For d format, the flag character '-', means that
2112 		 * the output should be left justified within the
2113 		 * field.  The default is to pad with blanks on the
2114 		 * left.  A '+' character means that the conversion
2115 		 * will always begin with a sign (+ or -).  The
2116 		 * blank flag character means that a non-negative
2117 		 * input will be preceded with a blank.  If both a
2118 		 * '+' and a ' ' are specified, the blank flag is
2119 		 * ignored.  The '0' flag character implies that
2120 		 * padding to the field width will be done with
2121 		 * zeros instead of blanks.
2122 		 *
2123 		 * The field width is treated as the minimum number
2124 		 * of characters to be printed.  The default is to
2125 		 * add no padding.  Padding is with blanks by
2126 		 * default.
2127 		 *
2128 		 * The precision, if set, is the minimum number of
2129 		 * digits to appear.  Padding is with leading 0s.
2130 		 * @param x the long to format.
2131 		 * @return the formatted String.
2132 		 */
2133 		private String printDFormat(long x) {
2134 			return printDFormat(Long.toString(x));
2135 		}
2136 		/**
2137 		 * Format method for the d conversion character and
2138 		 * int argument.
2139 		 *
2140 		 * For d format, the flag character '-', means that
2141 		 * the output should be left justified within the
2142 		 * field.  The default is to pad with blanks on the
2143 		 * left.  A '+' character means that the conversion
2144 		 * will always begin with a sign (+ or -).  The
2145 		 * blank flag character means that a non-negative
2146 		 * input will be preceded with a blank.  If both a
2147 		 * '+' and a ' ' are specified, the blank flag is
2148 		 * ignored.  The '0' flag character implies that
2149 		 * padding to the field width will be done with
2150 		 * zeros instead of blanks.
2151 		 *
2152 		 * The field width is treated as the minimum number
2153 		 * of characters to be printed.  The default is to
2154 		 * add no padding.  Padding is with blanks by
2155 		 * default.
2156 		 *
2157 		 * The precision, if set, is the minimum number of
2158 		 * digits to appear.  Padding is with leading 0s.
2159 		 * @param x the int to format.
2160 		 * @return the formatted String.
2161 		 */
2162 		private String printDFormat(int x) {
2163 			return printDFormat(Integer.toString(x));
2164 		}
2165 		/**
2166 		 * Utility method for formatting using the d
2167 		 * conversion character.
2168 		 * @param sx the String to format, the result of
2169 		 *     converting a short, int, or long to a
2170 		 *     String.
2171 		 * @return the formatted String.
2172 		 */
2173 		private String printDFormat(String sx) {
2174 			int nLeadingZeros = 0;
2175 			int nBlanks = 0, n = 0;
2176 			int i = 0, jFirst = 0;
2177 			boolean neg = sx.charAt(0) == '-';
2178 			if (sx.equals("0") && precisionSet && precision == 0)
2179 				sx = "";
2180 			if (!neg) {
2181 				if (precisionSet && sx.length() < precision)
2182 					nLeadingZeros = precision - sx.length();
2183 			} else {
2184 				if (precisionSet && (sx.length() - 1) < precision)
2185 					nLeadingZeros = precision - sx.length() + 1;
2186 			}
2187 			if (nLeadingZeros < 0)
2188 				nLeadingZeros = 0;
2189 			if (fieldWidthSet) {
2190 				nBlanks = fieldWidth - nLeadingZeros - sx.length();
2191 				if (!neg && (leadingSign || leadingSpace))
2192 					nBlanks--;
2193 			}
2194 			if (nBlanks < 0)
2195 				nBlanks = 0;
2196 			if (leadingSign && !neg)
2197 				n++;
2198 			else if (leadingSpace)
2199 				n++;
2200 			n += nBlanks;
2201 			n += nLeadingZeros;
2202 			n += sx.length();
2203 			char[] ca = new char[n];
2204 			if (leftJustify) {
2205 				if (neg)
2206 					ca[i++] = '-';
2207 				else if (leadingSign)
2208 					ca[i++] = '+';
2209 				else if (leadingSpace)
2210 					ca[i++] = ' ';
2211 				char[] csx = sx.toCharArray();
2212 				jFirst = neg ? 1 : 0;
2213 				for (int j = 0; j < nLeadingZeros; i++, j++)
2214 					ca[i] = '0';
2215 				for (int j = jFirst; j < csx.length; j++, i++)
2216 					ca[i] = csx[j];
2217 				for (int j = 0; j < nBlanks; i++, j++)
2218 					ca[i] = ' ';
2219 			} else {
2220 				if (!leadingZeros) {
2221 					for (i = 0; i < nBlanks; i++)
2222 						ca[i] = ' ';
2223 					if (neg)
2224 						ca[i++] = '-';
2225 					else if (leadingSign)
2226 						ca[i++] = '+';
2227 					else if (leadingSpace)
2228 						ca[i++] = ' ';
2229 				} else {
2230 					if (neg)
2231 						ca[i++] = '-';
2232 					else if (leadingSign)
2233 						ca[i++] = '+';
2234 					else if (leadingSpace)
2235 						ca[i++] = ' ';
2236 					for (int j = 0; j < nBlanks; j++, i++)
2237 						ca[i] = '0';
2238 				}
2239 				for (int j = 0; j < nLeadingZeros; j++, i++)
2240 					ca[i] = '0';
2241 				char[] csx = sx.toCharArray();
2242 				jFirst = neg ? 1 : 0;
2243 				for (int j = jFirst; j < csx.length; j++, i++)
2244 					ca[i] = csx[j];
2245 			}
2246 			return new String(ca);
2247 		}
2248 		/**
2249 		 * Format method for the x conversion character and
2250 		 * short argument.
2251 		 *
2252 		 * For x format, the flag character '-', means that
2253 		 * the output should be left justified within the
2254 		 * field.  The default is to pad with blanks on the
2255 		 * left.  The '#' flag character means to lead with
2256 		 * '0x'.
2257 		 *
2258 		 * The field width is treated as the minimum number
2259 		 * of characters to be printed.  The default is to
2260 		 * add no padding.  Padding is with blanks by
2261 		 * default.
2262 		 *
2263 		 * The precision, if set, is the minimum number of
2264 		 * digits to appear.  Padding is with leading 0s.
2265 		 * @param x the short to format.
2266 		 * @return the formatted String.
2267 		 */
2268 		private String printXFormat(short x) {
2269 			String sx = null;
2270 			if (x == Short.MIN_VALUE)
2271 				sx = "8000";
2272 			else if (x < 0) {
2273 				String t;
2274 				if (x == Short.MIN_VALUE)
2275 					t = "0";
2276 				else {
2277 					t = Integer.toString((~(-x - 1)) ^ Short.MIN_VALUE, 16);
2278 					if (t.charAt(0) == 'F' || t.charAt(0) == 'f')
2279 						t = t.substring(16, 32);
2280 				}
2281 				switch (t.length()) {
2282 					case 1 :
2283 						sx = "800" + t;
2284 						break;
2285 					case 2 :
2286 						sx = "80" + t;
2287 						break;
2288 					case 3 :
2289 						sx = "8" + t;
2290 						break;
2291 					case 4 :
2292 						switch (t.charAt(0)) {
2293 							case '1' :
2294 								sx = "9" + t.substring(1, 4);
2295 								break;
2296 							case '2' :
2297 								sx = "a" + t.substring(1, 4);
2298 								break;
2299 							case '3' :
2300 								sx = "b" + t.substring(1, 4);
2301 								break;
2302 							case '4' :
2303 								sx = "c" + t.substring(1, 4);
2304 								break;
2305 							case '5' :
2306 								sx = "d" + t.substring(1, 4);
2307 								break;
2308 							case '6' :
2309 								sx = "e" + t.substring(1, 4);
2310 								break;
2311 							case '7' :
2312 								sx = "f" + t.substring(1, 4);
2313 								break;
2314 						}
2315 						break;
2316 				}
2317 			} else
2318 				sx = Integer.toString((int) x, 16);
2319 			return printXFormat(sx);
2320 		}
2321 		/**
2322 		 * Format method for the x conversion character and
2323 		 * long argument.
2324 		 *
2325 		 * For x format, the flag character '-', means that
2326 		 * the output should be left justified within the
2327 		 * field.  The default is to pad with blanks on the
2328 		 * left.  The '#' flag character means to lead with
2329 		 * '0x'.
2330 		 *
2331 		 * The field width is treated as the minimum number
2332 		 * of characters to be printed.  The default is to
2333 		 * add no padding.  Padding is with blanks by
2334 		 * default.
2335 		 *
2336 		 * The precision, if set, is the minimum number of
2337 		 * digits to appear.  Padding is with leading 0s.
2338 		 * @param x the long to format.
2339 		 * @return the formatted String.
2340 		 */
2341 		private String printXFormat(long x) {
2342 			String sx = null;
2343 			if (x == Long.MIN_VALUE)
2344 				sx = "8000000000000000";
2345 			else if (x < 0) {
2346 				String t = Long.toString((~(-x - 1)) ^ Long.MIN_VALUE, 16);
2347 				switch (t.length()) {
2348 					case 1 :
2349 						sx = "800000000000000" + t;
2350 						break;
2351 					case 2 :
2352 						sx = "80000000000000" + t;
2353 						break;
2354 					case 3 :
2355 						sx = "8000000000000" + t;
2356 						break;
2357 					case 4 :
2358 						sx = "800000000000" + t;
2359 						break;
2360 					case 5 :
2361 						sx = "80000000000" + t;
2362 						break;
2363 					case 6 :
2364 						sx = "8000000000" + t;
2365 						break;
2366 					case 7 :
2367 						sx = "800000000" + t;
2368 						break;
2369 					case 8 :
2370 						sx = "80000000" + t;
2371 						break;
2372 					case 9 :
2373 						sx = "8000000" + t;
2374 						break;
2375 					case 10 :
2376 						sx = "800000" + t;
2377 						break;
2378 					case 11 :
2379 						sx = "80000" + t;
2380 						break;
2381 					case 12 :
2382 						sx = "8000" + t;
2383 						break;
2384 					case 13 :
2385 						sx = "800" + t;
2386 						break;
2387 					case 14 :
2388 						sx = "80" + t;
2389 						break;
2390 					case 15 :
2391 						sx = "8" + t;
2392 						break;
2393 					case 16 :
2394 						switch (t.charAt(0)) {
2395 							case '1' :
2396 								sx = "9" + t.substring(1, 16);
2397 								break;
2398 							case '2' :
2399 								sx = "a" + t.substring(1, 16);
2400 								break;
2401 							case '3' :
2402 								sx = "b" + t.substring(1, 16);
2403 								break;
2404 							case '4' :
2405 								sx = "c" + t.substring(1, 16);
2406 								break;
2407 							case '5' :
2408 								sx = "d" + t.substring(1, 16);
2409 								break;
2410 							case '6' :
2411 								sx = "e" + t.substring(1, 16);
2412 								break;
2413 							case '7' :
2414 								sx = "f" + t.substring(1, 16);
2415 								break;
2416 						}
2417 						break;
2418 				}
2419 			} else
2420 				sx = Long.toString(x, 16);
2421 			return printXFormat(sx);
2422 		}
2423 		/**
2424 		 * Format method for the x conversion character and
2425 		 * int argument.
2426 		 *
2427 		 * For x format, the flag character '-', means that
2428 		 * the output should be left justified within the
2429 		 * field.  The default is to pad with blanks on the
2430 		 * left.  The '#' flag character means to lead with
2431 		 * '0x'.
2432 		 *
2433 		 * The field width is treated as the minimum number
2434 		 * of characters to be printed.  The default is to
2435 		 * add no padding.  Padding is with blanks by
2436 		 * default.
2437 		 *
2438 		 * The precision, if set, is the minimum number of
2439 		 * digits to appear.  Padding is with leading 0s.
2440 		 * @param x the int to format.
2441 		 * @return the formatted String.
2442 		 */
2443 		private String printXFormat(int x) {
2444 			String sx = null;
2445 			if (x == Integer.MIN_VALUE)
2446 				sx = "80000000";
2447 			else if (x < 0) {
2448 				String t = Integer.toString((~(-x - 1)) ^ Integer.MIN_VALUE, 16);
2449 				switch (t.length()) {
2450 					case 1 :
2451 						sx = "8000000" + t;
2452 						break;
2453 					case 2 :
2454 						sx = "800000" + t;
2455 						break;
2456 					case 3 :
2457 						sx = "80000" + t;
2458 						break;
2459 					case 4 :
2460 						sx = "8000" + t;
2461 						break;
2462 					case 5 :
2463 						sx = "800" + t;
2464 						break;
2465 					case 6 :
2466 						sx = "80" + t;
2467 						break;
2468 					case 7 :
2469 						sx = "8" + t;
2470 						break;
2471 					case 8 :
2472 						switch (t.charAt(0)) {
2473 							case '1' :
2474 								sx = "9" + t.substring(1, 8);
2475 								break;
2476 							case '2' :
2477 								sx = "a" + t.substring(1, 8);
2478 								break;
2479 							case '3' :
2480 								sx = "b" + t.substring(1, 8);
2481 								break;
2482 							case '4' :
2483 								sx = "c" + t.substring(1, 8);
2484 								break;
2485 							case '5' :
2486 								sx = "d" + t.substring(1, 8);
2487 								break;
2488 							case '6' :
2489 								sx = "e" + t.substring(1, 8);
2490 								break;
2491 							case '7' :
2492 								sx = "f" + t.substring(1, 8);
2493 								break;
2494 						}
2495 						break;
2496 				}
2497 			} else
2498 				sx = Integer.toString(x, 16);
2499 			return printXFormat(sx);
2500 		}
2501 		/**
2502 		 * Utility method for formatting using the x
2503 		 * conversion character.
2504 		 * @param sx the String to format, the result of
2505 		 *     converting a short, int, or long to a
2506 		 *     String.
2507 		 * @return the formatted String.
2508 		 */
2509 		private String printXFormat(String sx) {
2510 			int nLeadingZeros = 0;
2511 			int nBlanks = 0;
2512 			if (sx.equals("0") && precisionSet && precision == 0)
2513 				sx = "";
2514 			if (precisionSet)
2515 				nLeadingZeros = precision - sx.length();
2516 			if (nLeadingZeros < 0)
2517 				nLeadingZeros = 0;
2518 			if (fieldWidthSet) {
2519 				nBlanks = fieldWidth - nLeadingZeros - sx.length();
2520 				if (alternateForm)
2521 					nBlanks = nBlanks - 2;
2522 			}
2523 			if (nBlanks < 0)
2524 				nBlanks = 0;
2525 			int n = 0;
2526 			if (alternateForm)
2527 				n += 2;
2528 			n += nLeadingZeros;
2529 			n += sx.length();
2530 			n += nBlanks;
2531 			char[] ca = new char[n];
2532 			int i = 0;
2533 			if (leftJustify) {
2534 				if (alternateForm) {
2535 					ca[i++] = '0';
2536 					ca[i++] = 'x';
2537 				}
2538 				for (int j = 0; j < nLeadingZeros; j++, i++)
2539 					ca[i] = '0';
2540 				char[] csx = sx.toCharArray();
2541 				for (int j = 0; j < csx.length; j++, i++)
2542 					ca[i] = csx[j];
2543 				for (int j = 0; j < nBlanks; j++, i++)
2544 					ca[i] = ' ';
2545 			} else {
2546 				if (!leadingZeros)
2547 					for (int j = 0; j < nBlanks; j++, i++)
2548 						ca[i] = ' ';
2549 				if (alternateForm) {
2550 					ca[i++] = '0';
2551 					ca[i++] = 'x';
2552 				}
2553 				if (leadingZeros)
2554 					for (int j = 0; j < nBlanks; j++, i++)
2555 						ca[i] = '0';
2556 				for (int j = 0; j < nLeadingZeros; j++, i++)
2557 					ca[i] = '0';
2558 				char[] csx = sx.toCharArray();
2559 				for (int j = 0; j < csx.length; j++, i++)
2560 					ca[i] = csx[j];
2561 			}
2562 			String caReturn = new String(ca);
2563 			if (conversionCharacter == 'X')
2564 				caReturn = caReturn.toUpperCase();
2565 			return caReturn;
2566 		}
2567 		/**
2568 		 * Format method for the o conversion character and
2569 		 * short argument.
2570 		 *
2571 		 * For o format, the flag character '-', means that
2572 		 * the output should be left justified within the
2573 		 * field.  The default is to pad with blanks on the 
2574 		 * left.  The '#' flag character means that the
2575 		 * output begins with a leading 0 and the precision
2576 		 * is increased by 1.
2577 		 *
2578 		 * The field width is treated as the minimum number
2579 		 * of characters to be printed.  The default is to
2580 		 * add no padding.  Padding is with blanks by
2581 		 * default.
2582 		 *
2583 		 * The precision, if set, is the minimum number of
2584 		 * digits to appear.  Padding is with leading 0s.
2585 		 * @param x the short to format.
2586 		 * @return the formatted String.
2587 		 */
2588 		private String printOFormat(short x) {
2589 			String sx = null;
2590 			if (x == Short.MIN_VALUE)
2591 				sx = "100000";
2592 			else if (x < 0) {
2593 				String t = Integer.toString((~(-x - 1)) ^ Short.MIN_VALUE, 8);
2594 				switch (t.length()) {
2595 					case 1 :
2596 						sx = "10000" + t;
2597 						break;
2598 					case 2 :
2599 						sx = "1000" + t;
2600 						break;
2601 					case 3 :
2602 						sx = "100" + t;
2603 						break;
2604 					case 4 :
2605 						sx = "10" + t;
2606 						break;
2607 					case 5 :
2608 						sx = "1" + t;
2609 						break;
2610 				}
2611 			} else
2612 				sx = Integer.toString((int) x, 8);
2613 			return printOFormat(sx);
2614 		}
2615 		/**
2616 		 * Format method for the o conversion character and
2617 		 * long argument.
2618 		 *
2619 		 * For o format, the flag character '-', means that
2620 		 * the output should be left justified within the
2621 		 * field.  The default is to pad with blanks on the 
2622 		 * left.  The '#' flag character means that the
2623 		 * output begins with a leading 0 and the precision
2624 		 * is increased by 1.
2625 		 *
2626 		 * The field width is treated as the minimum number
2627 		 * of characters to be printed.  The default is to
2628 		 * add no padding.  Padding is with blanks by
2629 		 * default.
2630 		 *
2631 		 * The precision, if set, is the minimum number of
2632 		 * digits to appear.  Padding is with leading 0s.
2633 		 * @param x the long to format.
2634 		 * @return the formatted String.
2635 		 */
2636 		private String printOFormat(long x) {
2637 			String sx = null;
2638 			if (x == Long.MIN_VALUE)
2639 				sx = "1000000000000000000000";
2640 			else if (x < 0) {
2641 				String t = Long.toString((~(-x - 1)) ^ Long.MIN_VALUE, 8);
2642 				switch (t.length()) {
2643 					case 1 :
2644 						sx = "100000000000000000000" + t;
2645 						break;
2646 					case 2 :
2647 						sx = "10000000000000000000" + t;
2648 						break;
2649 					case 3 :
2650 						sx = "1000000000000000000" + t;
2651 						break;
2652 					case 4 :
2653 						sx = "100000000000000000" + t;
2654 						break;
2655 					case 5 :
2656 						sx = "10000000000000000" + t;
2657 						break;
2658 					case 6 :
2659 						sx = "1000000000000000" + t;
2660 						break;
2661 					case 7 :
2662 						sx = "100000000000000" + t;
2663 						break;
2664 					case 8 :
2665 						sx = "10000000000000" + t;
2666 						break;
2667 					case 9 :
2668 						sx = "1000000000000" + t;
2669 						break;
2670 					case 10 :
2671 						sx = "100000000000" + t;
2672 						break;
2673 					case 11 :
2674 						sx = "10000000000" + t;
2675 						break;
2676 					case 12 :
2677 						sx = "1000000000" + t;
2678 						break;
2679 					case 13 :
2680 						sx = "100000000" + t;
2681 						break;
2682 					case 14 :
2683 						sx = "10000000" + t;
2684 						break;
2685 					case 15 :
2686 						sx = "1000000" + t;
2687 						break;
2688 					case 16 :
2689 						sx = "100000" + t;
2690 						break;
2691 					case 17 :
2692 						sx = "10000" + t;
2693 						break;
2694 					case 18 :
2695 						sx = "1000" + t;
2696 						break;
2697 					case 19 :
2698 						sx = "100" + t;
2699 						break;
2700 					case 20 :
2701 						sx = "10" + t;
2702 						break;
2703 					case 21 :
2704 						sx = "1" + t;
2705 						break;
2706 				}
2707 			} else
2708 				sx = Long.toString(x, 8);
2709 			return printOFormat(sx);
2710 		}
2711 		/**
2712 		 * Format method for the o conversion character and
2713 		 * int argument.
2714 		 *
2715 		 * For o format, the flag character '-', means that
2716 		 * the output should be left justified within the
2717 		 * field.  The default is to pad with blanks on the
2718 		 * left.  The '#' flag character means that the
2719 		 * output begins with a leading 0 and the precision
2720 		 * is increased by 1.
2721 		 *
2722 		 * The field width is treated as the minimum number
2723 		 * of characters to be printed.  The default is to
2724 		 * add no padding.  Padding is with blanks by
2725 		 * default.
2726 		 *
2727 		 * The precision, if set, is the minimum number of
2728 		 * digits to appear.  Padding is with leading 0s.
2729 		 * @param x the int to format.
2730 		 * @return the formatted String.
2731 		 */
2732 		private String printOFormat(int x) {
2733 			String sx = null;
2734 			if (x == Integer.MIN_VALUE)
2735 				sx = "20000000000";
2736 			else if (x < 0) {
2737 				String t = Integer.toString((~(-x - 1)) ^ Integer.MIN_VALUE, 8);
2738 				switch (t.length()) {
2739 					case 1 :
2740 						sx = "2000000000" + t;
2741 						break;
2742 					case 2 :
2743 						sx = "200000000" + t;
2744 						break;
2745 					case 3 :
2746 						sx = "20000000" + t;
2747 						break;
2748 					case 4 :
2749 						sx = "2000000" + t;
2750 						break;
2751 					case 5 :
2752 						sx = "200000" + t;
2753 						break;
2754 					case 6 :
2755 						sx = "20000" + t;
2756 						break;
2757 					case 7 :
2758 						sx = "2000" + t;
2759 						break;
2760 					case 8 :
2761 						sx = "200" + t;
2762 						break;
2763 					case 9 :
2764 						sx = "20" + t;
2765 						break;
2766 					case 10 :
2767 						sx = "2" + t;
2768 						break;
2769 					case 11 :
2770 						sx = "3" + t.substring(1);
2771 						break;
2772 				}
2773 			} else
2774 				sx = Integer.toString(x, 8);
2775 			return printOFormat(sx);
2776 		}
2777 		/**
2778 		 * Utility method for formatting using the o
2779 		 * conversion character.
2780 		 * @param sx the String to format, the result of
2781 		 *     converting a short, int, or long to a
2782 		 *     String.
2783 		 * @return the formatted String.
2784 		 */
2785 		private String printOFormat(String sx) {
2786 			int nLeadingZeros = 0;
2787 			int nBlanks = 0;
2788 			if (sx.equals("0") && precisionSet && precision == 0)
2789 				sx = "";
2790 			if (precisionSet)
2791 				nLeadingZeros = precision - sx.length();
2792 			if (alternateForm)
2793 				nLeadingZeros++;
2794 			if (nLeadingZeros < 0)
2795 				nLeadingZeros = 0;
2796 			if (fieldWidthSet)
2797 				nBlanks = fieldWidth - nLeadingZeros - sx.length();
2798 			if (nBlanks < 0)
2799 				nBlanks = 0;
2800 			int n = nLeadingZeros + sx.length() + nBlanks;
2801 			char[] ca = new char[n];
2802 			int i;
2803 			if (leftJustify) {
2804 				for (i = 0; i < nLeadingZeros; i++)
2805 					ca[i] = '0';
2806 				char[] csx = sx.toCharArray();
2807 				for (int j = 0; j < csx.length; j++, i++)
2808 					ca[i] = csx[j];
2809 				for (int j = 0; j < nBlanks; j++, i++)
2810 					ca[i] = ' ';
2811 			} else {
2812 				if (leadingZeros)
2813 					for (i = 0; i < nBlanks; i++)
2814 						ca[i] = '0';
2815 				else
2816 					for (i = 0; i < nBlanks; i++)
2817 						ca[i] = ' ';
2818 				for (int j = 0; j < nLeadingZeros; j++, i++)
2819 					ca[i] = '0';
2820 				char[] csx = sx.toCharArray();
2821 				for (int j = 0; j < csx.length; j++, i++)
2822 					ca[i] = csx[j];
2823 			}
2824 			return new String(ca);
2825 		}
2826 		/**
2827 		 * Format method for the c conversion character and
2828 		 * char argument.
2829 		 *
2830 		 * The only flag character that affects c format is
2831 		 * the '-', meaning that the output should be left
2832 		 * justified within the field.  The default is to
2833 		 * pad with blanks on the left.
2834 		 *
2835 		 * The field width is treated as the minimum number
2836 		 * of characters to be printed.  Padding is with
2837 		 * blanks by default.  The default width is 1.
2838 		 *
2839 		 * The precision, if set, is ignored.
2840 		 * @param x the char to format.
2841 		 * @return the formatted String.
2842 		 */
2843 		private String printCFormat(char x) {
2844 			int nPrint = 1;
2845 			int width = fieldWidth;
2846 			if (!fieldWidthSet)
2847 				width = nPrint;
2848 			char[] ca = new char[width];
2849 			int i = 0;
2850 			if (leftJustify) {
2851 				ca[0] = x;
2852 				for (i = 1; i <= width - nPrint; i++)
2853 					ca[i] = ' ';
2854 			} else {
2855 				for (i = 0; i < width - nPrint; i++)
2856 					ca[i] = ' ';
2857 				ca[i] = x;
2858 			}
2859 			return new String(ca);
2860 		}
2861 		/**
2862 		 * Format method for the s conversion character and
2863 		 * String argument.
2864 		 *
2865 		 * The only flag character that affects s format is
2866 		 * the '-', meaning that the output should be left
2867 		 * justified within the field.  The default is to
2868 		 * pad with blanks on the left.
2869 		 *
2870 		 * The field width is treated as the minimum number
2871 		 * of characters to be printed.  The default is the
2872 		 * smaller of the number of characters in the the
2873 		 * input and the precision.  Padding is with blanks
2874 		 * by default.
2875 		 *
2876 		 * The precision, if set, specifies the maximum
2877 		 * number of characters to be printed from the
2878 		 * string.  A null digit string is treated
2879 		 * as a 0.  The default is not to set a maximum
2880 		 * number of characters to be printed.
2881 		 * @param x the String to format.
2882 		 * @return the formatted String.
2883 		 */
2884 		private String printSFormat(String x) {
2885 			int nPrint = x.length();
2886 			int width = fieldWidth;
2887 			if (precisionSet && nPrint > precision)
2888 				nPrint = precision;
2889 			if (!fieldWidthSet)
2890 				width = nPrint;
2891 			int n = 0;
2892 			if (width > nPrint)
2893 				n += width - nPrint;
2894 			if (nPrint >= x.length())
2895 				n += x.length();
2896 			else
2897 				n += nPrint;
2898 			char[] ca = new char[n];
2899 			int i = 0;
2900 			if (leftJustify) {
2901 				if (nPrint >= x.length()) {
2902 					char[] csx = x.toCharArray();
2903 					for (i = 0; i < x.length(); i++)
2904 						ca[i] = csx[i];
2905 				} else {
2906 					char[] csx = x.substring(0, nPrint).toCharArray();
2907 					for (i = 0; i < nPrint; i++)
2908 						ca[i] = csx[i];
2909 				}
2910 				for (int j = 0; j < width - nPrint; j++, i++)
2911 					ca[i] = ' ';
2912 			} else {
2913 				for (i = 0; i < width - nPrint; i++)
2914 					ca[i] = ' ';
2915 				if (nPrint >= x.length()) {
2916 					char[] csx = x.toCharArray();
2917 					for (int j = 0; j < x.length(); i++, j++)
2918 						ca[i] = csx[j];
2919 				} else {
2920 					char[] csx = x.substring(0, nPrint).toCharArray();
2921 					for (int j = 0; j < nPrint; i++, j++)
2922 						ca[i] = csx[j];
2923 				}
2924 			}
2925 			return new String(ca);
2926 		}
2927 		/**
2928 		 * Check for a conversion character.  If it is
2929 		 * there, store it.
2930 		 * @return <code>true</code> if the conversion
2931 		 *     character is there, and
2932 		 *     <code>false</code> otherwise.
2933 		 */
2934 		private boolean setConversionCharacter() {
2935 			/* idfgGoxXeEcs */
2936 			boolean ret = false;
2937 			conversionCharacter = '\0';
2938 			if (pos < fmt.length()) {
2939 				char c = fmt.charAt(pos);
2940 				if (c == 'i'
2941 					|| c == 'd'
2942 					|| c == 'f'
2943 					|| c == 'g'
2944 					|| c == 'G'
2945 					|| c == 'o'
2946 					|| c == 'x'
2947 					|| c == 'X'
2948 					|| c == 'e'
2949 					|| c == 'E'
2950 					|| c == 'c'
2951 					|| c == 's'
2952 					|| c == '%') {
2953 					conversionCharacter = c;
2954 					pos++;
2955 					ret = true;
2956 				}
2957 			}
2958 			return ret;
2959 		}
2960 		/**
2961 		 * Check for an h, l, or L in a format.  An L is
2962 		 * used to control the minimum number of digits
2963 		 * in an exponent when using floating point
2964 		 * formats.  An l or h is used to control
2965 		 * conversion of the input to a long or short,
2966 		 * respectively, before formatting.  If any of
2967 		 * these is present, store them.
2968 		 */
2969 		private void setOptionalHL() {
2970 			optionalh = false;
2971 			optionall = false;
2972 			optionalL = false;
2973 			if (pos < fmt.length()) {
2974 				char c = fmt.charAt(pos);
2975 				if (c == 'h') {
2976 					optionalh = true;
2977 					pos++;
2978 				} else if (c == 'l') {
2979 					optionall = true;
2980 					pos++;
2981 				} else if (c == 'L') {
2982 					optionalL = true;
2983 					pos++;
2984 				}
2985 			}
2986 		}
2987 		/**
2988 		 * Set the precision.
2989 		 */
2990 		private void setPrecisionE() {
2991 			if (pos<fmt.length() && Character.isDigit(fmt.charAt(pos))) {
2992 				precisionE= Integer.parseInt(fmt.substring(pos,pos+1));
2993 				if (precisionE>3) precisionE=3;
2994 				if (precisionE<1) precisionE=1;
2995 				pos++;
2996 			}
2997 		}
2998 		/**
2999 		 * Set the precision.
3000 		 */
3001 		private void setPrecision() {
3002 			int firstPos = pos;
3003 			precisionSet = false;
3004 			if (pos < fmt.length() && fmt.charAt(pos) == '.') {
3005 				pos++;
3006 				if ((pos < fmt.length()) && (fmt.charAt(pos) == '*')) {
3007 					pos++;
3008 					if (!setPrecisionArgPosition()) {
3009 						variablePrecision = true;
3010 						precisionSet = true;
3011 					}
3012 					return;
3013 				} else {
3014 					while (pos < fmt.length()) {
3015 						char c = fmt.charAt(pos);
3016 						if (Character.isDigit(c))
3017 							pos++;
3018 						else
3019 							break;
3020 					}
3021 					if (pos > firstPos + 1) {
3022 						String sz = fmt.substring(firstPos + 1, pos);
3023 						precision = Integer.parseInt(sz);
3024 						precisionSet = true;
3025 					}
3026 				}
3027 			}
3028 		}
3029 		/**
3030 		 * Set the field width.
3031 		 */
3032 		private void setFieldWidth() {
3033 			int firstPos = pos;
3034 			fieldWidth = 0;
3035 			fieldWidthSet = false;
3036 			if ((pos < fmt.length()) && (fmt.charAt(pos) == '*')) {
3037 				pos++;
3038 				if (!setFieldWidthArgPosition()) {
3039 					variableFieldWidth = true;
3040 					fieldWidthSet = true;
3041 				}
3042 			} else {
3043 				while (pos < fmt.length()) {
3044 					char c = fmt.charAt(pos);
3045 					if (Character.isDigit(c))
3046 						pos++;
3047 					else
3048 						break;
3049 				}
3050 				if (firstPos < pos && firstPos < fmt.length()) {
3051 					String sz = fmt.substring(firstPos, pos);
3052 					fieldWidth = Integer.parseInt(sz);
3053 					fieldWidthSet = true;
3054 				}
3055 			}
3056 		}
3057 		/**
3058 		 * Store the digits <code>n</code> in %n$ forms.
3059 		 */
3060 		private void setArgPosition() {
3061 			int xPos;
3062 			for (xPos = pos; xPos < fmt.length(); xPos++) {
3063 				if (!Character.isDigit(fmt.charAt(xPos)))
3064 					break;
3065 			}
3066 			if (xPos > pos && xPos < fmt.length()) {
3067 				if (fmt.charAt(xPos) == '$') {
3068 					positionalSpecification = true;
3069 					argumentPosition = Integer.parseInt(fmt.substring(pos, xPos));
3070 					pos = xPos + 1;
3071 				}
3072 			}
3073 		}
3074 		/**
3075 		 * Store the digits <code>n</code> in *n$ forms.
3076 		 */
3077 		private boolean setFieldWidthArgPosition() {
3078 			boolean ret = false;
3079 			int xPos;
3080 			for (xPos = pos; xPos < fmt.length(); xPos++) {
3081 				if (!Character.isDigit(fmt.charAt(xPos)))
3082 					break;
3083 			}
3084 			if (xPos > pos && xPos < fmt.length()) {
3085 				if (fmt.charAt(xPos) == '$') {
3086 					positionalFieldWidth = true;
3087 					argumentPositionForFieldWidth = Integer.parseInt(fmt.substring(pos, xPos));
3088 					pos = xPos + 1;
3089 					ret = true;
3090 				}
3091 			}
3092 			return ret;
3093 		}
3094 		/**
3095 		 * Store the digits <code>n</code> in *n$ forms.
3096 		 */
3097 		private boolean setPrecisionArgPosition() {
3098 			boolean ret = false;
3099 			int xPos;
3100 			for (xPos = pos; xPos < fmt.length(); xPos++) {
3101 				if (!Character.isDigit(fmt.charAt(xPos)))
3102 					break;
3103 			}
3104 			if (xPos > pos && xPos < fmt.length()) {
3105 				if (fmt.charAt(xPos) == '$') {
3106 					positionalPrecision = true;
3107 					argumentPositionForPrecision = Integer.parseInt(fmt.substring(pos, xPos));
3108 					pos = xPos + 1;
3109 					ret = true;
3110 				}
3111 			}
3112 			return ret;
3113 		}
3114 		boolean isPositionalSpecification() {
3115 			return positionalSpecification;
3116 		}
3117 		int getArgumentPosition() {
3118 			return argumentPosition;
3119 		}
3120 		boolean isPositionalFieldWidth() {
3121 			return positionalFieldWidth;
3122 		}
3123 		int getArgumentPositionForFieldWidth() {
3124 			return argumentPositionForFieldWidth;
3125 		}
3126 		boolean isPositionalPrecision() {
3127 			return positionalPrecision;
3128 		}
3129 		int getArgumentPositionForPrecision() {
3130 			return argumentPositionForPrecision;
3131 		}
3132 		/**
3133 		 * Set flag characters, one of '-+#0 or a space.
3134 		 */
3135 		private void setFlagCharacters() {
3136 			/* '-+ #0 */
3137 			thousands = false;
3138 			leftJustify = false;
3139 			leadingSign = false;
3140 			leadingSpace = false;
3141 			alternateForm = false;
3142 			leadingZeros = false;
3143 			for (; pos < fmt.length(); pos++) {
3144 				char c = fmt.charAt(pos);
3145 				if (c == '\'')
3146 					thousands = true;
3147 				else if (c == '-') {
3148 					leftJustify = true;
3149 					leadingZeros = false;
3150 				} else if (c == '+') {
3151 					leadingSign = true;
3152 					leadingSpace = false;
3153 				} else if (c == ' ') {
3154 					if (!leadingSign)
3155 						leadingSpace = true;
3156 				} else if (c == '#')
3157 					alternateForm = true;
3158 				else if (c == '0') {
3159 					if (!leftJustify)
3160 						leadingZeros = true;
3161 				} else
3162 					break;
3163 			}
3164 		}
3165 		/**
3166 		 * The integer portion of the result of a decimal
3167 		 * conversion (i, d, u, f, g, or G) will be
3168 		 * formatted with thousands' grouping characters.
3169 		 * For other conversions the flag is ignored.
3170 		 */
3171 		private boolean thousands = false;
3172 		/**
3173 		 * The result of the conversion will be
3174 		 * left-justified within the field.
3175 		 */
3176 		private boolean leftJustify = false;
3177 		/**
3178 		 * The result of a signed conversion will always
3179 		 * begin with a sign (+ or -).
3180 		 */
3181 		private boolean leadingSign = false;
3182 		/**
3183 		 * Flag indicating that left padding with spaces is
3184 		 * specified.
3185 		 */
3186 		private boolean leadingSpace = false;
3187 		/**
3188 		 * For an o conversion, increase the precision to
3189 		 * force the first digit of the result to be a
3190 		 * zero.  For x (or X) conversions, a non-zero
3191 		 * result will have 0x (or 0X) prepended to it.
3192 		 * For e, E, f, g, or G conversions, the result
3193 		 * will always contain a radix character, even if
3194 		 * no digits follow the point.  For g and G
3195 		 * conversions, trailing zeros will not be removed
3196 		 * from the result.
3197 		 */
3198 		private boolean alternateForm = false;
3199 		/**
3200 		 * Flag indicating that left padding with zeroes is
3201 		 * specified.
3202 		 */
3203 		private boolean leadingZeros = false;
3204 		/**
3205 		 * Flag indicating that the field width is *.
3206 		 */
3207 		private boolean variableFieldWidth = false;
3208 		/**
3209 		 * If the converted value has fewer bytes than the
3210 		 * field width, it will be padded with spaces or
3211 		 * zeroes.
3212 		 */
3213 		private int fieldWidth = 0;
3214 		/**
3215 		 * Flag indicating whether or not the field width
3216 		 * has been set.
3217 		 */
3218 		private boolean fieldWidthSet = false;
3219 		/**
3220 		 * The minimum number of digits to appear for the
3221 		 * d, i, o, u, x, or X conversions.  The number of
3222 		 * digits to appear after the radix character for
3223 		 * the e, E, and f conversions.  The maximum number
3224 		 *  of significant digits for the g and G 
3225 		 * conversions.  The maximum number of bytes to be
3226 		 * printed from a string in s and S conversions.
3227 		 */
3228 		private int precision = 0;
3229 
3230 		/**
3231 		 * Ike workaround. Precision of exponent.
3232 		 */
3233 		private int precisionE = 3;
3234 		private boolean precisionSetE = false;
3235 		
3236 		/** Default precision. */
3237 		private final static int defaultDigits = 6;
3238 		/**
3239 		 * Flag indicating that the precision is *.
3240 		 */
3241 		private boolean variablePrecision = false;
3242 		/**
3243 		 * Flag indicating whether or not the precision has
3244 		 * been set.
3245 		 */
3246 		private boolean precisionSet = false;
3247 		/*
3248 		 */
3249 		private boolean positionalSpecification = false;
3250 		private int argumentPosition = 0;
3251 		private boolean positionalFieldWidth = false;
3252 		private int argumentPositionForFieldWidth = 0;
3253 		private boolean positionalPrecision = false;
3254 		private int argumentPositionForPrecision = 0;
3255 		/**
3256 		 * Flag specifying that a following d, i, o, u, x,
3257 		 * or X conversion character applies to a type
3258 		 * short int.
3259 		 */
3260 		private boolean optionalh = false;
3261 		/**
3262 		 * Flag specifying that a following d, i, o, u, x,
3263 		 * or X conversion character applies to a type lont
3264 		 * int argument.
3265 		 */
3266 		private boolean optionall = false;
3267 		/**
3268 		 * Flag specifying that a following e, E, f, g, or
3269 		 * G conversion character applies to a type double
3270 		 * argument.  This is a noop in Java.
3271 		 */
3272 		private boolean optionalL = false;
3273 		/** Control string type. */
3274 		private char conversionCharacter = '\0';
3275 		/**
3276 		 * Position within the control string.  Used by
3277 		 * the constructor.
3278 		 */
3279 		private int pos = 0;
3280 		/** Literal or control format string. */
3281 		private String fmt;
3282 	}
3283 	/** Vector of control strings and format literals. */
3284 	private Vector vFmt = new Vector();
3285 	/** Character position.  Used by the constructor. */
3286 	private int cPos = 0;
3287 	/** Character position.  Used by the constructor. */
3288 	private DecimalFormatSymbols dfs = null;
3289 }