1141cc406Sopenharmony_ci#include "../include/sane/config.h"
2141cc406Sopenharmony_ci
3141cc406Sopenharmony_ci#ifndef HAVE_SNPRINTF
4141cc406Sopenharmony_ci
5141cc406Sopenharmony_ci/**************************************************************************
6141cc406Sopenharmony_ci * Copyright 1994-2003 Patrick Powell, San Diego, CA <papowell@lprng.com>
7141cc406Sopenharmony_ci **************************************************************************/
8141cc406Sopenharmony_ci
9141cc406Sopenharmony_ci/*
10141cc406Sopenharmony_ci   Overview:
11141cc406Sopenharmony_ci
12141cc406Sopenharmony_ci   snprintf( char *buffer, int len, const char *format,...)
13141cc406Sopenharmony_ci   plp_unsafe_snprintf( char *buffer, int len, const char *format,...)
14141cc406Sopenharmony_ci     its horribly unsafe companion that does NOT protect you from
15141cc406Sopenharmony_ci     the printing of evil control characters,  but may be necessary
16141cc406Sopenharmony_ci     See the man page documentation below
17141cc406Sopenharmony_ci
18141cc406Sopenharmony_ci   This version of snprintf was developed originally for printing
19141cc406Sopenharmony_ci   on a motley collection of specialized hardware that had NO IO
20141cc406Sopenharmony_ci   library.  Due to contractual restrictions,  a clean room implementation
21141cc406Sopenharmony_ci   of the printf() code had to be developed.
22141cc406Sopenharmony_ci
23141cc406Sopenharmony_ci   The method chosen for printf was to be as paranoid as possible,
24141cc406Sopenharmony_ci   as these platforms had NO memory protection,  and very small
25141cc406Sopenharmony_ci   address spaces.  This made it possible to try to print
26141cc406Sopenharmony_ci   very long strings, i.e. - all of memory, very easily.  To guard
27141cc406Sopenharmony_ci   against this,  all printing was done via a buffer, generous enough
28141cc406Sopenharmony_ci   to hold strings,  but small enough to protect against overruns,
29141cc406Sopenharmony_ci   etc.
30141cc406Sopenharmony_ci
31141cc406Sopenharmony_ci   Strangely enough,  this proved to be of immense importance when
32141cc406Sopenharmony_ci   SPRINTFing to a buffer on a stack...  The rest,  of course,  is
33141cc406Sopenharmony_ci   well known,  as buffer overruns in the stack are a common way to
34141cc406Sopenharmony_ci   do horrible things to operating systems, security, etc etc.
35141cc406Sopenharmony_ci
36141cc406Sopenharmony_ci   This version of snprintf is VERY limited by modern standards.
37141cc406Sopenharmony_ci
38141cc406Sopenharmony_ci   Revision History:
39141cc406Sopenharmony_ci   First Released Version - 1994.  This version had NO comments.
40141cc406Sopenharmony_ci   First Released Version - 1994.  This version had NO comments.
41141cc406Sopenharmony_ci   Second Major Released Version - Tue May 23 10:43:44 PDT 2000
42141cc406Sopenharmony_ci    Configuration and other items changed.  Read this doc.
43141cc406Sopenharmony_ci    Treat this as a new version.
44141cc406Sopenharmony_ci   Minor Revision - Mon Apr  1 09:41:28 PST 2002
45141cc406Sopenharmony_ci     - fixed up some constants and casts
46141cc406Sopenharmony_ci
47141cc406Sopenharmony_ci   COPYRIGHT AND TERMS OF USE:
48141cc406Sopenharmony_ci
49141cc406Sopenharmony_ci   You may use, copy, distribute, or otherwise incorporate this software
50141cc406Sopenharmony_ci   and documentation into any product or other item,  provided that
51141cc406Sopenharmony_ci   the copyright in the documentation and source code as well as the
52141cc406Sopenharmony_ci   source code generated constant strings in the object, executable
53141cc406Sopenharmony_ci   or other code remain in place and are present in executable modules
54141cc406Sopenharmony_ci   or objects.
55141cc406Sopenharmony_ci
56141cc406Sopenharmony_ci   You may modify this code as appropriate to your usage; however the
57141cc406Sopenharmony_ci   modified version must be identified by changing the various source
58141cc406Sopenharmony_ci   and object code identification strings as is appropriately noted
59141cc406Sopenharmony_ci   in the source code.
60141cc406Sopenharmony_ci
61141cc406Sopenharmony_ci   You can use this with the GNU CONFIGURE utility.
62141cc406Sopenharmony_ci   This should define the following macros appropriately:
63141cc406Sopenharmony_ci
64141cc406Sopenharmony_ci   HAVE_STDARG_H - if the <stdargs.h> include file is available
65141cc406Sopenharmony_ci   HAVE_VARARG_H - if the <varargs.h> include file is available
66141cc406Sopenharmony_ci
67141cc406Sopenharmony_ci   HAVE_STRERROR - if the strerror() routine is available.
68141cc406Sopenharmony_ci     If it is not available, then examine the lines containing
69141cc406Sopenharmony_ci     the tests below.
70141cc406Sopenharmony_ci
71141cc406Sopenharmony_ci   HAVE_SYS_ERRLIST  - have sys_errlist available
72141cc406Sopenharmony_ci   HAVE_DECL_SYS_ERRLIST - sys_errlist declaration in include files
73141cc406Sopenharmony_ci   HAVE_SYS_NERR - have sys_nerr available
74141cc406Sopenharmony_ci   HAVE_DECL_SYS_NERR -  sys_nerr declaration in include files
75141cc406Sopenharmony_ci
76141cc406Sopenharmony_ci   HAVE_QUAD_T      - if the quad_t type is defined
77141cc406Sopenharmony_ci   HAVE_LONG_LONG   - if the long long type is defined
78141cc406Sopenharmony_ci   HAVE_LONG_DOUBLE - if the long double type is defined
79141cc406Sopenharmony_ci
80141cc406Sopenharmony_ci     If you are using the GNU configure (autoconf) facility, add the
81141cc406Sopenharmony_ci     following line to the configure.in file, to force checking for the
82141cc406Sopenharmony_ci     quad_t and long long  data types:
83141cc406Sopenharmony_ci
84141cc406Sopenharmony_ci
85141cc406Sopenharmony_ci    AC_CHECK_HEADERS(stdlib.h,stdio.h,unistd.h,errno.h)
86141cc406Sopenharmony_ci	AC_CHECK_FUNCS(strerror)
87141cc406Sopenharmony_ci	AC_CACHE_CHECK(for errno,
88141cc406Sopenharmony_ci	ac_cv_errno,
89141cc406Sopenharmony_ci	[
90141cc406Sopenharmony_ci	AC_TRY_LINK(,[extern int errno; return (errno);],
91141cc406Sopenharmony_ci		ac_cv_errno=yes, ac_cv_errno=no)
92141cc406Sopenharmony_ci	])
93141cc406Sopenharmony_ci	if test "$ac_cv_errno" = yes; then
94141cc406Sopenharmony_ci		AC_DEFINE(HAVE_ERRNO)
95141cc406Sopenharmony_ci		AC_CACHE_CHECK(for errno declaration,
96141cc406Sopenharmony_ci		ac_cv_decl_errno,
97141cc406Sopenharmony_ci		[
98141cc406Sopenharmony_ci		AC_TRY_COMPILE([
99141cc406Sopenharmony_ci		#include <stdio.h>
100141cc406Sopenharmony_ci		#ifdef HAVE_STDLIB_H
101141cc406Sopenharmony_ci		#include <stdlib.h>
102141cc406Sopenharmony_ci		#endif
103141cc406Sopenharmony_ci		#ifdef HAVE_UNISTD_H
104141cc406Sopenharmony_ci		#include <unistd.h>
105141cc406Sopenharmony_ci		#endif
106141cc406Sopenharmony_ci		#ifdef HAVE_ERRNO_H
107141cc406Sopenharmony_ci		#include <errno.h>
108141cc406Sopenharmony_ci		],[return(sys_nerr);],
109141cc406Sopenharmony_ci			ac_cv_decl_errno=yes, ac_cv_decl_errno=no)
110141cc406Sopenharmony_ci		])
111141cc406Sopenharmony_ci		if test "$ac_cv_decl_errno" = yes; then
112141cc406Sopenharmony_ci			AC_DEFINE(HAVE_DECL_ERRNO)
113141cc406Sopenharmony_ci		fi;
114141cc406Sopenharmony_ci	fi
115141cc406Sopenharmony_ci
116141cc406Sopenharmony_ci	AC_CACHE_CHECK(for sys_nerr,
117141cc406Sopenharmony_ci	ac_cv_sys_nerr,
118141cc406Sopenharmony_ci	[
119141cc406Sopenharmony_ci	AC_TRY_LINK(,[extern int sys_nerr; return (sys_nerr);],
120141cc406Sopenharmony_ci		ac_cv_sys_nerr=yes, ac_cv_sys_nerr=no)
121141cc406Sopenharmony_ci	])
122141cc406Sopenharmony_ci	if test "$ac_cv_sys_nerr" = yes; then
123141cc406Sopenharmony_ci		AC_DEFINE(HAVE_SYS_NERR)
124141cc406Sopenharmony_ci		AC_CACHE_CHECK(for sys_nerr declaration,
125141cc406Sopenharmony_ci		ac_cv_decl_sys_nerr,
126141cc406Sopenharmony_ci		[
127141cc406Sopenharmony_ci		AC_TRY_COMPILE([
128141cc406Sopenharmony_ci		#include <stdio.h>
129141cc406Sopenharmony_ci		#ifdef HAVE_STDLIB_H
130141cc406Sopenharmony_ci		#include <stdlib.h>
131141cc406Sopenharmony_ci		#endif
132141cc406Sopenharmony_ci		#ifdef HAVE_UNISTD_H
133141cc406Sopenharmony_ci		#include <unistd.h>
134141cc406Sopenharmony_ci		#endif],[return(sys_nerr);],
135141cc406Sopenharmony_ci		ac_cv_decl_sys_nerr_def=yes, ac_cv_decl_sys_nerr_def=no)
136141cc406Sopenharmony_ci		])
137141cc406Sopenharmony_ci		if test "$ac_cv_decl_sys_nerr" = yes; then
138141cc406Sopenharmony_ci			AC_DEFINE(HAVE_DECL_SYS_NERR)
139141cc406Sopenharmony_ci		fi
140141cc406Sopenharmony_ci	fi
141141cc406Sopenharmony_ci
142141cc406Sopenharmony_ci
143141cc406Sopenharmony_ci	AC_CACHE_CHECK(for sys_errlist array,
144141cc406Sopenharmony_ci	ac_cv_sys_errlist,
145141cc406Sopenharmony_ci	[AC_TRY_LINK(,[extern char *sys_errlist[];
146141cc406Sopenharmony_ci		sys_errlist[0];],
147141cc406Sopenharmony_ci		ac_cv_sys_errlist=yes, ac_cv_sys_errlist=no)
148141cc406Sopenharmony_ci	])
149141cc406Sopenharmony_ci	if test "$ac_cv_sys_errlist" = yes; then
150141cc406Sopenharmony_ci		AC_DEFINE(HAVE_SYS_ERRLIST)
151141cc406Sopenharmony_ci		AC_CACHE_CHECK(for sys_errlist declaration,
152141cc406Sopenharmony_ci		ac_cv_sys_errlist_def,
153141cc406Sopenharmony_ci		[AC_TRY_COMPILE([
154141cc406Sopenharmony_ci		#include <stdio.h>
155141cc406Sopenharmony_ci		#include <errno.h>
156141cc406Sopenharmony_ci		#ifdef HAVE_STDLIB_H
157141cc406Sopenharmony_ci		#include <stdlib.h>
158141cc406Sopenharmony_ci		#endif
159141cc406Sopenharmony_ci		#ifdef HAVE_UNISTD_H
160141cc406Sopenharmony_ci		#include <unistd.h>
161141cc406Sopenharmony_ci		#endif],[char *s = sys_errlist[0]; return(*s);],
162141cc406Sopenharmony_ci		ac_cv_decl_sys_errlist=yes, ac_cv_decl_sys_errlist=no)
163141cc406Sopenharmony_ci		])
164141cc406Sopenharmony_ci		if test "$ac_cv_decl_sys_errlist" = yes; then
165141cc406Sopenharmony_ci			AC_DEFINE(HAVE_DECL_SYS_ERRLIST)
166141cc406Sopenharmony_ci		fi
167141cc406Sopenharmony_ci	fi
168141cc406Sopenharmony_ci
169141cc406Sopenharmony_ci
170141cc406Sopenharmony_ci
171141cc406Sopenharmony_ci	AC_CACHE_CHECK(checking for long long,
172141cc406Sopenharmony_ci	ac_cv_long_long,
173141cc406Sopenharmony_ci	[
174141cc406Sopenharmony_ci	AC_TRY_COMPILE([
175141cc406Sopenharmony_ci	#include <stdio.h>
176141cc406Sopenharmony_ci	#include <sys/types.h>
177141cc406Sopenharmony_ci	], [printf("%d",sizeof(long long));],
178141cc406Sopenharmony_ci	ac_cv_long_long=yes, ac_cv_long_long=no)
179141cc406Sopenharmony_ci	])
180141cc406Sopenharmony_ci	if test $ac_cv_long_long = yes; then
181141cc406Sopenharmony_ci	  AC_DEFINE(HAVE_LONG_LONG)
182141cc406Sopenharmony_ci	fi
183141cc406Sopenharmony_ci
184141cc406Sopenharmony_ci	AC_CACHE_CHECK(checking for long double,
185141cc406Sopenharmony_ci	ac_cv_long_double,
186141cc406Sopenharmony_ci	[
187141cc406Sopenharmony_ci	AC_TRY_COMPILE([
188141cc406Sopenharmony_ci	#include <stdio.h>
189141cc406Sopenharmony_ci	#include <sys/types.h>
190141cc406Sopenharmony_ci	], [printf("%d",sizeof(long double));],
191141cc406Sopenharmony_ci	ac_cv_long_double=yes, ac_cv_long_double=no)
192141cc406Sopenharmony_ci	])
193141cc406Sopenharmony_ci	if test $ac_cv_long_double = yes; then
194141cc406Sopenharmony_ci	  AC_DEFINE(HAVE_LONG_DOUBLE)
195141cc406Sopenharmony_ci	fi
196141cc406Sopenharmony_ci
197141cc406Sopenharmony_ci	AC_CACHE_CHECK(checking for quad_t,
198141cc406Sopenharmony_ci	ac_cv_quad_t,
199141cc406Sopenharmony_ci	[
200141cc406Sopenharmony_ci	AC_TRY_COMPILE([
201141cc406Sopenharmony_ci	#include <stdio.h>
202141cc406Sopenharmony_ci	#include <sys/types.h>
203141cc406Sopenharmony_ci	], [printf("%d",sizeof(quad_t));],
204141cc406Sopenharmony_ci	ac_cv_quad_t=yes, ac_cv_quad_t=no)
205141cc406Sopenharmony_ci	])
206141cc406Sopenharmony_ci	if test $ac_cv_quad_t = yes; then
207141cc406Sopenharmony_ci	  AC_DEFINE(HAVE_QUAD_T)
208141cc406Sopenharmony_ci	fi
209141cc406Sopenharmony_ci
210141cc406Sopenharmony_ci
211141cc406Sopenharmony_ci
212141cc406Sopenharmony_ci NAME
213141cc406Sopenharmony_ci     snprintf, plp_vsnprintf - formatted output conversion
214141cc406Sopenharmony_ci
215141cc406Sopenharmony_ci SYNOPSIS
216141cc406Sopenharmony_ci     #include <stdio.h>
217141cc406Sopenharmony_ci     #include <stdarg.h>
218141cc406Sopenharmony_ci
219141cc406Sopenharmony_ci     int
220141cc406Sopenharmony_ci     snprintf(const char *format, size_t size, va_list ap);
221141cc406Sopenharmony_ci     int
222141cc406Sopenharmony_ci     plp_unsafe_snprintf(const char *format, size_t size, va_list ap);
223141cc406Sopenharmony_ci
224141cc406Sopenharmony_ci     AKA snprintf and unsafe_snprintf in the documentation below
225141cc406Sopenharmony_ci
226141cc406Sopenharmony_ci     int
227141cc406Sopenharmony_ci     vsnprintf(char *str, size_t size, const char *format, va_list ap);
228141cc406Sopenharmony_ci     int
229141cc406Sopenharmony_ci     unsafe_vsnprintf(char *str, size_t size, const char *format, va_list ap);
230141cc406Sopenharmony_ci
231141cc406Sopenharmony_ci     AKA vsnprintf and unsafe_vsnprintf in the documentation below
232141cc406Sopenharmony_ci
233141cc406Sopenharmony_ci     (Multithreaded Safe)
234141cc406Sopenharmony_ci
235141cc406Sopenharmony_ci DESCRIPTION
236141cc406Sopenharmony_ci     The printf() family of functions produces output according to
237141cc406Sopenharmony_ci     a format as described below.  Snprintf(), and vsnprintf()
238141cc406Sopenharmony_ci     write to the character string str. These functions write the
239141cc406Sopenharmony_ci     output under the control of a format string that specifies
240141cc406Sopenharmony_ci     how subsequent arguments (or arguments accessed via the
241141cc406Sopenharmony_ci     variable-length argument facilities of stdarg(3))  are converted
242141cc406Sopenharmony_ci     for output.  These functions return the number of characters
243141cc406Sopenharmony_ci     printed (not including the trailing `\0' used to end output
244141cc406Sopenharmony_ci     to strings).  Snprintf() and vsnprintf() will write at most
245141cc406Sopenharmony_ci     size-1 of the characters printed into the output string (the
246141cc406Sopenharmony_ci     size'th character then gets the terminating `\0'); if the
247141cc406Sopenharmony_ci     return value is greater than or equal to the size argument,
248141cc406Sopenharmony_ci     the string was too short and some of the printed characters
249141cc406Sopenharmony_ci     were discarded.  The size or str may be given as zero to find
250141cc406Sopenharmony_ci     out how many characters are needed; in this case, the str
251141cc406Sopenharmony_ci     argument is ignored.
252141cc406Sopenharmony_ci
253141cc406Sopenharmony_ci     By default, the snprintf function will not format control
254141cc406Sopenharmony_ci     characters (except new line and tab) in strings.  This is a
255141cc406Sopenharmony_ci     safety feature that has proven to be extremely critical when
256141cc406Sopenharmony_ci     using snprintf for secure applications and when debugging.
257141cc406Sopenharmony_ci     If you MUST have control characters formatted or printed,
258141cc406Sopenharmony_ci     then use the unsafe_snprintf() and unsafe_vsnprintf() and on
259141cc406Sopenharmony_ci     your own head be the consequences.  You have been warned.
260141cc406Sopenharmony_ci
261141cc406Sopenharmony_ci     There is one exception to the comments above, and that is
262141cc406Sopenharmony_ci     the "%c" (character) format.  It brutally assumes that the
263141cc406Sopenharmony_ci     user will have performed the necessary 'isprint()' or other
264141cc406Sopenharmony_ci     checks and uses the integer value as a character.
265141cc406Sopenharmony_ci
266141cc406Sopenharmony_ci     The format string is composed of zero or more directives:
267141cc406Sopenharmony_ci     ordinary characters (not %), which are copied unchanged to
268141cc406Sopenharmony_ci     the output stream; and conversion specifications, each
269141cc406Sopenharmony_ci     of which results in fetching zero or more subsequent arguments.
270141cc406Sopenharmony_ci     Each conversion specification is introduced by the character
271141cc406Sopenharmony_ci     %. The arguments must correspond properly (after type promotion)
272141cc406Sopenharmony_ci     with the conversion specifier.  After the %, the following
273141cc406Sopenharmony_ci     appear in sequence:
274141cc406Sopenharmony_ci
275141cc406Sopenharmony_ci     o   Zero or more of the following flags:
276141cc406Sopenharmony_ci
277141cc406Sopenharmony_ci	   -   A zero `0' character specifying zero padding.  For
278141cc406Sopenharmony_ci	     all conversions except n, the converted value is padded
279141cc406Sopenharmony_ci	     on the left with zeros rather than blanks.  If a
280141cc406Sopenharmony_ci	     precision is given with a numeric conversion (d, i,
281141cc406Sopenharmony_ci	     o, u, i, x, and X), the `0' flag is ignored.
282141cc406Sopenharmony_ci
283141cc406Sopenharmony_ci       -   A negative field width flag `-' indicates the converted
284141cc406Sopenharmony_ci	     value is to be left adjusted on the field boundary.  Except
285141cc406Sopenharmony_ci	     for n conversions, the converted value is padded on
286141cc406Sopenharmony_ci	     the right with blanks, rather than on the left with
287141cc406Sopenharmony_ci	     blanks or zeros.  A `-' overrides a `0' if both are
288141cc406Sopenharmony_ci	     given.
289141cc406Sopenharmony_ci
290141cc406Sopenharmony_ci	   -   A space, specifying that a blank should be left before
291141cc406Sopenharmony_ci	     a positive number produced by a signed conversion (d, e, E, f,
292141cc406Sopenharmony_ci	     g, G, or i).
293141cc406Sopenharmony_ci
294141cc406Sopenharmony_ci	   -   A `+' character specifying that a sign always be placed
295141cc406Sopenharmony_ci	     before a number produced by a signed conversion.  A `+' overrides
296141cc406Sopenharmony_ci	     a space if both are used.
297141cc406Sopenharmony_ci
298141cc406Sopenharmony_ci     o   An optional decimal digit string specifying a minimum
299141cc406Sopenharmony_ci		 field width.  If the converted value has fewer
300141cc406Sopenharmony_ci		 characters than the field width, it will be padded
301141cc406Sopenharmony_ci		 with spaces on the left (or right, if the
302141cc406Sopenharmony_ci		 left-adjustment flag has been given) to fill out
303141cc406Sopenharmony_ci		 the field width.
304141cc406Sopenharmony_ci
305141cc406Sopenharmony_ci     o   An optional precision, in the form of a period `.' followed
306141cc406Sopenharmony_ci		 by an optional digit string.  If the digit string
307141cc406Sopenharmony_ci		 is omitted, the precision is taken as zero.  This
308141cc406Sopenharmony_ci		 gives the minimum number of digits to appear for
309141cc406Sopenharmony_ci		 d, i, o, u, x, and X conversions, the number of
310141cc406Sopenharmony_ci		 digits to appear after the decimal-point for e,
311141cc406Sopenharmony_ci		 E, and f conversions, the maximum number of
312141cc406Sopenharmony_ci		 significant digits for g and G conversions, or
313141cc406Sopenharmony_ci		 the maximum number of characters to be printed
314141cc406Sopenharmony_ci		 from a string for s conversions.
315141cc406Sopenharmony_ci
316141cc406Sopenharmony_ci     o   The optional character h, specifying that a following d,
317141cc406Sopenharmony_ci		 i, o, u, x, or X conversion corresponds to a short
318141cc406Sopenharmony_ci		 int or unsigned short int argument, or that a
319141cc406Sopenharmony_ci		 following n conversion corresponds to a pointer
320141cc406Sopenharmony_ci		 to a short int argument.
321141cc406Sopenharmony_ci
322141cc406Sopenharmony_ci     o   The optional character l (ell) specifying that a following
323141cc406Sopenharmony_ci		 d, i, o, u, x, or X conversion applies to a pointer
324141cc406Sopenharmony_ci		 to a long int or unsigned long int argument, or
325141cc406Sopenharmony_ci		 that a following n conversion corresponds to a
326141cc406Sopenharmony_ci		 pointer to a long int argument.
327141cc406Sopenharmony_ci
328141cc406Sopenharmony_ci     o   The optional character q, specifying that a following d,
329141cc406Sopenharmony_ci		 i, o, u, x, or X conversion corresponds to a quad_t
330141cc406Sopenharmony_ci		 or u_quad_t argument, or that a following n
331141cc406Sopenharmony_ci		 conversion corresponds to a quad_t argument.
332141cc406Sopenharmony_ci         This value is always printed in HEX notation.  Tough.
333141cc406Sopenharmony_ci         quad_t's are an OS system implementation, and should
334141cc406Sopenharmony_ci         not be allowed.
335141cc406Sopenharmony_ci
336141cc406Sopenharmony_ci     o   The character L specifying that a following e, E, f, g,
337141cc406Sopenharmony_ci		 or G conversion corresponds to a long double
338141cc406Sopenharmony_ci		 argument.
339141cc406Sopenharmony_ci
340141cc406Sopenharmony_ci     o   A character that specifies the type of conversion to be applied.
341141cc406Sopenharmony_ci
342141cc406Sopenharmony_ci
343141cc406Sopenharmony_ci     A field width or precision, or both, may be indicated by an asterisk `*'
344141cc406Sopenharmony_ci     instead of a digit string.  In this case, an int argument supplies the
345141cc406Sopenharmony_ci     field width or precision.  A negative field width is treated as a left
346141cc406Sopenharmony_ci     adjustment flag followed by a positive field width; a negative precision
347141cc406Sopenharmony_ci     is treated as though it were missing.
348141cc406Sopenharmony_ci
349141cc406Sopenharmony_ci     The conversion specifiers and their meanings are:
350141cc406Sopenharmony_ci
351141cc406Sopenharmony_ci     diouxX  The int (or appropriate variant) argument is converted to signed
352141cc406Sopenharmony_ci			 decimal (d and i), unsigned octal (o), unsigned decimal
353141cc406Sopenharmony_ci			 (u), or unsigned hexadecimal (x and X) notation.  The
354141cc406Sopenharmony_ci			 letters abcdef are used for x conversions; the letters
355141cc406Sopenharmony_ci			 ABCDEF are used for X conversions.  The precision, if
356141cc406Sopenharmony_ci			 any, gives the minimum number of digits that must
357141cc406Sopenharmony_ci			 appear; if the converted value requires fewer digits,
358141cc406Sopenharmony_ci			 it is padded on the left with zeros.
359141cc406Sopenharmony_ci
360141cc406Sopenharmony_ci     eE      The double argument is rounded and converted in the style
361141cc406Sopenharmony_ci             [-]d.ddde+-dd where there is one digit before the decimal-point
362141cc406Sopenharmony_ci			 character and the number of digits after it is equal
363141cc406Sopenharmony_ci			 to the precision; if the precision is missing, it is
364141cc406Sopenharmony_ci			 taken as 6; if the precision is zero, no decimal-point
365141cc406Sopenharmony_ci			 character appears.  An E conversion uses the letter
366141cc406Sopenharmony_ci			 E (rather than e) to introduce the exponent.
367141cc406Sopenharmony_ci			 The exponent always contains at least two digits; if
368141cc406Sopenharmony_ci			 the value is zero, the exponent is 00.
369141cc406Sopenharmony_ci
370141cc406Sopenharmony_ci     f       The double argument is rounded and converted to decimal notation
371141cc406Sopenharmony_ci             in the style [-]ddd.ddd, where the number of digits after the
372141cc406Sopenharmony_ci             decimal-point character is equal to the precision specification.
373141cc406Sopenharmony_ci             If the precision is missing, it is taken as 6; if the precision
374141cc406Sopenharmony_ci             is explicitly zero, no decimal-point character appears.  If a
375141cc406Sopenharmony_ci             decimal point appears, at least one digit appears before it.
376141cc406Sopenharmony_ci
377141cc406Sopenharmony_ci     g       The double argument is converted in style f or e (or
378141cc406Sopenharmony_ci			 E for G conversions).  The precision specifies the
379141cc406Sopenharmony_ci			 number of significant digits.  If the precision is
380141cc406Sopenharmony_ci			 missing, 6 digits are given; if the precision is zero,
381141cc406Sopenharmony_ci			 it is treated as 1.  Style e is used if the exponent
382141cc406Sopenharmony_ci			 from its conversion is less than -4 or greater than
383141cc406Sopenharmony_ci			 or equal to the precision.  Trailing zeros are removed
384141cc406Sopenharmony_ci			 from the fractional part of the result; a decimal
385141cc406Sopenharmony_ci			 point appears only if it is followed by at least one
386141cc406Sopenharmony_ci			 digit.
387141cc406Sopenharmony_ci
388141cc406Sopenharmony_ci     c       The int argument is converted to an unsigned char,
389141cc406Sopenharmony_ci             and the resulting character is written.
390141cc406Sopenharmony_ci
391141cc406Sopenharmony_ci     s       The ``char *'' argument is expected to be a pointer to an array
392141cc406Sopenharmony_ci			 of character type (pointer to a string).  Characters
393141cc406Sopenharmony_ci			 from the array are written up to (but not including)
394141cc406Sopenharmony_ci			 a terminating NUL character; if a precision is
395141cc406Sopenharmony_ci			 specified, no more than the number specified are
396141cc406Sopenharmony_ci			 written.  If a precision is given, no null character
397141cc406Sopenharmony_ci			 need be present; if the precision is not specified,
398141cc406Sopenharmony_ci			 or is greater than the size of the array, the array
399141cc406Sopenharmony_ci			 must contain a terminating NUL character.
400141cc406Sopenharmony_ci
401141cc406Sopenharmony_ci     %       A `%' is written. No argument is converted. The complete
402141cc406Sopenharmony_ci             conversion specification is `%%'.
403141cc406Sopenharmony_ci
404141cc406Sopenharmony_ci     In no case does a non-existent or small field width cause truncation of a
405141cc406Sopenharmony_ci     field; if the result of a conversion is wider than the field width, the
406141cc406Sopenharmony_ci     field is expanded to contain the conversion result.
407141cc406Sopenharmony_ci
408141cc406Sopenharmony_ci EXAMPLES
409141cc406Sopenharmony_ci     To print a date and time in the form `Sunday, July 3, 10:02', where
410141cc406Sopenharmony_ci     weekday and month are pointers to strings:
411141cc406Sopenharmony_ci
412141cc406Sopenharmony_ci           #include <stdio.h>
413141cc406Sopenharmony_ci           fprintf(stdout, "%s, %s %d, %.2d:%.2d\n",
414141cc406Sopenharmony_ci                   weekday, month, day, hour, min);
415141cc406Sopenharmony_ci
416141cc406Sopenharmony_ci     To print pi to five decimal places:
417141cc406Sopenharmony_ci
418141cc406Sopenharmony_ci           #include <math.h>
419141cc406Sopenharmony_ci           #include <stdio.h>
420141cc406Sopenharmony_ci           fprintf(stdout, "pi = %.5f\n", 4 * atan(1.0));
421141cc406Sopenharmony_ci
422141cc406Sopenharmony_ci     To allocate a 128 byte string and print into it:
423141cc406Sopenharmony_ci
424141cc406Sopenharmony_ci           #include <stdio.h>
425141cc406Sopenharmony_ci           #include <stdlib.h>
426141cc406Sopenharmony_ci           #include <stdarg.h>
427141cc406Sopenharmony_ci           char *newfmt(const char *fmt, ...)
428141cc406Sopenharmony_ci           {
429141cc406Sopenharmony_ci               char *p;
430141cc406Sopenharmony_ci               va_list ap;
431141cc406Sopenharmony_ci               if ((p = malloc(128)) == NULL)
432141cc406Sopenharmony_ci                       return (NULL);
433141cc406Sopenharmony_ci               va_start(ap, fmt);
434141cc406Sopenharmony_ci               (void) vsnprintf(p, 128, fmt, ap);
435141cc406Sopenharmony_ci               va_end(ap);
436141cc406Sopenharmony_ci               return (p);
437141cc406Sopenharmony_ci           }
438141cc406Sopenharmony_ci
439141cc406Sopenharmony_ci SEE ALSO
440141cc406Sopenharmony_ci     printf(1),  scanf(3)
441141cc406Sopenharmony_ci
442141cc406Sopenharmony_ci STANDARDS
443141cc406Sopenharmony_ci     Turkey C Standardization and wimpy POSIX folks did not define
444141cc406Sopenharmony_ci     snprintf or vsnprintf().
445141cc406Sopenharmony_ci
446141cc406Sopenharmony_ci BUGS
447141cc406Sopenharmony_ci     The conversion formats %D, %O, and %U are not standard and are provided
448141cc406Sopenharmony_ci     only for backward compatibility.  The effect of padding the %p format
449141cc406Sopenharmony_ci     with zeros (either by the `0' flag or by specifying a precision), and the
450141cc406Sopenharmony_ci     benign effect (i.e., none) of the `#' flag on %n and %p conversions, as
451141cc406Sopenharmony_ci     well as other nonsensical combinations such as %Ld, are not standard;
452141cc406Sopenharmony_ci     such combinations should be avoided.
453141cc406Sopenharmony_ci
454141cc406Sopenharmony_ci     The typedef names quad_t and u_quad_t are infelicitous.
455141cc406Sopenharmony_ci
456141cc406Sopenharmony_ci*/
457141cc406Sopenharmony_ci
458141cc406Sopenharmony_ci
459141cc406Sopenharmony_ci#include <sys/types.h>
460141cc406Sopenharmony_ci#include <ctype.h>
461141cc406Sopenharmony_ci#include <stdlib.h>
462141cc406Sopenharmony_ci#include <stdio.h>
463141cc406Sopenharmony_ci#if defined(HAVE_STRING_H)
464141cc406Sopenharmony_ci# include <string.h>
465141cc406Sopenharmony_ci#endif
466141cc406Sopenharmony_ci#if defined(HAVE_STRINGS_H)
467141cc406Sopenharmony_ci# include <strings.h>
468141cc406Sopenharmony_ci#endif
469141cc406Sopenharmony_ci#if defined(HAVE_ERRNO_H)
470141cc406Sopenharmony_ci#include <errno.h>
471141cc406Sopenharmony_ci#endif
472141cc406Sopenharmony_ci
473141cc406Sopenharmony_ci/*
474141cc406Sopenharmony_ci * For testing, define these values
475141cc406Sopenharmony_ci */
476141cc406Sopenharmony_ci#if 0
477141cc406Sopenharmony_ci#define HAVE_STDARG_H 1
478141cc406Sopenharmony_ci#define TEST 1
479141cc406Sopenharmony_ci#define HAVE_QUAD_T 1
480141cc406Sopenharmony_ci#endif
481141cc406Sopenharmony_ci
482141cc406Sopenharmony_ci/**** ENDINCLUDE ****/
483141cc406Sopenharmony_ci
484141cc406Sopenharmony_ci/*************************************************
485141cc406Sopenharmony_ci * KEEP THIS STRING - MODIFY AT THE END WITH YOUR REVISIONS
486141cc406Sopenharmony_ci * i.e. - the LOCAL REVISIONS part is for your use
487141cc406Sopenharmony_ci *************************************************/
488141cc406Sopenharmony_ci
489141cc406Sopenharmony_ci
490141cc406Sopenharmony_ci static char *const _id = "plp_snprintf V2000.08.18 Copyright Patrick Powell 1988-2000 "
491141cc406Sopenharmony_ci "$Id: plp_snprintf.c,v 1.4 2005/04/14 20:05:19 papowell Exp $"
492141cc406Sopenharmony_ci " LOCAL REVISIONS: renamed plp_snprintf to snprintf, conditionalized everything on HAVE_SNPRINTF";
493141cc406Sopenharmony_ci
494141cc406Sopenharmony_ci/* varargs declarations: */
495141cc406Sopenharmony_ci
496141cc406Sopenharmony_ci# undef HAVE_STDARGS    /* let's hope that works everywhere (mj) */
497141cc406Sopenharmony_ci# undef VA_LOCAL_DECL
498141cc406Sopenharmony_ci# undef VA_START
499141cc406Sopenharmony_ci# undef VA_SHIFT
500141cc406Sopenharmony_ci# undef VA_END
501141cc406Sopenharmony_ci
502141cc406Sopenharmony_ci#if defined(HAVE_STDARG_H)
503141cc406Sopenharmony_ci# include <stdarg.h>
504141cc406Sopenharmony_ci# define HAVE_STDARGS    /* let's hope that works everywhere (mj) */
505141cc406Sopenharmony_ci# define VA_LOCAL_DECL   va_list ap;
506141cc406Sopenharmony_ci# define VA_START(f)     va_start(ap, f)
507141cc406Sopenharmony_ci# define VA_SHIFT(v,t)	;	/* no-op for ANSI */
508141cc406Sopenharmony_ci# define VA_END          va_end(ap)
509141cc406Sopenharmony_ci#else
510141cc406Sopenharmony_ci# if defined(HAVE_VARARGS_H)
511141cc406Sopenharmony_ci#  include <varargs.h>
512141cc406Sopenharmony_ci#  undef HAVE_STDARGS
513141cc406Sopenharmony_ci#  define VA_LOCAL_DECL   va_list ap;
514141cc406Sopenharmony_ci#  define VA_START(f)     va_start(ap)		/* f is ignored! */
515141cc406Sopenharmony_ci#  define VA_SHIFT(v,t)	v = va_arg(ap,t)
516141cc406Sopenharmony_ci#  define VA_END		va_end(ap)
517141cc406Sopenharmony_ci# else
518141cc406Sopenharmony_ci XX ** NO VARARGS ** XX
519141cc406Sopenharmony_ci# endif
520141cc406Sopenharmony_ci#endif
521141cc406Sopenharmony_ci
522141cc406Sopenharmony_ci union value {
523141cc406Sopenharmony_ci#if defined(HAVE_QUAD_T)
524141cc406Sopenharmony_ci	quad_t qvalue;
525141cc406Sopenharmony_ci#endif
526141cc406Sopenharmony_ci#if defined(HAVE_LONG_LONG)
527141cc406Sopenharmony_ci	long long value;
528141cc406Sopenharmony_ci#else
529141cc406Sopenharmony_ci	long value;
530141cc406Sopenharmony_ci#endif
531141cc406Sopenharmony_ci	double dvalue;
532141cc406Sopenharmony_ci};
533141cc406Sopenharmony_ci
534141cc406Sopenharmony_ci#undef CVAL
535141cc406Sopenharmony_ci#define CVAL(s) (*((unsigned char *)s))
536141cc406Sopenharmony_ci#define safestrlen(s) ((s)?strlen(s):0)
537141cc406Sopenharmony_ci
538141cc406Sopenharmony_ci
539141cc406Sopenharmony_ci static char * plp_Errormsg ( int err, char *buffer );
540141cc406Sopenharmony_ci static void dopr( int visible_control, char **buffer, int *left,
541141cc406Sopenharmony_ci	const char *format, va_list args );
542141cc406Sopenharmony_ci static void fmtstr( int visible_control, char **buffer, int *left,
543141cc406Sopenharmony_ci	char *value, int ljust, int len, int zpad, int precision );
544141cc406Sopenharmony_ci static void fmtnum(  char **buffer, int *left,
545141cc406Sopenharmony_ci	union value *value, int base, int dosign,
546141cc406Sopenharmony_ci	int ljust, int len, int zpad, int precision );
547141cc406Sopenharmony_ci#if defined(HAVE_QUAD_T)
548141cc406Sopenharmony_ci static void fmtquad(  char **buffer, int *left,
549141cc406Sopenharmony_ci	union value *value, int base, int dosign,
550141cc406Sopenharmony_ci	int ljust, int len, int zpad, int precision );
551141cc406Sopenharmony_ci#endif
552141cc406Sopenharmony_ci static void fmtdouble( char **buffer, int *left,
553141cc406Sopenharmony_ci	int fmt, double value,
554141cc406Sopenharmony_ci	int ljust, int len, int zpad, int precision );
555141cc406Sopenharmony_ci static void dostr(  char **buffer, int *left, char *str );
556141cc406Sopenharmony_ci static void dopr_outch(  char **buffer, int *left, int c );
557141cc406Sopenharmony_ci/* VARARGS3 */
558141cc406Sopenharmony_ci#ifdef HAVE_STDARGS
559141cc406Sopenharmony_ci int plp_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
560141cc406Sopenharmony_ci#else
561141cc406Sopenharmony_ci int plp_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
562141cc406Sopenharmony_ci#endif
563141cc406Sopenharmony_ci
564141cc406Sopenharmony_ci{
565141cc406Sopenharmony_ci	int left;
566141cc406Sopenharmony_ci	char *buffer;
567141cc406Sopenharmony_ci	if( (int)count < 0 ) count = 0;
568141cc406Sopenharmony_ci	left = count;
569141cc406Sopenharmony_ci	if( count == 0 ) str = 0;
570141cc406Sopenharmony_ci	buffer = str;
571141cc406Sopenharmony_ci	dopr( 1, &buffer, &left, fmt, args );
572141cc406Sopenharmony_ci	/* fprintf(stderr,"str 0x%x, buffer 0x%x, count %d, left %d\n",
573141cc406Sopenharmony_ci		(int)str, (int)buffer, count, left ); */
574141cc406Sopenharmony_ci	if( str && count > 0 ){
575141cc406Sopenharmony_ci		if( left > 0 ){
576141cc406Sopenharmony_ci			str[count-left] = 0;
577141cc406Sopenharmony_ci		} else {
578141cc406Sopenharmony_ci			str[count-1] = 0;
579141cc406Sopenharmony_ci		}
580141cc406Sopenharmony_ci	}
581141cc406Sopenharmony_ci	return(count - left);
582141cc406Sopenharmony_ci}
583141cc406Sopenharmony_ci
584141cc406Sopenharmony_ci/* VARARGS3 */
585141cc406Sopenharmony_ci#ifdef HAVE_STDARGS
586141cc406Sopenharmony_ci int plp_unsafe_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
587141cc406Sopenharmony_ci#else
588141cc406Sopenharmony_ci int plp_unsafe_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
589141cc406Sopenharmony_ci#endif
590141cc406Sopenharmony_ci{
591141cc406Sopenharmony_ci	int left;
592141cc406Sopenharmony_ci	char *buffer;
593141cc406Sopenharmony_ci	if( (int)count < 0 ) count = 0;
594141cc406Sopenharmony_ci	left = count;
595141cc406Sopenharmony_ci	if( count == 0 ) str = 0;
596141cc406Sopenharmony_ci	buffer = str;
597141cc406Sopenharmony_ci	dopr( 0, &buffer, &left, fmt, args );
598141cc406Sopenharmony_ci	/* fprintf(stderr,"str 0x%x, buffer 0x%x, count %d, left %d\n",
599141cc406Sopenharmony_ci		(int)str, (int)buffer, count, left ); */
600141cc406Sopenharmony_ci	if( str && count > 0 ){
601141cc406Sopenharmony_ci		if( left > 0 ){
602141cc406Sopenharmony_ci			str[count-left] = 0;
603141cc406Sopenharmony_ci		} else {
604141cc406Sopenharmony_ci			str[count-1] = 0;
605141cc406Sopenharmony_ci		}
606141cc406Sopenharmony_ci	}
607141cc406Sopenharmony_ci	return(count - left);
608141cc406Sopenharmony_ci}
609141cc406Sopenharmony_ci
610141cc406Sopenharmony_ci/* VARARGS3 */
611141cc406Sopenharmony_ci#ifdef HAVE_STDARGS
612141cc406Sopenharmony_ci int snprintf (char *str,size_t count,const char *fmt,...)
613141cc406Sopenharmony_ci#else
614141cc406Sopenharmony_ci int snprintf (va_alist) va_dcl
615141cc406Sopenharmony_ci#endif
616141cc406Sopenharmony_ci{
617141cc406Sopenharmony_ci#ifndef HAVE_STDARGS
618141cc406Sopenharmony_ci    char *str;
619141cc406Sopenharmony_ci	size_t count;
620141cc406Sopenharmony_ci    char *fmt;
621141cc406Sopenharmony_ci#endif
622141cc406Sopenharmony_ci	int n = 0;
623141cc406Sopenharmony_ci    VA_LOCAL_DECL
624141cc406Sopenharmony_ci
625141cc406Sopenharmony_ci    VA_START (fmt);
626141cc406Sopenharmony_ci    VA_SHIFT (str, char *);
627141cc406Sopenharmony_ci    VA_SHIFT (count, size_t );
628141cc406Sopenharmony_ci    VA_SHIFT (fmt, char *);
629141cc406Sopenharmony_ci    n = plp_vsnprintf ( str, count, fmt, ap);
630141cc406Sopenharmony_ci    VA_END;
631141cc406Sopenharmony_ci	return( n );
632141cc406Sopenharmony_ci}
633141cc406Sopenharmony_ci
634141cc406Sopenharmony_ci
635141cc406Sopenharmony_ci/* VARARGS3 */
636141cc406Sopenharmony_ci#ifdef HAVE_STDARGS
637141cc406Sopenharmony_ci int plp_unsafe_snprintf (char *str,size_t count,const char *fmt,...)
638141cc406Sopenharmony_ci#else
639141cc406Sopenharmony_ci int plp_unsafe_snprintf (va_alist) va_dcl
640141cc406Sopenharmony_ci#endif
641141cc406Sopenharmony_ci{
642141cc406Sopenharmony_ci#ifndef HAVE_STDARGS
643141cc406Sopenharmony_ci    char *str;
644141cc406Sopenharmony_ci	size_t count;
645141cc406Sopenharmony_ci    char *fmt;
646141cc406Sopenharmony_ci#endif
647141cc406Sopenharmony_ci	int n = 0;
648141cc406Sopenharmony_ci    VA_LOCAL_DECL
649141cc406Sopenharmony_ci
650141cc406Sopenharmony_ci    VA_START (fmt);
651141cc406Sopenharmony_ci    VA_SHIFT (str, char *);
652141cc406Sopenharmony_ci    VA_SHIFT (count, size_t );
653141cc406Sopenharmony_ci    VA_SHIFT (fmt, char *);
654141cc406Sopenharmony_ci    n = plp_unsafe_vsnprintf ( str, count, fmt, ap);
655141cc406Sopenharmony_ci    VA_END;
656141cc406Sopenharmony_ci	return( n );
657141cc406Sopenharmony_ci}
658141cc406Sopenharmony_ci static void dopr( int visible_control, char **buffer, int *left, const char *format, va_list args )
659141cc406Sopenharmony_ci{
660141cc406Sopenharmony_ci	int ch;
661141cc406Sopenharmony_ci	union value value;
662141cc406Sopenharmony_ci	int longflag = 0;
663141cc406Sopenharmony_ci	int quadflag = 0;
664141cc406Sopenharmony_ci	char *strvalue;
665141cc406Sopenharmony_ci	int ljust;
666141cc406Sopenharmony_ci	int len;
667141cc406Sopenharmony_ci	int zpad;
668141cc406Sopenharmony_ci	int precision;
669141cc406Sopenharmony_ci	int set_precision;
670141cc406Sopenharmony_ci	double dval;
671141cc406Sopenharmony_ci	int err = errno;
672141cc406Sopenharmony_ci	int base = 0;
673141cc406Sopenharmony_ci	int signed_val = 0;
674141cc406Sopenharmony_ci
675141cc406Sopenharmony_ci	while( (ch = *format++) ){
676141cc406Sopenharmony_ci		switch( ch ){
677141cc406Sopenharmony_ci		case '%':
678141cc406Sopenharmony_ci			longflag = quadflag =
679141cc406Sopenharmony_ci			ljust = len = zpad = base = signed_val = 0;
680141cc406Sopenharmony_ci			precision = -1; set_precision = 0;
681141cc406Sopenharmony_ci		nextch:
682141cc406Sopenharmony_ci			ch = *format++;
683141cc406Sopenharmony_ci			switch( ch ){
684141cc406Sopenharmony_ci			case 0:
685141cc406Sopenharmony_ci				dostr( buffer, left, "**end of format**" );
686141cc406Sopenharmony_ci				return;
687141cc406Sopenharmony_ci			case '-': ljust = 1; goto nextch;
688141cc406Sopenharmony_ci			case '.': set_precision = 1; precision = 0; goto nextch;
689141cc406Sopenharmony_ci			case '*':
690141cc406Sopenharmony_ci				if( set_precision ){
691141cc406Sopenharmony_ci					precision = va_arg( args, int );
692141cc406Sopenharmony_ci				} else {
693141cc406Sopenharmony_ci					len = va_arg( args, int );
694141cc406Sopenharmony_ci				}
695141cc406Sopenharmony_ci				goto nextch;
696141cc406Sopenharmony_ci			case '0': /* set zero padding if len not set */
697141cc406Sopenharmony_ci				if(len==0 && set_precision == 0 ) zpad = '0';
698141cc406Sopenharmony_ci			case '1': case '2': case '3':
699141cc406Sopenharmony_ci			case '4': case '5': case '6':
700141cc406Sopenharmony_ci			case '7': case '8': case '9':
701141cc406Sopenharmony_ci				if( set_precision ){
702141cc406Sopenharmony_ci					precision = precision*10 + ch - '0';
703141cc406Sopenharmony_ci				} else {
704141cc406Sopenharmony_ci					len = len*10 + ch - '0';
705141cc406Sopenharmony_ci				}
706141cc406Sopenharmony_ci				goto nextch;
707141cc406Sopenharmony_ci			case 'l': ++longflag; goto nextch;
708141cc406Sopenharmony_ci			case 'q':
709141cc406Sopenharmony_ci#if !defined( HAVE_QUAD_T )
710141cc406Sopenharmony_ci					dostr( buffer, left, "*no quad_t support *");
711141cc406Sopenharmony_ci					return;
712141cc406Sopenharmony_ci#endif
713141cc406Sopenharmony_ci					quadflag = 1;
714141cc406Sopenharmony_ci					goto nextch;
715141cc406Sopenharmony_ci			case 'u': case 'U':
716141cc406Sopenharmony_ci				if( base == 0 ){ base = 10; signed_val = 0; }
717141cc406Sopenharmony_ci			case 'o': case 'O':
718141cc406Sopenharmony_ci				if( base == 0 ){ base = 8; signed_val = 0; }
719141cc406Sopenharmony_ci			case 'd': case 'D':
720141cc406Sopenharmony_ci				if( base == 0 ){ base = 10; signed_val = 1; }
721141cc406Sopenharmony_ci			case 'x':
722141cc406Sopenharmony_ci				if( base == 0 ){ base = 16; signed_val = 0; }
723141cc406Sopenharmony_ci			case 'X':
724141cc406Sopenharmony_ci				if( base == 0 ){ base = -16; signed_val = 0; }
725141cc406Sopenharmony_ci#if defined( HAVE_QUAD_T )
726141cc406Sopenharmony_ci				if( quadflag ){
727141cc406Sopenharmony_ci					value.qvalue = va_arg( args, quad_t );
728141cc406Sopenharmony_ci					fmtquad( buffer, left,  &value,base,signed_val, ljust, len, zpad, precision );
729141cc406Sopenharmony_ci					break;
730141cc406Sopenharmony_ci				} else
731141cc406Sopenharmony_ci#endif
732141cc406Sopenharmony_ci				if( longflag > 1 ){
733141cc406Sopenharmony_ci#if defined(HAVE_LONG_LONG)
734141cc406Sopenharmony_ci					if( signed_val ){
735141cc406Sopenharmony_ci					value.value = va_arg( args, long long );
736141cc406Sopenharmony_ci					} else {
737141cc406Sopenharmony_ci					value.value = va_arg( args, unsigned long long );
738141cc406Sopenharmony_ci					}
739141cc406Sopenharmony_ci#else
740141cc406Sopenharmony_ci					if( signed_val ){
741141cc406Sopenharmony_ci					value.value = va_arg( args, long );
742141cc406Sopenharmony_ci					} else {
743141cc406Sopenharmony_ci					value.value = va_arg( args, unsigned long );
744141cc406Sopenharmony_ci					}
745141cc406Sopenharmony_ci#endif
746141cc406Sopenharmony_ci				} else if( longflag ){
747141cc406Sopenharmony_ci					if( signed_val ){
748141cc406Sopenharmony_ci						value.value = va_arg( args, long );
749141cc406Sopenharmony_ci					} else {
750141cc406Sopenharmony_ci						value.value = va_arg( args, unsigned long );
751141cc406Sopenharmony_ci					}
752141cc406Sopenharmony_ci				} else {
753141cc406Sopenharmony_ci					if( signed_val ){
754141cc406Sopenharmony_ci						value.value = va_arg( args, int );
755141cc406Sopenharmony_ci					} else {
756141cc406Sopenharmony_ci						value.value = va_arg( args, unsigned int );
757141cc406Sopenharmony_ci					}
758141cc406Sopenharmony_ci				}
759141cc406Sopenharmony_ci				fmtnum( buffer, left,  &value,base,signed_val, ljust, len, zpad, precision ); break;
760141cc406Sopenharmony_ci			case 's':
761141cc406Sopenharmony_ci				strvalue = va_arg( args, char *);
762141cc406Sopenharmony_ci				fmtstr( visible_control, buffer, left, strvalue,ljust,len, zpad, precision );
763141cc406Sopenharmony_ci				break;
764141cc406Sopenharmony_ci			case 'c':
765141cc406Sopenharmony_ci				ch = va_arg( args, int );
766141cc406Sopenharmony_ci				{ char b[2];
767141cc406Sopenharmony_ci					b[0] = ch;
768141cc406Sopenharmony_ci					b[1] = 0;
769141cc406Sopenharmony_ci					fmtstr( 0, buffer, left, b,ljust,len, zpad, precision );
770141cc406Sopenharmony_ci				}
771141cc406Sopenharmony_ci				break;
772141cc406Sopenharmony_ci			case 'f': case 'g': case 'e':
773141cc406Sopenharmony_ci				dval = va_arg( args, double );
774141cc406Sopenharmony_ci				fmtdouble( buffer, left, ch, dval,ljust,len, zpad, precision ); break;
775141cc406Sopenharmony_ci			case 'm':
776141cc406Sopenharmony_ci				{ char shortbuffer[32];
777141cc406Sopenharmony_ci				fmtstr( visible_control, buffer, left,
778141cc406Sopenharmony_ci					plp_Errormsg(err, shortbuffer),ljust,len, zpad, precision );
779141cc406Sopenharmony_ci				}
780141cc406Sopenharmony_ci				break;
781141cc406Sopenharmony_ci			case '%': dopr_outch( buffer, left, ch ); continue;
782141cc406Sopenharmony_ci			default:
783141cc406Sopenharmony_ci				dostr(  buffer, left, "???????" );
784141cc406Sopenharmony_ci			}
785141cc406Sopenharmony_ci			longflag = 0;
786141cc406Sopenharmony_ci			break;
787141cc406Sopenharmony_ci		default:
788141cc406Sopenharmony_ci			dopr_outch( buffer, left, ch );
789141cc406Sopenharmony_ci			break;
790141cc406Sopenharmony_ci		}
791141cc406Sopenharmony_ci	}
792141cc406Sopenharmony_ci}
793141cc406Sopenharmony_ci
794141cc406Sopenharmony_ci/*
795141cc406Sopenharmony_ci * Format '%[-]len[.precision]s'
796141cc406Sopenharmony_ci * -   = left justify (ljust)
797141cc406Sopenharmony_ci * len = minimum length
798141cc406Sopenharmony_ci * precision = numbers of chars in string to use
799141cc406Sopenharmony_ci */
800141cc406Sopenharmony_ci static void
801141cc406Sopenharmony_ci fmtstr( int visible_control, char **buffer, int *left,
802141cc406Sopenharmony_ci	 char *value, int ljust, int len, int zpad, int precision )
803141cc406Sopenharmony_ci{
804141cc406Sopenharmony_ci	int padlen, strlenv, i, c;	/* amount to pad */
805141cc406Sopenharmony_ci
806141cc406Sopenharmony_ci	if( value == 0 ){
807141cc406Sopenharmony_ci		value = "<NULL>";
808141cc406Sopenharmony_ci	}
809141cc406Sopenharmony_ci	/* cheap strlen so you do not have library call */
810141cc406Sopenharmony_ci	for( strlenv = i = 0; (c=CVAL(value+i)); ++i ){
811141cc406Sopenharmony_ci		if( visible_control && iscntrl( c ) && c != '\t' && c != '\n' ){
812141cc406Sopenharmony_ci			++strlenv;
813141cc406Sopenharmony_ci		}
814141cc406Sopenharmony_ci		++strlenv;
815141cc406Sopenharmony_ci	}
816141cc406Sopenharmony_ci	if( precision > 0 && strlenv > precision ){
817141cc406Sopenharmony_ci		strlenv = precision;
818141cc406Sopenharmony_ci	}
819141cc406Sopenharmony_ci	padlen = len - strlenv;
820141cc406Sopenharmony_ci	if( padlen < 0 ) padlen = 0;
821141cc406Sopenharmony_ci	if( ljust ) padlen = -padlen;
822141cc406Sopenharmony_ci	while( padlen > 0 ) {
823141cc406Sopenharmony_ci		dopr_outch( buffer, left, ' ' );
824141cc406Sopenharmony_ci		--padlen;
825141cc406Sopenharmony_ci	}
826141cc406Sopenharmony_ci	/* output characters */
827141cc406Sopenharmony_ci	for( i = 0; i < strlenv && (c = CVAL(value+i)); ++i ){
828141cc406Sopenharmony_ci		if( visible_control && iscntrl( c ) && c != '\t' && c != '\n' ){
829141cc406Sopenharmony_ci			dopr_outch(buffer, left, '^');
830141cc406Sopenharmony_ci			c = ('@' | (c & 0x1F));
831141cc406Sopenharmony_ci		}
832141cc406Sopenharmony_ci		dopr_outch(buffer, left, c);
833141cc406Sopenharmony_ci	}
834141cc406Sopenharmony_ci	while( padlen < 0 ) {
835141cc406Sopenharmony_ci		dopr_outch( buffer, left, ' ' );
836141cc406Sopenharmony_ci		++padlen;
837141cc406Sopenharmony_ci	}
838141cc406Sopenharmony_ci}
839141cc406Sopenharmony_ci
840141cc406Sopenharmony_ci static void
841141cc406Sopenharmony_ci fmtnum( char **buffer, int *left,
842141cc406Sopenharmony_ci	union value *value, int base, int dosign, int ljust,
843141cc406Sopenharmony_ci	int len, int zpad, int precision )
844141cc406Sopenharmony_ci{
845141cc406Sopenharmony_ci	int signvalue = 0;
846141cc406Sopenharmony_ci#if defined(HAVE_LONG_LONG)
847141cc406Sopenharmony_ci	unsigned long long uvalue;
848141cc406Sopenharmony_ci#else
849141cc406Sopenharmony_ci	unsigned long uvalue;
850141cc406Sopenharmony_ci#endif
851141cc406Sopenharmony_ci	char convert[sizeof( union value) * 8 + 16];
852141cc406Sopenharmony_ci	int place = 0;
853141cc406Sopenharmony_ci	int padlen = 0;	/* amount to pad */
854141cc406Sopenharmony_ci	int caps = 0;
855141cc406Sopenharmony_ci
856141cc406Sopenharmony_ci	/* fprintf(stderr,"value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n",
857141cc406Sopenharmony_ci		value, base, dosign, ljust, len, zpad );/ **/
858141cc406Sopenharmony_ci	uvalue = value->value;
859141cc406Sopenharmony_ci	if( dosign ){
860141cc406Sopenharmony_ci		if( value->value < 0 ) {
861141cc406Sopenharmony_ci			signvalue = '-';
862141cc406Sopenharmony_ci			uvalue = -value->value;
863141cc406Sopenharmony_ci		}
864141cc406Sopenharmony_ci	}
865141cc406Sopenharmony_ci	if( base < 0 ){
866141cc406Sopenharmony_ci		caps = 1;
867141cc406Sopenharmony_ci		base = -base;
868141cc406Sopenharmony_ci	}
869141cc406Sopenharmony_ci	do{
870141cc406Sopenharmony_ci		convert[place++] =
871141cc406Sopenharmony_ci			(caps? "0123456789ABCDEF":"0123456789abcdef")
872141cc406Sopenharmony_ci			 [uvalue % (unsigned)base  ];
873141cc406Sopenharmony_ci		uvalue = (uvalue / (unsigned)base );
874141cc406Sopenharmony_ci	}while(uvalue);
875141cc406Sopenharmony_ci	convert[place] = 0;
876141cc406Sopenharmony_ci	padlen = len - place;
877141cc406Sopenharmony_ci	if( padlen < 0 ) padlen = 0;
878141cc406Sopenharmony_ci	if( ljust ) padlen = -padlen;
879141cc406Sopenharmony_ci	/* fprintf( stderr, "str '%s', place %d, sign %c, padlen %d\n",
880141cc406Sopenharmony_ci		convert,place,signvalue,padlen); / **/
881141cc406Sopenharmony_ci	if( zpad && padlen > 0 ){
882141cc406Sopenharmony_ci		if( signvalue ){
883141cc406Sopenharmony_ci			dopr_outch( buffer, left, signvalue );
884141cc406Sopenharmony_ci			--padlen;
885141cc406Sopenharmony_ci			signvalue = 0;
886141cc406Sopenharmony_ci		}
887141cc406Sopenharmony_ci		while( padlen > 0 ){
888141cc406Sopenharmony_ci			dopr_outch( buffer, left, zpad );
889141cc406Sopenharmony_ci			--padlen;
890141cc406Sopenharmony_ci		}
891141cc406Sopenharmony_ci	}
892141cc406Sopenharmony_ci	while( padlen > 0 ) {
893141cc406Sopenharmony_ci		dopr_outch( buffer, left, ' ' );
894141cc406Sopenharmony_ci		--padlen;
895141cc406Sopenharmony_ci	}
896141cc406Sopenharmony_ci	if( signvalue ) dopr_outch( buffer, left, signvalue );
897141cc406Sopenharmony_ci	while( place > 0 ) dopr_outch( buffer, left, convert[--place] );
898141cc406Sopenharmony_ci	while( padlen < 0 ){
899141cc406Sopenharmony_ci		dopr_outch( buffer, left, ' ' );
900141cc406Sopenharmony_ci		++padlen;
901141cc406Sopenharmony_ci	}
902141cc406Sopenharmony_ci}
903141cc406Sopenharmony_ci
904141cc406Sopenharmony_ci#if defined(HAVE_QUAD_T)
905141cc406Sopenharmony_ci
906141cc406Sopenharmony_ci static void
907141cc406Sopenharmony_ci fmtquad( char **buffer, int *left,
908141cc406Sopenharmony_ci	union value *value, int base, int dosign, int ljust,
909141cc406Sopenharmony_ci	int len, int zpad, int precision )
910141cc406Sopenharmony_ci{
911141cc406Sopenharmony_ci	int signvalue = 0;
912141cc406Sopenharmony_ci	int place = 0;
913141cc406Sopenharmony_ci	int padlen = 0;	/* amount to pad */
914141cc406Sopenharmony_ci	int caps = 0;
915141cc406Sopenharmony_ci	int i, c;
916141cc406Sopenharmony_ci	union {
917141cc406Sopenharmony_ci		quad_t qvalue;
918141cc406Sopenharmony_ci		unsigned char qconvert[sizeof(quad_t)];
919141cc406Sopenharmony_ci	} vvalue;
920141cc406Sopenharmony_ci	char convert[2*sizeof(quad_t)+1];
921141cc406Sopenharmony_ci
922141cc406Sopenharmony_ci	/* fprintf(stderr,"value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n",
923141cc406Sopenharmony_ci		value, base, dosign, ljust, len, zpad );/ **/
924141cc406Sopenharmony_ci	vvalue.qvalue = value->qvalue;
925141cc406Sopenharmony_ci
926141cc406Sopenharmony_ci	if( base < 0 ){
927141cc406Sopenharmony_ci		caps = 1;
928141cc406Sopenharmony_ci	}
929141cc406Sopenharmony_ci
930141cc406Sopenharmony_ci	for( i = 0; i < (int)sizeof(quad_t); ++i ){
931141cc406Sopenharmony_ci		c = vvalue.qconvert[i];
932141cc406Sopenharmony_ci		convert[2*i] =
933141cc406Sopenharmony_ci			(caps? "0123456789ABCDEF":"0123456789abcdef")[ (c >> 4) & 0xF];
934141cc406Sopenharmony_ci		convert[2*i+1] =
935141cc406Sopenharmony_ci			(caps? "0123456789ABCDEF":"0123456789abcdef")[ c  & 0xF];
936141cc406Sopenharmony_ci	}
937141cc406Sopenharmony_ci	convert[2*i] = 0;
938141cc406Sopenharmony_ci
939141cc406Sopenharmony_ci	place = strlen(convert);
940141cc406Sopenharmony_ci	padlen = len - place;
941141cc406Sopenharmony_ci	if( padlen < 0 ) padlen = 0;
942141cc406Sopenharmony_ci	if( ljust ) padlen = -padlen;
943141cc406Sopenharmony_ci	/* fprintf( stderr, "str '%s', place %d, sign %c, padlen %d\n",
944141cc406Sopenharmony_ci		convert,place,signvalue,padlen); / **/
945141cc406Sopenharmony_ci	if( zpad && padlen > 0 ){
946141cc406Sopenharmony_ci		if( signvalue ){
947141cc406Sopenharmony_ci			dopr_outch( buffer, left, signvalue );
948141cc406Sopenharmony_ci			--padlen;
949141cc406Sopenharmony_ci			signvalue = 0;
950141cc406Sopenharmony_ci		}
951141cc406Sopenharmony_ci		while( padlen > 0 ){
952141cc406Sopenharmony_ci			dopr_outch( buffer, left, zpad );
953141cc406Sopenharmony_ci			--padlen;
954141cc406Sopenharmony_ci		}
955141cc406Sopenharmony_ci	}
956141cc406Sopenharmony_ci	while( padlen > 0 ) {
957141cc406Sopenharmony_ci		dopr_outch( buffer, left, ' ' );
958141cc406Sopenharmony_ci		--padlen;
959141cc406Sopenharmony_ci	}
960141cc406Sopenharmony_ci	if( signvalue ) dopr_outch( buffer, left, signvalue );
961141cc406Sopenharmony_ci	while( place > 0 ) dopr_outch( buffer, left, convert[--place] );
962141cc406Sopenharmony_ci	while( padlen < 0 ){
963141cc406Sopenharmony_ci		dopr_outch( buffer, left, ' ' );
964141cc406Sopenharmony_ci		++padlen;
965141cc406Sopenharmony_ci	}
966141cc406Sopenharmony_ci}
967141cc406Sopenharmony_ci
968141cc406Sopenharmony_ci#endif
969141cc406Sopenharmony_ci
970141cc406Sopenharmony_ci static void mystrcat(char *dest, char *src )
971141cc406Sopenharmony_ci{
972141cc406Sopenharmony_ci	if( dest && src ){
973141cc406Sopenharmony_ci		dest += safestrlen(dest);
974141cc406Sopenharmony_ci		strcpy(dest,src);
975141cc406Sopenharmony_ci	}
976141cc406Sopenharmony_ci}
977141cc406Sopenharmony_ci
978141cc406Sopenharmony_ci static void
979141cc406Sopenharmony_ci fmtdouble( char **buffer, int *left,
980141cc406Sopenharmony_ci	int fmt, double value, int ljust, int len, int zpad, int precision )
981141cc406Sopenharmony_ci{
982141cc406Sopenharmony_ci	char convert[sizeof( union value) * 8 + 512];
983141cc406Sopenharmony_ci	char formatstr[128];
984141cc406Sopenharmony_ci
985141cc406Sopenharmony_ci	/* fprintf(stderr,"len %d, precision %d\n", len, precision ); */
986141cc406Sopenharmony_ci	if( len > 255 ){
987141cc406Sopenharmony_ci		len = 255;
988141cc406Sopenharmony_ci	}
989141cc406Sopenharmony_ci	if( precision > 255 ){
990141cc406Sopenharmony_ci		precision = 255;
991141cc406Sopenharmony_ci	}
992141cc406Sopenharmony_ci	if( precision >= 0 && len > 0 && precision > len ) precision = len;
993141cc406Sopenharmony_ci	strcpy( formatstr, "%" );		/* 1 */
994141cc406Sopenharmony_ci	if( ljust ) mystrcat(formatstr, "-" ); /* 1 */
995141cc406Sopenharmony_ci	if( zpad ) mystrcat(formatstr, "0" );	/* 1 */
996141cc406Sopenharmony_ci	if( len >= 0 ){
997141cc406Sopenharmony_ci		sprintf( formatstr+strlen(formatstr), "%d", len ); /* 3 */
998141cc406Sopenharmony_ci	}
999141cc406Sopenharmony_ci	if( precision >= 0 ){
1000141cc406Sopenharmony_ci		sprintf( formatstr+strlen(formatstr), ".%d", precision ); /* 3 */
1001141cc406Sopenharmony_ci	}
1002141cc406Sopenharmony_ci	/* format string will be at most 10 chars long ... */
1003141cc406Sopenharmony_ci	sprintf( formatstr+strlen(formatstr), "%c", fmt );
1004141cc406Sopenharmony_ci	/* this is easier than trying to do the portable dtostr */
1005141cc406Sopenharmony_ci	/* fprintf(stderr,"format string '%s'\n", formatstr); */
1006141cc406Sopenharmony_ci	sprintf( convert, formatstr, value );
1007141cc406Sopenharmony_ci	dostr( buffer, left, convert );
1008141cc406Sopenharmony_ci}
1009141cc406Sopenharmony_ci
1010141cc406Sopenharmony_ci static void dostr( char **buffer, int *left, char *str  )
1011141cc406Sopenharmony_ci{
1012141cc406Sopenharmony_ci	if(str)while(*str) dopr_outch( buffer, left, *str++ );
1013141cc406Sopenharmony_ci}
1014141cc406Sopenharmony_ci
1015141cc406Sopenharmony_ci static void dopr_outch( char **buffer, int *left, int c )
1016141cc406Sopenharmony_ci{
1017141cc406Sopenharmony_ci	if( *left > 0 ){
1018141cc406Sopenharmony_ci		*(*buffer)++ = c;
1019141cc406Sopenharmony_ci	}
1020141cc406Sopenharmony_ci	*left -= 1;
1021141cc406Sopenharmony_ci}
1022141cc406Sopenharmony_ci
1023141cc406Sopenharmony_ci
1024141cc406Sopenharmony_ci/****************************************************************************
1025141cc406Sopenharmony_ci * static char *plp_errormsg( int err )
1026141cc406Sopenharmony_ci *  returns a printable form of the
1027141cc406Sopenharmony_ci *  errormessage corresponding to the valie of err.
1028141cc406Sopenharmony_ci *  This is the poor man's version of sperror(), not available on all systems
1029141cc406Sopenharmony_ci *  Patrick Powell Tue Apr 11 08:05:05 PDT 1995
1030141cc406Sopenharmony_ci ****************************************************************************/
1031141cc406Sopenharmony_ci/****************************************************************************/
1032141cc406Sopenharmony_ci
1033141cc406Sopenharmony_ci#if !defined(HAVE_STRERROR)
1034141cc406Sopenharmony_ci# undef  num_errors
1035141cc406Sopenharmony_ci# if defined(HAVE_SYS_ERRLIST)
1036141cc406Sopenharmony_ci#  if !defined(HAVE_DECL_SYS_ERRLIST)
1037141cc406Sopenharmony_ci     extern const char *const sys_errlist[];
1038141cc406Sopenharmony_ci#  endif
1039141cc406Sopenharmony_ci#  if defined(HAVE_SYS_NERR)
1040141cc406Sopenharmony_ci#   if !defined(HAVE_DECL_SYS_NERR)
1041141cc406Sopenharmony_ci      extern int sys_nerr;
1042141cc406Sopenharmony_ci#   endif
1043141cc406Sopenharmony_ci#   define num_errors    (sys_nerr)
1044141cc406Sopenharmony_ci#  endif
1045141cc406Sopenharmony_ci# endif
1046141cc406Sopenharmony_ci# if !defined(num_errors)
1047141cc406Sopenharmony_ci#   define num_errors   (-1)            /* always use "errno=%d" */
1048141cc406Sopenharmony_ci# endif
1049141cc406Sopenharmony_ci#endif
1050141cc406Sopenharmony_ci
1051141cc406Sopenharmony_ci static char * plp_Errormsg ( int err, char *buffer /* int maxlen = 32 */)
1052141cc406Sopenharmony_ci{
1053141cc406Sopenharmony_ci    char *cp;
1054141cc406Sopenharmony_ci
1055141cc406Sopenharmony_ci#if defined(HAVE_STRERROR)
1056141cc406Sopenharmony_ci	cp = (void *)strerror(err);
1057141cc406Sopenharmony_ci#else
1058141cc406Sopenharmony_ci# if defined(HAVE_SYS_ERRLIST)
1059141cc406Sopenharmony_ci    if (err >= 0 && err < num_errors) {
1060141cc406Sopenharmony_ci		cp = (void *)sys_errlist[err];
1061141cc406Sopenharmony_ci    } else
1062141cc406Sopenharmony_ci# endif
1063141cc406Sopenharmony_ci	{
1064141cc406Sopenharmony_ci		(void) sprintf (buffer, "errno=%d", err);
1065141cc406Sopenharmony_ci		cp = buffer;
1066141cc406Sopenharmony_ci    }
1067141cc406Sopenharmony_ci#endif
1068141cc406Sopenharmony_ci    return (cp);
1069141cc406Sopenharmony_ci}
1070141cc406Sopenharmony_ci
1071141cc406Sopenharmony_ci#if defined(TEST)
1072141cc406Sopenharmony_ci#include <stdio.h>
1073141cc406Sopenharmony_ci int main( void )
1074141cc406Sopenharmony_ci{
1075141cc406Sopenharmony_ci	char buffer[128];
1076141cc406Sopenharmony_ci	char *t;
1077141cc406Sopenharmony_ci	char *test1 = "01234";
1078141cc406Sopenharmony_ci	int n;
1079141cc406Sopenharmony_ci	errno = 1;
1080141cc406Sopenharmony_ci	buffer[0] = 0;
1081141cc406Sopenharmony_ci	n = snprintf( buffer, 0, (t="test")); printf( "[%d] %s = '%s'\n", n, t, buffer );
1082141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t="errno '%m'")); printf( "[%d] %s = '%s'\n", n, t, buffer );
1083141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1084141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%12s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1085141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%-12s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1086141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%12.2s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1087141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%-12.2s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1088141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1089141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%g"), 1.2345 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1090141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%12g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1091141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%12.1g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1092141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%12.2g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1093141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%12.3g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1094141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%0*d"), 6, 1 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1095141cc406Sopenharmony_ci#if defined(HAVE_LONG_LONG)
1096141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%llx"), 1, 2, 3, 4 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1097141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%llx"), (long long)1, (long long)2 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1098141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%qx"), 1, 2, 3, 4 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1099141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%qx"), (quad_t)1, (quad_t)2 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1100141cc406Sopenharmony_ci#endif
1101141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "0%x, 0%x"), (char *)(0x01234567), (char *)0, 0, 0, 0); printf( "[%d] %s = '%s'\n", n, t, buffer );
1102141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "0%x, 0%x"), (char *)(0x01234567), (char *)0x89ABCDEF, 0, 0, 0); printf( "[%d] %s = '%s'\n", n, t, buffer );
1103141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "0%x, 0%x"), t, 0, 0, 0, 0); printf( "[%d] %s = '%s'\n", n, t, buffer );
1104141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%f"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1105141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%f"), 1.2345 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1106141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%12f"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1107141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%12.2f"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1108141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1109141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%.0f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1110141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%0.0f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1111141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%1.0f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1112141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%1.5f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1113141cc406Sopenharmony_ci	n = snprintf( buffer, sizeof(buffer), (t = "%5.5f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
1114141cc406Sopenharmony_ci	return(0);
1115141cc406Sopenharmony_ci}
1116141cc406Sopenharmony_ci#endif
1117141cc406Sopenharmony_ci
1118141cc406Sopenharmony_ci
1119141cc406Sopenharmony_ci#endif /* HAVE_SNPRINTF */
1120