Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/xmud/util/PrintfFormat.java


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