2 * Copyright (c) 2012-2014 ARM Ltd
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the company may not be used to endorse or promote
14 * products derived from this software without specific prior written
17 * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
22 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 #include "../stdlib/local.h"
45 #include "nano-vfprintf_local.h"
47 /* Decode and print non-floating point data. */
49 _printf_common (struct _reent
*data
,
50 struct _prt_data_t
*pdata
,
53 int (*pfunc
)(struct _reent
*, FILE *,
54 const char *, size_t len
))
58 * All reasonable formats wind up here. At this point, `cp'
59 * points to a string which (if not flags&LADJUST) should be
60 * padded out to `width' places. If flags&ZEROPAD, it should
61 * first be prefixed by any sign or other prefix; otherwise,
62 * it should be blank padded before the prefix is emitted.
63 * After any left-hand padding and prefixing, emit zeroes
64 * required by a decimal [diouxX] precision, then print the
65 * string proper, then emit zeroes required by any leftover
66 * floating precision; finally, if LADJUST, pad with blanks.
67 * If flags&FPT, ch must be in [aAeEfg].
69 * Compute actual size, so we know how much to pad.
70 * size excludes decimal prec; realsz includes it.
72 *realsz
= pdata
->dprec
> pdata
->size
? pdata
->dprec
: pdata
->size
;
76 if (pdata
->flags
& HEXPREFIX
)
79 /* Right-adjusting blank padding. */
80 if ((pdata
->flags
& (LADJUST
|ZEROPAD
)) == 0)
81 PAD (pdata
->width
- *realsz
, pdata
->blank
);
88 if (pdata
->flags
& HEXPREFIX
)
90 pdata
->l_buf
[n
++] = '0';
91 pdata
->l_buf
[n
++] = pdata
->l_buf
[2];
94 PRINT (pdata
->l_buf
, n
);
95 n
= pdata
->width
- *realsz
;
96 if ((pdata
->flags
& (LADJUST
|ZEROPAD
)) != ZEROPAD
|| n
< 0)
99 if (pdata
->dprec
> pdata
->size
)
100 n
+= pdata
->dprec
- pdata
->size
;
102 PAD (n
, pdata
->zero
);
108 _printf_i (struct _reent
*data
, struct _prt_data_t
*pdata
, FILE *fp
,
109 int (*pfunc
)(struct _reent
*, FILE *, const char *, size_t len
),
112 /* Field size expanded by dprec. */
117 char *cp
= pdata
->buf
+ BUF
;
118 char *xdigs
= "0123456789ABCDEF";
120 /* Decoding the conversion specifier. */
124 *--cp
= GET_ARG (N
, *ap
, int);
126 goto non_number_nosign
;
129 _uquad
= SARG (pdata
->flags
);
130 if ((long) _uquad
< 0)
133 pdata
->l_buf
[0] = '-';
139 _uquad
= UARG (pdata
->flags
);
140 base
= (pdata
->code
== 'o') ? 8 : 10;
143 pdata
->l_buf
[2] = 'X';
147 * ``The argument shall be a pointer to void. The
148 * value of the pointer is converted to a sequence
149 * of printable characters, in an implementation-
153 pdata
->flags
|= HEXPREFIX
;
154 if (sizeof (void*) > sizeof (int))
155 pdata
->flags
|= LONGINT
;
158 pdata
->l_buf
[2] = 'x';
159 xdigs
= "0123456789abcdef";
161 _uquad
= UARG (pdata
->flags
);
163 if (pdata
->flags
& ALT
)
164 pdata
->flags
|= HEXPREFIX
;
166 /* Leading 0x/X only if non-zero. */
168 pdata
->flags
&= ~HEXPREFIX
;
170 /* Unsigned conversions. */
172 pdata
->l_buf
[0] = '\0';
174 * ``... diouXx conversions ... if a precision is
175 * specified, the 0 flag will be ignored.''
179 if ((pdata
->dprec
= pdata
->prec
) >= 0)
180 pdata
->flags
&= ~ZEROPAD
;
183 * ``The result of converting a zero value with an
184 * explicit precision of zero is no characters.''
187 if (_uquad
!= 0 || pdata
->prec
!= 0)
191 *--cp
= xdigs
[_uquad
% base
];
196 /* For 'o' conversion, '#' increases the precision to force the first
197 digit of the result to be zero. */
198 if (base
== 8 && (pdata
->flags
& ALT
) && pdata
->prec
<= pdata
->size
)
201 pdata
->size
= pdata
->buf
+ BUF
- cp
;
204 if (pdata
->flags
& LONGINT
)
205 *GET_ARG (N
, *ap
, long_ptr_t
) = pdata
->ret
;
206 else if (pdata
->flags
& SHORTINT
)
207 *GET_ARG (N
, *ap
, short_ptr_t
) = pdata
->ret
;
209 *GET_ARG (N
, *ap
, int_ptr_t
) = pdata
->ret
;
214 cp
= GET_ARG (N
, *ap
, char_ptr_t
);
215 /* Precision gives the maximum number of chars to be written from a
216 string, and take prec == -1 into consideration.
217 Use normal Newlib approach here to support case where cp is not
219 char *p
= memchr (cp
, 0, pdata
->prec
);
222 pdata
->prec
= p
- cp
;
224 pdata
->size
= pdata
->prec
;
225 goto non_number_nosign
;
227 /* "%?" prints ?, unless ? is NUL. */
228 /* Pretend it was %c with argument ch. */
232 pdata
->l_buf
[0] = '\0';
237 n
= _printf_common (data
, pdata
, &realsz
, fp
, pfunc
);
241 PRINT (cp
, pdata
->size
);
242 /* Left-adjusting padding (always blank). */
243 if (pdata
->flags
& LADJUST
)
244 PAD (pdata
->width
- realsz
, pdata
->blank
);
246 return (pdata
->width
> realsz
? pdata
->width
: realsz
);