diff options
| author | Michael Kerrisk <mtk.manpages@gmail.com> | 2004-11-03 13:51:07 +0000 |
|---|---|---|
| committer | Michael Kerrisk <mtk.manpages@gmail.com> | 2004-11-03 13:51:07 +0000 |
| commit | fea681dafb1363a154b7fc6d59baa83d2a9ebc5c (patch) | |
| tree | 8ea275c0f242af739617d0afc3e1b16c4eff3dc2 /man3/printf.3 | |
| download | man-pages-fea681dafb1363a154b7fc6d59baa83d2a9ebc5c.tar.gz | |
Import of man-pages 1.70man-pages-1.70
Diffstat (limited to 'man3/printf.3')
| -rw-r--r-- | man3/printf.3 | 931 |
1 files changed, 931 insertions, 0 deletions
diff --git a/man3/printf.3 b/man3/printf.3 new file mode 100644 index 0000000000..a5daac8717 --- /dev/null +++ b/man3/printf.3 @@ -0,0 +1,931 @@ +.\" Copyright (c) 1999 Andries Brouwer (aeb@cwi.nl) +.\" +.\" This is free documentation; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License as +.\" published by the Free Software Foundation; either version 2 of +.\" the License, or (at your option) any later version. +.\" +.\" The GNU General Public License's references to "object code" +.\" and "executables" are to be interpreted as the output of any +.\" document formatting or typesetting system, including +.\" intermediate and printed output. +.\" +.\" This manual is distributed in the hope that it will be useful, +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.\" GNU General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public +.\" License along with this manual; if not, write to the Free +.\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, +.\" USA. +.\" +.\" +.\" Earlier versions of this page influenced the present text. +.\" It was derived from a Berkeley page with version +.\" @(#)printf.3 6.14 (Berkeley) 7/30/91 +.\" converted for Linux by faith@cs.unc.edu, updated by +.\" Helmut.Geyer@iwr.uni-heidelberg.de, agulbra@troll.no and Bruno Haible. +.\" +.\" 1999-11-25 aeb - Rewritten, using SUSv2 and C99. +.\" 2000-07-26 jsm28@hermes.cam.ac.uk - three small fixes +.\" 2000-10-16 jsm28@hermes.cam.ac.uk - more fixes +.\" +.TH PRINTF 3 2000-10-16 "Linux Manpage" "Linux Programmer's Manual" +.SH NAME +printf, fprintf, sprintf, snprintf, vprintf, vfprintf, vsprintf, vsnprintf \- formatted output conversion +.SH SYNOPSIS +.B #include <stdio.h> +.sp +.BI "int printf(const char *" format ", ...);" +.br +.BI "int fprintf(FILE *" stream ", const char *" format ", ...);" +.br +.BI "int sprintf(char *" str ", const char *" format ", ...);" +.br +.BI "int snprintf(char *" str ", size_t " size ", const char *" format ", ...);" +.sp +.B #include <stdarg.h> +.sp +.BI "int vprintf(const char *" format ", va_list " ap ); +.br +.BI "int vfprintf(FILE *" stream ", const char *" format ", va_list " ap ); +.br +.BI "int vsprintf(char *" str ", const char *" format ", va_list " ap ); +.br +.BI "int vsnprintf(char *" str ", size_t " size ", const char *" format ", va_list " ap ); +.SH DESCRIPTION +The functions in the +.B printf +family produce output according to a +.I format +as described below. The functions +.B printf +and +.B vprintf +write output to +.IR stdout , +the standard output stream; +.B fprintf +and +.B vfprintf +write output to the given output +.IR stream ; +.BR sprintf , +.BR snprintf , +.B vsprintf +and +.B vsnprintf +write to the character string +.IR str . +.PP +The functions +.BR vprintf , +.BR vfprintf , +.BR vsprintf , +.B vsnprintf +are equivalent to the functions +.BR printf , +.BR fprintf , +.BR sprintf , +.BR snprintf , +respectively, except that they are called with a va_list instead +of a variable number of arguments. These functions do not call the +.I va_end +macro. Consequently, the value of +.I ap +is undefined after the call. The application should call +.I va_end(ap) +itself afterwards. +.PP +These eight functions write the output under the control of a +.I format +string that specifies how subsequent arguments (or arguments accessed via +the variable-length argument facilities of +.BR stdarg (3)) +are converted for output. +.SS "Return value" +Upon successful return, these functions return the number of characters +printed (not including the trailing '\e0' used to end output to strings). +The functions +.BR snprintf " and " vsnprintf +do not write more than +.I size +bytes (including the trailing '\e0'). +If the output was truncated due to this limit then the return value +is the number of characters (not including the trailing '\e0') +which would have been written to the final string if enough space +had been available. Thus, a return value of +.I size +or more means that the output was truncated. (See also below +under NOTES.) +If an output error is encountered, a negative value is returned. +.SS "Format of the format string" +The format string is a character string, beginning and ending +in its initial shift state, if any. +The format string is composed of zero or more directives: ordinary +characters (not +.BR % ), +which are copied unchanged to the output stream; +and conversion specifications, each of which results in fetching zero or +more subsequent arguments. Each conversion specification is introduced by +the character +.BR % , +and ends with a +.IR "conversion specifier" . +In between there may be (in this order) zero or more +.IR flags , +an optional minimum +.IR "field width" , +an optional +.I precision +and an optional +.IR "length modifier" . + +The arguments must correspond properly (after type promotion) with the +conversion specifier. By default, the arguments are used in the order +given, where each `*' and each conversion specifier asks for the next +argument (and it is an error if insufficiently many arguments are given). +One can also specify explicitly which argument is taken, +at each place where an argument is required, by writing `%m$' instead +of `%' and `*m$' instead of `*', where the decimal integer m denotes +the position in the argument list of the desired argument, indexed starting +from 1. Thus, +.RS +.nf + printf("%*d", width, num); +.fi +.RE +and +.RS +.nf + printf("%2$*1$d", width, num); +.fi +.RE +are equivalent. The second style allows repeated references to the +same argument. The C99 standard does not include the style using `$', +which comes from the Single Unix Specification. If the style using +`$' is used, it must be used throughout for all conversions taking an +argument and all width and precision arguments, but it may be mixed +with `%%' formats which do not consume an argument. There may be no +gaps in the numbers of arguments specified using `$'; for example, if +arguments 1 and 3 are specified, argument 2 must also be specified +somewhere in the format string. + +For some numeric conversions a radix character (`decimal point') or +thousands' grouping character is used. The actual character used +depends on the LC_NUMERIC part of the locale. The POSIX locale +uses `.' as radix character, and does not have a grouping character. +Thus, +.RS +.nf + printf("%'.2f", 1234567.89); +.fi +.RE +results in `1234567.89' in the POSIX locale, in `1234567,89' in the +nl_NL locale, and in `1.234.567,89' in the da_DK locale. +.SS "The flag characters" +The character % is followed by zero or more of the following flags: +.TP +.B # +The value should be converted to an ``alternate form''. +For +.BR o +conversions, the first character of the output string is made zero +(by prefixing a 0 if it was not zero already). +For +.B x +and +.B X +conversions, a non\-zero result has the string `0x' (or `0X' for +.B X +conversions) prepended to it. For +.BR a , +.BR A , +.BR e , +.BR E , +.BR f , +.BR F , +.BR g , +and +.B G +conversions, the result will always contain a decimal point, even if no +digits follow it (normally, a decimal point appears in the results of those +conversions only if a digit follows). For +.B g +and +.B G +conversions, trailing zeros are not removed from the result as they would +otherwise be. +For other conversions, the result is undefined. +.TP +.B \&0 +The value should be zero padded. For +.BR d , +.BR i , +.BR o , +.BR u , +.BR x , +.BR X , +.BR a , +.BR A , +.BR e , +.BR E , +.BR f , +.BR F , +.BR g , +and +.B G +conversions, the converted value is padded on the left with zeros rather +than blanks. +If the +.B \&0 +and +.B \- +flags both appear, the +.B \&0 +flag is ignored. +If a precision is given with a numeric conversion +.BR "" ( d , +.BR i , +.BR o , +.BR u , +.BR x , +and +.BR X ), +the +.B \&0 +flag is ignored. +For other conversions, the behavior is undefined. +.TP +.B \- +The converted value is to be left adjusted on the field boundary. +(The default is right justification.) Except for +.B n +conversions, the converted value is padded on the right with blanks, rather +than on the left with blanks or zeros. A +.B \- +overrides a +.B \&0 +if both are given. +.TP +.B ' ' +(a space) A blank should be left before a positive number +(or empty string) produced by a signed conversion. +.TP +.B + +A sign (+ or -) always be placed before a number produced by a signed +conversion. By default a sign is used only for negative numbers. A +.B + +overrides a space if both are used. +.PP +The five flag characters above are defined in the C standard. +The SUSv2 specifies one further flag character. +.TP +.B ' +For decimal conversion +.BR "" ( i , +.BR d , +.BR u , +.BR f , +.BR F , +.BR g , +.BR G ) +the output is to be grouped with thousands' grouping characters +if the locale information indicates any. Note that many versions of +.B gcc +cannot parse this option and will issue a warning. SUSv2 does not +include %'F. +.PP +glibc 2.2 adds one further flag character. +.TP +.B I +For decimal integer conversion +.BR "" ( i , +.BR d , +.BR u ) +the output uses the locale's alternative output digits, if any. +For example, since glibc 2.2.3 this will give Arabic-Indic digits +in the Persian (`fa_IR') locale. +.\" outdigits keyword in locale file +.SS "The field width" +An optional decimal digit string (with nonzero first digit) specifying +a minimum field width. If the converted value has fewer characters +than the field width, it will be padded with spaces on the left +(or right, if the left-adjustment flag has been given). +Instead of a decimal digit string one may write `*' or `*m$' +(for some decimal integer m) to specify that the field width +is given in the next argument, or in the m-th argument, respectively, +which must be of type +.IR int . +A negative field width is taken as a `-' flag followed by a +positive field width. +In no case does a non-existent or small field width cause truncation of a +field; if the result of a conversion is wider than the field width, the +field is expanded to contain the conversion result. +.SS "The precision" +An optional precision, in the form of a period (`\&.') followed by an +optional decimal digit string. +Instead of a decimal digit string one may write `*' or `*m$' +(for some decimal integer m) to specify that the precision +is given in the next argument, or in the m-th argument, respectively, +which must be of type +.IR int . +If the precision is given as just `.', or the precision is negative, +the precision is taken to be zero. +This gives the minimum number of digits to appear for +.BR d , +.BR i , +.BR o , +.BR u , +.BR x , +and +.B X +conversions, the number of digits to appear after the radix character for +.BR a , +.BR A , +.BR e , +.BR E , +.BR f , +and +.B F +conversions, the maximum number of significant digits for +.B g +and +.B G +conversions, or the maximum number of characters to be printed from a +string for +.B s +and +.B S +conversions. +.SS "The length modifier" +Here, `integer conversion' stands for +.BR d , +.BR i , +.BR o , +.BR u , +.BR x , +or +.BR X +conversion. +.TP +.B hh +A following integer conversion corresponds to a +.I signed char +or +.I unsigned char +argument, or a following +.B n +conversion corresponds to a pointer to a +.I signed char +argument. +.TP +.B h +A following integer conversion corresponds to a +.I short int +or +.I unsigned short int +argument, or a following +.B n +conversion corresponds to a pointer to a +.I short int +argument. +.TP +.B l +(ell) A following integer conversion corresponds to a +.I long int +or +.I unsigned long int +argument, or a following +.B n +conversion corresponds to a pointer to a +.I long int +argument, or a following +.B c +conversion corresponds to a +.I wint_t +argument, or a following +.B s +conversion corresponds to a pointer to +.I wchar_t +argument. +.TP +.B ll +(ell-ell). +A following integer conversion corresponds to a +.I long long int +or +.I unsigned long long int +argument, or a following +.B n +conversion corresponds to a pointer to a +.I long long int +argument. +.TP +.BR L +A following +.BR a , +.BR A , +.BR e , +.BR E , +.BR f , +.BR F , +.BR g , +or +.B G +conversion corresponds to a +.I long double +argument. +(C99 allows %LF, but SUSv2 does not.) +.TP +.B q +(`quad'. BSD 4.4 and Linux libc5 only. Don't use.) +This is a synonym for +.BR ll . +.TP +.B j +A following integer conversion corresponds to an +.I intmax_t +or +.I uintmax_t +argument. +.TP +.B z +A following integer conversion corresponds to a +.I size_t +or +.I ssize_t +argument. (Linux libc5 has +.B Z +with this meaning. Don't use it.) +.TP +.B t +A following integer conversion corresponds to a +.I ptrdiff_t +argument. +.PP +The SUSv2 only knows about the length modifiers +.B h +(in +.BR hd , +.BR hi , +.BR ho , +.BR hx , +.BR hX , +.BR hn ) +and +.B l +(in +.BR ld , +.BR li , +.BR lo , +.BR lx , +.BR lX , +.BR ln , +.BR lc , +.BR ls ) +and +.B L +(in +.BR Le , +.BR LE , +.BR Lf , +.BR Lg , +.BR LG ). + +.SS "The conversion specifier" +A character that specifies the type of conversion to be applied. +The conversion specifiers and their meanings are: +.TP +.BR d , i +The +.I int +argument is converted to signed decimal notation. +The precision, if any, gives the minimum number of digits +that must appear; if the converted value requires fewer digits, it is +padded on the left with zeros. The default precision is 1. +When 0 is printed with an explicit precision 0, the output is empty. +.TP +.BR o , u , x , X +The +.I "unsigned int" +argument is converted to unsigned octal +.BR "" ( o ), +unsigned decimal +.BR "" ( u ), +or unsigned hexadecimal +.BR "" ( x +and +.BR X ) +notation. The letters +.B abcdef +are used for +.B x +conversions; the letters +.B ABCDEF +are used for +.B X +conversions. The precision, if any, gives the minimum number of digits +that must appear; if the converted value requires fewer digits, it is +padded on the left with zeros. The default precision is 1. +When 0 is printed with an explicit precision 0, the output is empty. +.TP +.BR e , E +The +.I double +argument is rounded and converted in the style +.if \w'\*(Pm'=0 .ds Pm \(+- +.BR "" [\-]d \&. ddd e \\*(Pmdd +where there is one digit before the decimal\-point character and the number +of digits after it is equal to the precision; if the precision is missing, +it is taken as 6; if the precision is zero, no decimal\-point character +appears. An +.B E +conversion uses the letter +.B E +(rather than +.BR e ) +to introduce the exponent. The exponent always contains at least two +digits; if the value is zero, the exponent is 00. +.TP +.BR f , F +The +.I double +argument is rounded and converted to decimal notation in the style +.BR "" [\-]ddd \&. ddd, +where the number of digits after the decimal\-point character is equal to +the precision specification. If the precision is missing, it is taken as +6; if the precision is explicitly zero, no decimal\-point character appears. +If a decimal point appears, at least one digit appears before it. + +(The SUSv2 does not know about +.B F +and says that character string representations for infinity and NaN +may be made available. The C99 standard specifies `[-]inf' or `[-]infinity' +for infinity, and a string starting with `nan' for NaN, in the case of +.B f +conversion, and `[-]INF' or `[-]INFINITY' or `NAN*' in the case of +.B F +conversion.) +.TP +.BR g , G +The +.I double +argument is converted in style +.B f +or +.B e +(or +.B F +or +.B E +for +.B G +conversions). The precision specifies the number of significant digits. +If the precision is missing, 6 digits are given; if the precision is zero, +it is treated as 1. Style +.B e +is used if the exponent from its conversion is less than \-4 or greater +than or equal to the precision. Trailing zeros are removed from the +fractional part of the result; a decimal point appears only if it is +followed by at least one digit. +.TP +.BR a , A +(C99; not in SUSv2) For +.B a +conversion, the +.I double +argument is converted to hexadecimal notation (using the letters abcdef) +in the style +.BR "" [-] 0x h \&. hhhh p \\*(Pmd; +for +.B A +conversion the prefix +.BR 0X , +the letters ABCDEF, and the exponent separator +.B P +is used. +There is one hexadecimal digit before the decimal point, +and the number of digits after it is equal to the precision. +The default precision suffices for an exact representation of the value +if an exact representation in base 2 exists +and otherwise is sufficiently large to distinguish values of type +.IR double . +The digit before the decimal point is unspecified for non-normalized +numbers, and nonzero but otherwise unspecified for normalized numbers. +.TP +.B c +If no +.B l +modifier is present, the +.I int +argument is converted to an +.IR "unsigned char" , +and the resulting character is written. +If an +.B l +modifier is present, the +.I wint_t +(wide character) argument is converted to a multibyte sequence by a call +to the +.B wcrtomb +function, with a conversion state starting in the initial state, and the +resulting multibyte string is written. +.TP +.B s +If no +.B l +modifier is present: The +.I "const char *" +argument is expected to be a pointer to an array of character type (pointer +to a string). Characters from the array are written up to (but not +including) a terminating +.B NUL +character; if a precision is specified, no more than the number specified +are written. If a precision is given, no null character need be present; +if the precision is not specified, or is greater than the size of the +array, the array must contain a terminating +.B NUL +character. + +If an +.B l +modifier is present: The +.I "const wchar_t *" +argument is expected to be a pointer to an array of wide characters. +Wide characters from the array are converted to multibyte characters +(each by a call to the +.B wcrtomb +function, with a conversion state starting in the initial state before +the first wide character), up to and including a terminating null +wide character. The resulting multibyte characters are written up to +(but not including) the terminating null byte. If a precision is +specified, no more bytes than the number specified are written, but +no partial multibyte characters are written. Note that the precision +determines the number of +.I bytes +written, not the number of +.I wide characters +or +.IR "screen positions" . +The array must contain a terminating null wide character, unless a +precision is given and it is so small that the number of bytes written +exceeds it before the end of the array is reached. +.TP +.B C +(Not in C99, but in SUSv2.) +Synonym for +.BR lc . +Don't use. +.TP +.B S +(Not in C99, but in SUSv2.) +Synonym for +.BR ls . +Don't use. +.TP +.B p +The +.I "void *" +pointer argument is printed in hexadecimal (as if by +.B %#x +or +.BR %#lx ). +.TP +.B n +The number of characters written so far is stored into the integer +indicated by the +.I "int *" +(or variant) pointer argument. No argument is converted. +.TP +.B % +A `%' is written. No argument is converted. The complete conversion +specification is `%%'. +.PP +.SH EXAMPLES +.br +.if \w'\*(Pi'=0 .ds Pi pi +To print \*(Pi to five decimal places: +.RS +.nf +#include <math.h> +#include <stdio.h> +fprintf(stdout, "pi = %.5f\en", 4 * atan(1.0)); +.fi +.RE +.PP +To print a date and time in the form `Sunday, July 3, 10:02', +where +.I weekday +and +.I month +are pointers to strings: +.RS +.nf +#include <stdio.h> +fprintf(stdout, "%s, %s %d, %.2d:%.2d\en", + weekday, month, day, hour, min); +.fi +.RE +.PP +Many countries use the day-month-year order. +Hence, an internationalized version must be able to print +the arguments in an order specified by the format: +.RS +.nf +#include <stdio.h> +fprintf(stdout, format, + weekday, month, day, hour, min); +.fi +.RE +where +.I format +depends on locale, and may permute the arguments. With the value +.RS +.nf +"%1$s, %3$d. %2$s, %4$d:%5$.2d\en" +.fi +.RE +one might obtain `Sonntag, 3. Juli, 10:02'. +.PP +To allocate a sufficiently large string and print into it +(code correct for both glibc 2.0 and glibc 2.1): +.RS +.nf +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +char * +make_message(const char *fmt, ...) { + /* Guess we need no more than 100 bytes. */ + int n, size = 100; + char *p; + va_list ap; + if ((p = malloc (size)) == NULL) + return NULL; + while (1) { + /* Try to print in the allocated space. */ + va_start(ap, fmt); + n = vsnprintf (p, size, fmt, ap); + va_end(ap); + /* If that worked, return the string. */ + if (n > -1 && n < size) + return p; + /* Else try again with more space. */ + if (n > -1) /* glibc 2.1 */ + size = n+1; /* precisely what is needed */ + else /* glibc 2.0 */ + size *= 2; /* twice the old size */ + if ((p = realloc (p, size)) == NULL) + return NULL; + } +} +.fi +.RE + +.SH NOTES +The glibc implementation of the functions +.B snprintf +and +.B vsnprintf +conforms to the C99 standard, i.e., behaves as described above, +since glibc version 2.1. Until glibc 2.0.6 they would return \-1 +when the output was truncated. +.SH "CONFORMING TO" +The +.BR fprintf , +.BR printf , +.BR sprintf , +.BR vprintf , +.BR vfprintf , +and +.B vsprintf +functions conform to ANSI X3.159-1989 (``ANSI C'') and ISO/IEC 9899:1999 +(``ISO C99''). +The +.B snprintf +and +.B vsnprintf +functions conform to ISO/IEC 9899:1999. +.PP +Concerning the return value of +.BR snprintf , +the SUSv2 and the C99 standard contradict each other: when +.B snprintf +is called with +.IR size =0 +then SUSv2 stipulates an unspecified return value less than 1, +while C99 allows +.I str +to be NULL in this case, and gives the return value (as always) +as the number of characters that would have been written in case +the output string has been large enough. +.PP +Linux libc4 knows about the five C standard flags. +It knows about the length modifiers h,l,L, and the conversions +cdeEfFgGinopsuxX, where F is a synonym for f. +Additionally, it accepts D,O,U as synonyms for ld,lo,lu. +(This is bad, and caused serious bugs later, when +support for %D disappeared.) No locale-dependent radix character, +no thousands' separator, no NaN or infinity, no %m$ and *m$. +.PP +Linux libc5 knows about the five C standard flags and the ' flag, +locale, %m$ and *m$. +It knows about the length modifiers h,l,L,Z,q, but accepts L and q +both for long doubles and for long long integers (this is a bug). +It no longer recognizes FDOU, but adds a new conversion character +.BR m , +which outputs +.IR strerror(errno) . +.PP +glibc 2.0 adds conversion characters C and S. +.PP +glibc 2.1 adds length modifiers hh,j,t,z and conversion characters a,A. +.PP +glibc 2.2 adds the conversion character F with C99 semantics, and the +flag character I. +.SH HISTORY +Unix V7 defines the three routines +.BR printf , +.BR fprintf , +.BR sprintf , +and has the flag -, the width or precision *, the length modifier l, +and the conversions doxfegcsu, and also D,O,U,X as synonyms for ld,lo,lu,lx. +This is still true for BSD 2.9.1, but BSD 2.10 has the flags +#, + and <space> and no longer mentions D,O,U,X. +BSD 2.11 has +.BR vprintf , +.BR vfprintf , +.BR vsprintf , +and warns not to use D,O,U,X. +BSD 4.3 Reno has the flag 0, the length modifiers h and L, +and the conversions n, p, E, G, X (with current meaning) +and deprecates D,O,U. +BSD 4.4 introduces the functions +.B snprintf +and +.BR vsnprintf , +and the length modifier q. +FreeBSD also has functions +.I asprintf +and +.IR vasprintf , +that allocate a buffer large enough for +.BR sprintf . +In glibc there are functions +.I dprintf +and +.I vdprintf +that print to a file descriptor instead of a stream. +.SH BUGS +Because +.B sprintf +and +.B vsprintf +assume an arbitrarily long string, callers must be careful not to overflow +the actual space; this is often impossible to assure. Note that the length +of the strings produced is locale-dependent and difficult to predict. +Use +.B snprintf +and +.B vsnprintf +instead (or +.B asprintf +and +.BR vasprintf ). +.PP +Linux libc4.[45] does not have a +.BR snprintf , +but provides a libbsd that contains an +.B snprintf +equivalent to +.BR sprintf , +i.e., one that ignores the +.I size +argument. +Thus, the use of +.B snprintf +with early libc4 leads to serious security problems. +.PP +Code such as +.BI printf( foo ); +often indicates a bug, since +.I foo +may contain a % character. If +.I foo +comes from untrusted user input, it may contain %n, causing the +.B printf +call to write to memory and creating a security hole. +.\" .PP +.\" Some floating point conversions under early libc4 +.\" caused memory leaks. + +.SH "SEE ALSO" +.BR printf (1), +.BR asprintf (3), +.BR dprintf (3), +.BR scanf (3), +.BR wcrtomb (3), +.BR wprintf (3), +.BR locale (5) |
