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