summaryrefslogtreecommitdiff
path: root/newlib/libc/stdio/sprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'newlib/libc/stdio/sprintf.c')
-rw-r--r--newlib/libc/stdio/sprintf.c360
1 files changed, 360 insertions, 0 deletions
diff --git a/newlib/libc/stdio/sprintf.c b/newlib/libc/stdio/sprintf.c
new file mode 100644
index 00000000000..b5376327e3f
--- /dev/null
+++ b/newlib/libc/stdio/sprintf.c
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+
+FUNCTION
+ <<printf>>, <<fprintf>>, <<sprintf>>, <<snprintf>>---format output
+INDEX
+ fprintf
+INDEX
+ printf
+INDEX
+ sprintf
+INDEX
+ snprintf
+
+ANSI_SYNOPSIS
+ #include <stdio.h>
+
+ int printf(const char *<[format]> [, <[arg]>, ...]);
+ int fprintf(FILE *<[fd]>, const char *<[format]> [, <[arg]>, ...]);
+ int sprintf(char *<[str]>, const char *<[format]> [, <[arg]>, ...]);
+ int snprintf(char *<[str]>, size_t <[size]>, const char *<[format]> [, <[arg]>, ...]);
+
+TRAD_SYNOPSIS
+ #include <stdio.h>
+
+ int printf(<[format]> [, <[arg]>, ...])
+ char *<[format]>;
+
+ int fprintf(<[fd]>, <[format]> [, <[arg]>, ...]);
+ FILE *<[fd]>;
+ char *<[format]>;
+
+ int sprintf(<[str]>, <[format]> [, <[arg]>, ...]);
+ char *<[str]>;
+ char *<[format]>;
+
+ int snprintf(<[str]>, size_t <[size]>, <[format]> [, <[arg]>, ...]);
+ char *<[str]>;
+ size_t <[size]>;
+ char *<[format]>;
+
+DESCRIPTION
+ <<printf>> accepts a series of arguments, applies to each a
+ format specifier from <<*<[format]>>>, and writes the
+ formatted data to <<stdout>>, terminated with a null character.
+ The behavior of <<printf>> is undefined if there are not enough
+ arguments for the format.
+ <<printf>> returns when it reaches the end of the format string.
+ If there are more arguments than the format requires, excess
+ arguments are ignored.
+
+ <<fprintf>>, <<sprintf>> and <<snprintf>> are identical to <<printf>>,
+ other than the destination of the formatted output: <<fprintf>> sends
+ the output to a specified file <[fd]>, while <<sprintf>> stores the
+ output in the specified char array <[str]> and <<snprintf>> limits
+ number of characters written to <[str]> to at most <[size]> (including
+ terminating <<0>>). For <<sprintf>> and <<snprintf>>, the behavior is
+ also undefined if the output <<*<[str]>>> overlaps with one of the
+ arguments. <[format]> is a pointer to a charater string containing
+ two types of objects: ordinary characters (other than <<%>>), which
+ are copied unchanged to the output, and conversion
+ specifications, each of which is introduced by <<%>>.
+ (To include <<%>> in the output, use <<%%>> in the format string.)
+ A conversion specification has the following form:
+
+. %[<[flags]>][<[width]>][.<[prec]>][<[size]>][<[type]>]
+
+ The fields of the conversion specification have the following meanings:
+
+ O+
+ o <[flags]>
+
+ an optional sequence of characters which control
+ output justification, numeric signs, decimal points,
+ trailing zeroes, and octal and hex prefixes.
+ The flag characters are minus (<<->>), plus (<<+>>),
+ space ( ), zero (<<0>>), and sharp (<<#>>). They can
+ appear in any combination.
+
+ o+
+ o -
+ The result of the conversion is left justified, and the right is
+ padded with blanks. If you do not use this flag, the result is right
+ justified, and padded on the left.
+
+ o +
+ The result of a signed conversion (as determined by <[type]>)
+ will always begin with a plus or minus sign. (If you do not use
+ this flag, positive values do not begin with a plus sign.)
+
+ o " " (space)
+ If the first character of a signed conversion specification
+ is not a sign, or if a signed conversion results in no
+ characters, the result will begin with a space. If the
+ space ( ) flag and the plus (<<+>>) flag both appear,
+ the space flag is ignored.
+
+ o 0
+ If the <[type]> character is <<d>>, <<i>>, <<o>>, <<u>>,
+ <<x>>, <<X>>, <<e>>, <<E>>, <<f>>, <<g>>, or <<G>>: leading zeroes,
+ are used to pad the field width (following any indication of sign or
+ base); no spaces are used for padding. If the zero (<<0>>) and
+ minus (<<->>) flags both appear, the zero (<<0>>) flag will
+ be ignored. For <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, and <<X>>
+ conversions, if a precision <[prec]> is specified, the zero (<<0>>)
+ flag is ignored.
+
+ Note that <<0>> is interpreted as a flag, not as the beginning
+ of a field width.
+
+ o #
+ The result is to be converted to an alternative form, according
+ to the next character:
+
+ o+
+ o 0
+ increases precision to force the first digit
+ of the result to be a zero.
+
+ o x
+ a non-zero result will have a <<0x>> prefix.
+
+ o X
+ a non-zero result will have a <<0X>> prefix.
+
+ o e, E or f
+ The result will always contain a decimal point
+ even if no digits follow the point.
+ (Normally, a decimal point appears only if a
+ digit follows it.) Trailing zeroes are removed.
+
+ o g or G
+ same as <<e>> or <<E>>, but trailing zeroes
+ are not removed.
+
+ o all others
+ undefined.
+
+ o-
+ o-
+
+ o <[width]>
+
+ <[width]> is an optional minimum field width. You can either
+ specify it directly as a decimal integer, or indirectly by
+ using instead an asterisk (<<*>>), in which case an <<int>>
+ argument is used as the field width. Negative field widths
+ are not supported; if you attempt to specify a negative field
+ width, it is interpreted as a minus (<<->>) flag followed by a
+ positive field width.
+
+ o <[prec]>
+
+ an optional field; if present, it is introduced with `<<.>>'
+ (a period). This field gives the maximum number of
+ characters to print in a conversion; the minimum number of
+ digits of an integer to print, for conversions with <[type]>
+ <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, and <<X>>; the maximum number of
+ significant digits, for the <<g>> and <<G>> conversions;
+ or the number of digits to print after the decimal
+ point, for <<e>>, <<E>>, and <<f>> conversions. You can specify
+ the precision either directly as a decimal integer or
+ indirectly by using an asterisk (<<*>>), in which case
+ an <<int>> argument is used as the precision. Supplying a negative
+ precision is equivalent to omitting the precision.
+ If only a period is specified the precision is zero.
+ If a precision appears with any other conversion <[type]>
+ than those listed here, the behavior is undefined.
+
+ o <[size]>
+
+ <<h>>, <<l>>, and <<L>> are optional size characters which
+ override the default way that <<printf>> interprets the
+ data type of the corresponding argument. <<h>> forces
+ the following <<d>>, <<i>>, <<o>>, <<u>>, <<x>> or <<X>> conversion
+ <[type]> to apply to a <<short>> or <<unsigned short>>. <<h>> also
+ forces a following <<n>> <[type]> to apply to
+ a pointer to a <<short>>. Similarily, an
+ <<l>> forces the following <<d>>, <<i>>, <<o>>, <<u>>,
+ <<x>> or <<X>> conversion <[type]> to apply to a <<long>> or
+ <<unsigned long>>. <<l>> also forces a following <<n>> <[type]> to
+ apply to a pointer to a <<long>>. If an <<h>>
+ or an <<l>> appears with another conversion
+ specifier, the behavior is undefined. <<L>> forces a
+ following <<e>>, <<E>>, <<f>>, <<g>> or <<G>> conversion <[type]> to
+ apply to a <<long double>> argument. If <<L>> appears with
+ any other conversion <[type]>, the behavior is undefined.
+
+ o <[type]>
+
+ <[type]> specifies what kind of conversion <<printf>> performs.
+ Here is a table of these:
+
+ o+
+ o %
+ prints the percent character (<<%>>)
+
+ o c
+ prints <[arg]> as single character
+
+ o s
+ prints characters until precision is reached or a null terminator
+ is encountered; takes a string pointer
+
+ o d
+ prints a signed decimal integer; takes an <<int>> (same as <<i>>)
+
+ o i
+ prints a signed decimal integer; takes an <<int>> (same as <<d>>)
+
+ o o
+ prints a signed octal integer; takes an <<int>>
+
+ o u
+ prints an unsigned decimal integer; takes an <<int>>
+
+ o x
+ prints an unsigned hexadecimal integer (using <<abcdef>> as
+ digits beyond <<9>>); takes an <<int>>
+
+ o X
+ prints an unsigned hexadecimal integer (using <<ABCDEF>> as
+ digits beyond <<9>>); takes an <<int>>
+
+ o f
+ prints a signed value of the form <<[-]9999.9999>>; takes
+ a floating point number
+
+ o e
+ prints a signed value of the form <<[-]9.9999e[+|-]999>>; takes a
+ floating point number
+
+ o E
+ prints the same way as <<e>>, but using <<E>> to introduce the
+ exponent; takes a floating point number
+
+ o g
+ prints a signed value in either <<f>> or <<e>> form, based on given
+ value and precision---trailing zeros and the decimal point are
+ printed only if necessary; takes a floating point number
+
+ o G
+ prints the same way as <<g>>, but using <<E>> for the exponent if an
+ exponent is needed; takes a floating point number
+
+ o n
+ stores (in the same object) a count of the characters written;
+ takes a pointer to <<int>>
+
+ o p
+ prints a pointer in an implementation-defined format.
+ This implementation treats the pointer as an
+ <<unsigned long>> (same as <<Lu>>).
+ o-
+O-
+
+
+RETURNS
+<<sprintf>> returns the number of bytes in the output string,
+save that the concluding <<NULL>> is not counted.
+<<printf>> and <<fprintf>> return the number of characters transmitted.
+If an error occurs, <<printf>> and <<fprintf>> return <<EOF>>. No
+error returns occur for <<sprintf>>.
+
+PORTABILITY
+ The ANSI C standard specifies that implementations must
+ support at least formatted output of up to 509 characters.
+
+Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
+<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
+*/
+
+#include <stdio.h>
+#ifdef _HAVE_STDC
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <limits.h>
+#include <_ansi.h>
+#include "local.h"
+
+int
+#ifdef _HAVE_STDC
+_DEFUN (_sprintf_r, (ptr, str, fmt), struct _reent *ptr _AND char *str _AND _CONST char *fmt _DOTS)
+#else
+_sprintf_r (ptr, str, fmt, va_alist)
+ struct _reent *ptr;
+ char *str;
+ _CONST char *fmt;
+ va_dcl
+#endif
+{
+ int ret;
+ va_list ap;
+ FILE f;
+
+ f._flags = __SWR | __SSTR;
+ f._bf._base = f._p = (unsigned char *) str;
+ f._bf._size = f._w = INT_MAX;
+ f._data = ptr;
+#ifdef _HAVE_STDC
+ va_start (ap, fmt);
+#else
+ va_start (ap);
+#endif
+ ret = vfprintf (&f, fmt, ap);
+ va_end (ap);
+ *f._p = 0;
+ return (ret);
+}
+
+#ifndef _REENT_ONLY
+
+int
+#ifdef _HAVE_STDC
+_DEFUN (sprintf, (str, fmt), char *str _AND _CONST char *fmt _DOTS)
+#else
+sprintf (str, fmt, va_alist)
+ char *str;
+ _CONST char *fmt;
+ va_dcl
+#endif
+{
+ int ret;
+ va_list ap;
+ FILE f;
+
+ f._flags = __SWR | __SSTR;
+ f._bf._base = f._p = (unsigned char *) str;
+ f._bf._size = f._w = INT_MAX;
+ f._data = _REENT;
+#ifdef _HAVE_STDC
+ va_start (ap, fmt);
+#else
+ va_start (ap);
+#endif
+ ret = vfprintf (&f, fmt, ap);
+ va_end (ap);
+ *f._p = 0;
+ return (ret);
+}
+
+#endif