devctl.h: update for POSIX-1.2024
[newlib-cygwin.git] / newlib / libc / machine / msp430 / tiny-printf.c
blobf2412a0e6a0d77f35ae53a3f1f83abb9cd139fcf
1 /*
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
34 * Copyright (c) 2012-2014 ARM Ltd
35 * All rights reserved.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. The name of the company may not be used to endorse or promote
46 * products derived from this software without specific prior written
47 * permission.
49 * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
50 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
51 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
52 * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
53 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
54 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
55 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
56 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
57 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
58 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 #if defined(LIBC_SCCS) && !defined(lint)
62 /*static char *sccsid = "from: @(#)vfprintf.c 5.50 (Berkeley) 12/16/92";*/
63 static char *rcsid = "$Id$";
64 #endif /* LIBC_SCCS and not lint */
66 #include <_ansi.h>
67 #include <reent.h>
68 #include <stdio.h>
69 #include <stdlib.h>
70 #include <string.h>
71 #include <limits.h>
72 #include <stdint.h>
73 #include <wchar.h>
74 #include <sys/lock.h>
75 #include <stdarg.h>
76 #include <string.h>
77 #include <newlib.h>
78 #include "../../stdio/local.h"
79 #include "../../stdlib/local.h"
80 #include "../../stdio/fvwrite.h"
81 #include "../../stdio/nano-vfprintf_local.h"
83 /* Bypass *putc* fns called by the default _sfputs_r to save code size.
84 Among other things, this means there is no buffering of the string before
85 it is sent to <<write>>, but <<write>> does its own buffering so we won't
86 lose chars when buf is larger than sizeof(CIOBUF). */
87 int
88 __tiny__sfputs_r (struct _reent *ptr,
89 FILE *fp,
90 const char *buf,
91 size_t len)
93 return write (1, buf, len);
96 /* VFPRINTF_R from nano-vfprintf.c but:
97 - No support for reentrancy
98 - No support for streams
99 - __SINGLE_THREAD__ assumed.
100 - No STRING_ONLY variant (either way the formatted string would end up
101 being sent to <<write>> via <<__tiny__sfputs_r>>.
102 Basically, format the string as normal, and send it to write. */
104 __tiny_vfprintf_r (struct _reent *data,
105 FILE * fp,
106 const char *fmt0,
107 va_list ap)
109 register char *fmt; /* Format string. */
110 register int n, m; /* Handy integers (short term usage). */
111 register char *cp; /* Handy char pointer (short term usage). */
112 const char *flag_chars;
113 struct _prt_data_t prt_data; /* All data for decoding format string. */
114 va_list ap_copy;
116 /* Output function pointer. */
117 int (*pfunc)(struct _reent *, FILE *, const char *, size_t len);
119 pfunc = __tiny__sfputs_r;
121 fmt = (char *)fmt0;
122 prt_data.ret = 0;
123 prt_data.blank = ' ';
124 prt_data.zero = '0';
126 /* GCC PR 14577 at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14557 */
127 va_copy (ap_copy, ap);
129 /* Scan the format for conversions (`%' character). */
130 for (;;)
132 cp = fmt;
133 while (*fmt != '\0' && *fmt != '%')
134 fmt += 1;
136 if ((m = fmt - cp) != 0)
138 PRINT (cp, m);
139 prt_data.ret += m;
141 if (*fmt == '\0')
142 goto done;
144 fmt++; /* Skip over '%'. */
146 prt_data.flags = 0;
147 prt_data.width = 0;
148 prt_data.prec = -1;
149 prt_data.dprec = 0;
150 prt_data.l_buf[0] = '\0';
151 #ifdef FLOATING_POINT
152 prt_data.lead = 0;
153 #endif
154 /* The flags. */
156 * ``Note that 0 is taken as a flag, not as the
157 * beginning of a field width.''
158 * -- ANSI X3J11
160 flag_chars = "#-0+ ";
161 for (; cp = memchr (flag_chars, *fmt, 5); fmt++)
162 prt_data.flags |= (1 << (cp - flag_chars));
164 if (prt_data.flags & SPACESGN)
165 prt_data.l_buf[0] = ' ';
168 * ``If the space and + flags both appear, the space
169 * flag will be ignored.''
170 * -- ANSI X3J11
172 if (prt_data.flags & PLUSSGN)
173 prt_data.l_buf[0] = '+';
175 /* The width. */
176 if (*fmt == '*')
179 * ``A negative field width argument is taken as a
180 * - flag followed by a positive field width.''
181 * -- ANSI X3J11
182 * They don't exclude field widths read from args.
184 prt_data.width = GET_ARG (n, ap_copy, int);
185 if (prt_data.width < 0)
187 prt_data.width = -prt_data.width;
188 prt_data.flags |= LADJUST;
190 fmt++;
192 else
194 for (; is_digit (*fmt); fmt++)
195 prt_data.width = 10 * prt_data.width + to_digit (*fmt);
198 /* The precision. */
199 if (*fmt == '.')
201 fmt++;
202 if (*fmt == '*')
204 fmt++;
205 prt_data.prec = GET_ARG (n, ap_copy, int);
206 if (prt_data.prec < 0)
207 prt_data.prec = -1;
209 else
211 prt_data.prec = 0;
212 for (; is_digit (*fmt); fmt++)
213 prt_data.prec = 10 * prt_data.prec + to_digit (*fmt);
217 /* The length modifiers. */
218 flag_chars = "hlL";
219 if ((cp = memchr (flag_chars, *fmt, 3)) != NULL)
221 prt_data.flags |= (SHORTINT << (cp - flag_chars));
222 fmt++;
225 /* The conversion specifiers. */
226 prt_data.code = *fmt++;
227 cp = memchr ("efgEFG", prt_data.code, 6);
228 #ifdef FLOATING_POINT
229 /* If cp is not NULL, we are facing FLOATING POINT NUMBER. */
230 if (cp)
232 /* Consume floating point argument if _printf_float is not
233 linked. */
234 if (_printf_float == NULL)
236 if (prt_data.flags & LONGDBL)
237 GET_ARG (N, ap_copy, _LONG_DOUBLE);
238 else
239 GET_ARG (N, ap_copy, double);
241 else
242 n = _printf_float (data, &prt_data, fp, pfunc, &ap_copy);
244 else
245 #endif
246 n = _printf_i (data, &prt_data, fp, pfunc, &ap_copy);
248 if (n == -1)
249 goto error;
251 prt_data.ret += n;
253 done:
254 error:
255 va_end (ap_copy);
256 return (__sferror (fp) ? EOF : prt_data.ret);
260 __wrap_printf (const char *__restrict fmt, ...)
262 int ret;
263 va_list ap;
264 struct _reent *ptr = _REENT;
266 va_start (ap, fmt);
267 ret = __tiny_vfprintf_r (ptr, _stdout_r (ptr), fmt, ap);
268 va_end (ap);
269 return ret;
272 int printf (const char *__restrict fmt, ...) __attribute__ ((weak, alias ("__wrap_printf")));