~ubuntu-branches/ubuntu/precise/netatalk/precise

« back to all changes in this revision

Viewing changes to libatalk/compat/snprintf.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Rittau
  • Date: 2004-01-19 12:43:49 UTC
  • Revision ID: james.westby@ubuntu.com-20040119124349-es563jbp0hk0ae51
Tags: upstream-1.6.4
ImportĀ upstreamĀ versionĀ 1.6.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**************************************************************************
 
2
 * Copyright 1994-2000 Patrick Powell, San Diego, CA <papowell@astart.com>
 
3
 * 
 
4
 * Modified for Netatalk 2002/02/12 Burkhard Schmidt <bs@cpfs.mpg.de>
 
5
 **************************************************************************/
 
6
 
 
7
/*
 
8
   Overview:
 
9
 
 
10
   plp_snprintf( char *buffer, int len, const char *format,...)
 
11
   plp_unsafe_snprintf( char *buffer, int len, const char *format,...)
 
12
     its horribly unsafe companion that does NOT protect you from
 
13
     the printing of evil control characters,  but may be necessary
 
14
     See the man page documentation below
 
15
   
 
16
   This version of snprintf was developed originally for printing
 
17
   on a motley collection of specialized hardware that had NO IO
 
18
   library.  Due to contractual restrictions,  a clean room implementation
 
19
   of the printf() code had to be developed.
 
20
   
 
21
   The method chosen for printf was to be as paranoid as possible,
 
22
   as these platforms had NO memory protection,  and very small
 
23
   address spaces.  This made it possible to try to print
 
24
   very long strings, i.e. - all of memory, very easily.  To guard
 
25
   against this,  all printing was done via a buffer, generous enough
 
26
   to hold strings,  but small enough to protect against overruns,
 
27
   etc.
 
28
   
 
29
   Strangely enough,  this proved to be of immense importance when
 
30
   SPRINTFing to a buffer on a stack...  The rest,  of course,  is
 
31
   well known,  as buffer overruns in the stack are a common way to
 
32
   do horrible things to operating systems, security, etc etc.
 
33
   
 
34
   This version of snprintf is VERY limited by modern standards.
 
35
 
 
36
   Revision History:
 
37
   First Released Version - 1994.  This version had NO comments.
 
38
   First Released Version - 1994.  This version had NO comments.
 
39
   Second Major Released Version - Tue May 23 10:43:44 PDT 2000
 
40
    Configuration and other items changed.  Read this doc.
 
41
    Treat this as a new version.
 
42
   
 
43
   COPYRIGHT AND TERMS OF USE:
 
44
   
 
45
   You may use, copy, distribute, or otherwise incorporate this software
 
46
   and documentation into any product or other item,  provided that
 
47
   the copyright in the documentation and source code as well as the
 
48
   source code generated constant strings in the object, executable
 
49
   or other code remain in place and are present in executable modules
 
50
   or objects.
 
51
   
 
52
   You may modify this code as appropriate to your usage; however the
 
53
   modified version must be identified by changing the various source
 
54
   and object code identification strings as is appropriately noted
 
55
   in the source code.
 
56
   
 
57
   The next include line is expected to work in conjunction with the
 
58
   GNU CONFIGURE utility.  You  should define the following macros
 
59
   appropriately:
 
60
   
 
61
   HAVE_STDARG_H - if the <stdargs.h> include file is available
 
62
   HAVE_VARARG_H - if the <varargs.h> include file is available
 
63
   
 
64
   HAVE_STRERROR - if the strerror() routine is available.
 
65
     If it is not available, then examine the lines containing
 
66
     the tests below.  You may need to fiddle with HAVE_SYS_NERR
 
67
   HAVE_SYS_ERRLIST
 
68
   HAVE_DECL_SYS_ERRLIST
 
69
   HAVE_SYS_NERR
 
70
   HAVE_DECL_SYS_NERR
 
71
   
 
72
   HAVE_QUAD_T      - if the quad_t type is defined
 
73
   HAVE_LONG_LONG   - if the long long type is defined
 
74
   HAVE_LONG_DOUBLE - if the long double type is defined
 
75
   
 
76
     If you are using the GNU configure (autoconf) facility, add the
 
77
     following line to the configure.in file, to force checking for the
 
78
     quad_t and long long  data types:
 
79
 
 
80
 
 
81
        AC_CHECK_FUNCS(strerror);
 
82
        AC_CACHE_CHECK(for errno,
 
83
        ac_cv_errno,
 
84
        [
 
85
        AC_TRY_LINK(,[extern int errno; return (errno);],
 
86
                ac_cv_errno=yes, ac_cv_errno=no)
 
87
        ])
 
88
        if test "$ac_cv_errno" = yes; then
 
89
                AC_DEFINE(HAVE_ERRNO)
 
90
                AC_CACHE_CHECK(for errno declaration,
 
91
                ac_cv_decl_errno,
 
92
                [
 
93
                AC_TRY_COMPILE([
 
94
                #include <stdio.h>
 
95
                #ifdef HAVE_STDLIB_H
 
96
                #include <stdlib.h>
 
97
                #endif
 
98
                #ifdef HAVE_UNISTD_H
 
99
                #include <unistd.h>
 
100
                #endif
 
101
                #ifdef HAVE_ERRNO_H
 
102
                #include <errno.h>
 
103
                ],[return(sys_nerr);],
 
104
                        ac_cv_decl_errno=yes, ac_cv_decl_errno=no)
 
105
                ])
 
106
                if test "$ac_cv_decl_errno" = yes; then
 
107
                        AC_DEFINE(HAVE_DECL_ERRNO)
 
108
                fi;
 
109
        fi
 
110
 
 
111
        AC_CACHE_CHECK(for sys_nerr,
 
112
        ac_cv_sys_nerr,
 
113
        [
 
114
        AC_TRY_LINK(,[extern int sys_nerr; return (sys_nerr);],
 
115
                ac_cv_sys_nerr=yes, ac_cv_sys_nerr=no)
 
116
        ])
 
117
        if test "$ac_cv_sys_nerr" = yes; then
 
118
                AC_DEFINE(HAVE_SYS_NERR)
 
119
                AC_CACHE_CHECK(for sys_nerr declaration,
 
120
                ac_cv_decl_sys_nerr,
 
121
                [
 
122
                AC_TRY_COMPILE([
 
123
                #include <stdio.h>
 
124
                #ifdef HAVE_STDLIB_H
 
125
                #include <stdlib.h>
 
126
                #endif
 
127
                #ifdef HAVE_UNISTD_H
 
128
                #include <unistd.h>
 
129
                #endif],[return(sys_nerr);],
 
130
                ac_cv_decl_sys_nerr_def=yes, ac_cv_decl_sys_nerr_def=no)
 
131
                ])
 
132
                if test "$ac_cv_decl_sys_nerr" = yes; then
 
133
                        AC_DEFINE(HAVE_DECL_SYS_NERR)
 
134
                fi
 
135
        fi
 
136
 
 
137
 
 
138
        AC_CACHE_CHECK(for sys_errlist array,
 
139
        ac_cv_sys_errlist,
 
140
        [AC_TRY_LINK(,[extern char *sys_errlist[];
 
141
                sys_errlist[0];],
 
142
                ac_cv_sys_errlist=yes, ac_cv_sys_errlist=no)
 
143
        ])
 
144
        if test "$ac_cv_sys_errlist" = yes; then
 
145
                AC_DEFINE(HAVE_SYS_ERRLIST)
 
146
                AC_CACHE_CHECK(for sys_errlist declaration,
 
147
                ac_cv_sys_errlist_def,
 
148
                [AC_TRY_COMPILE([
 
149
                #include <stdio.h>
 
150
                #include <errno.h>
 
151
                #ifdef HAVE_STDLIB_H
 
152
                #include <stdlib.h>
 
153
                #endif
 
154
                #ifdef HAVE_UNISTD_H
 
155
                #include <unistd.h>
 
156
                #endif],[char *s = sys_errlist[0]; return(*s);],
 
157
                ac_cv_decl_sys_errlist=yes, ac_cv_decl_sys_errlist=no)
 
158
                ])
 
159
                if test "$ac_cv_decl_sys_errlist" = yes; then
 
160
                        AC_DEFINE(HAVE_DECL_SYS_ERRLIST)
 
161
                fi
 
162
        fi
 
163
 
 
164
 
 
165
 
 
166
        AC_CACHE_CHECK(checking for long long,
 
167
        ac_cv_long_long,
 
168
        [
 
169
        AC_TRY_COMPILE([
 
170
        #include <stdio.h>
 
171
        #include <sys/types.h>
 
172
        ], [printf("%d",sizeof(long long));],
 
173
        ac_cv_long_long=yes, ac_cv_long_long=no)
 
174
        ])
 
175
        if test $ac_cv_long_long = yes; then
 
176
          AC_DEFINE(HAVE_LONG_LONG)
 
177
        fi
 
178
 
 
179
        AC_CACHE_CHECK(checking for long double,
 
180
        ac_cv_long_double,
 
181
        [
 
182
        AC_TRY_COMPILE([
 
183
        #include <stdio.h>
 
184
        #include <sys/types.h>
 
185
        ], [printf("%d",sizeof(long double));],
 
186
        ac_cv_long_double=yes, ac_cv_long_double=no)
 
187
        ])
 
188
        if test $ac_cv_long_double = yes; then
 
189
          AC_DEFINE(HAVE_LONG_DOUBLE)
 
190
        fi
 
191
 
 
192
        AC_CACHE_CHECK(checking for quad_t,
 
193
        ac_cv_quad_t,
 
194
        [
 
195
        AC_TRY_COMPILE([
 
196
        #include <stdio.h>
 
197
        #include <sys/types.h>
 
198
        ], [printf("%d",sizeof(quad_t));],
 
199
        ac_cv_quad_t=yes, ac_cv_quad_t=no)
 
200
        ])
 
201
        if test $ac_cv_quad_t = yes; then
 
202
          AC_DEFINE(HAVE_QUAD_T)
 
203
        fi
 
204
 
 
205
 
 
206
 
 
207
NAME
 
208
     plp_snprintf, plp_vsnprintf - formatted output conversion
 
209
 
 
210
SYNOPSIS
 
211
     #include <stdio.h>
 
212
     #include <stdarg.h>
 
213
 
 
214
     int
 
215
     plp_snprintf(const char *format, size_t size, va_list ap);
 
216
     int
 
217
     plp_unsafe_snprintf(const char *format, size_t size, va_list ap);
 
218
 
 
219
     AKA snprintf and unsafe_snprintf in the documentation below
 
220
 
 
221
     int
 
222
     vsnprintf(char *str, size_t size, const char *format, va_list ap);
 
223
     int
 
224
     unsafe_vsnprintf(char *str, size_t size, const char *format, va_list ap);
 
225
 
 
226
     AKA vsnprintf and unsafe_vsnprintf in the documentation below
 
227
 
 
228
     (Multithreaded Safe)
 
229
 
 
230
DESCRIPTION
 
231
     The printf() family of functions produces output according to
 
232
     a format as described below.  Snprintf(), and vsnprintf()
 
233
     write to the character string str. These functions write the
 
234
     output under the control of a format string that specifies
 
235
     how subsequent arguments (or arguments accessed via the
 
236
     variable-length argument facilities of stdarg(3))  are converted
 
237
     for output.  These functions return the number of characters
 
238
     printed (not including the trailing `\0' used to end output
 
239
     to strings).  Snprintf() and vsnprintf() will write at most
 
240
     size-1 of the characters printed into the output string (the
 
241
     size'th character then gets the terminating `\0'); if the
 
242
     return value is greater than or equal to the size argument,
 
243
     the string was too short and some of the printed characters
 
244
     were discarded.  The size or str may be given as zero to find
 
245
     out how many characters are needed; in this case, the str
 
246
     argument is ignored.
 
247
 
 
248
     By default, the snprintf function will not format control
 
249
     characters (except new line and tab) in strings.  This is a
 
250
     safety feature that has proven to be extremely critical when
 
251
     using snprintf for secure applications and when debugging.
 
252
     If you MUST have control characters formatted or printed,
 
253
     then use the unsafe_snprintf() and unsafe_vsnprintf() and on
 
254
     your own head be the consequences.  You have been warned.
 
255
 
 
256
     There is one exception to the comments above, and that is
 
257
     the "%c" (character) format.  It brutally assumes that the
 
258
     user will have performed the necessary 'isprint()' or other
 
259
     checks and uses the integer value as a character.
 
260
 
 
261
     The format string is composed of zero or more directives:
 
262
     ordinary characters (not %), which are copied unchanged to
 
263
     the output stream; and conversion specifications, each
 
264
     of which results in fetching zero or more subsequent arguments.
 
265
     Each conversion specification is introduced by the character
 
266
     %. The arguments must correspond properly (after type promotion)
 
267
     with the conversion specifier.  After the %, the following
 
268
     appear in sequence:
 
269
 
 
270
     o   Zero or more of the following flags:
 
271
 
 
272
           -   A zero `0' character specifying zero padding.  For
 
273
             all conversions except n, the converted value is padded
 
274
             on the left with zeros rather than blanks.  If a
 
275
             precision is given with a numeric conversion (d, i,
 
276
             o, u, i, x, and X), the `0' flag is ignored.
 
277
 
 
278
       -   A negative field width flag `-' indicates the converted
 
279
             value is to be left adjusted on the field boundary.  Except
 
280
             for n conversions, the converted value is padded on
 
281
             the right with blanks, rather than on the left with
 
282
             blanks or zeros.  A `-' overrides a `0' if both are
 
283
             given.
 
284
 
 
285
           -   A space, specifying that a blank should be left before
 
286
             a positive number produced by a signed conversion (d, e, E, f,
 
287
             g, G, or i).
 
288
 
 
289
           -   A `+' character specifying that a sign always be placed
 
290
             before a number produced by a signed conversion.  A `+' overrides
 
291
             a space if both are used.
 
292
 
 
293
     o   An optional decimal digit string specifying a minimum
 
294
                 field width.  If the converted value has fewer
 
295
                 characters than the field width, it will be padded
 
296
                 with spaces on the left (or right, if the
 
297
                 left-adjustment flag has been given) to fill out
 
298
                 the field width.
 
299
 
 
300
     o   An optional precision, in the form of a period `.' followed
 
301
                 by an optional digit string.  If the digit string
 
302
                 is omitted, the precision is taken as zero.  This
 
303
                 gives the minimum number of digits to appear for
 
304
                 d, i, o, u, x, and X conversions, the number of
 
305
                 digits to appear after the decimal-point for e,
 
306
                 E, and f conversions, the maximum number of
 
307
                 significant digits for g and G conversions, or
 
308
                 the maximum number of characters to be printed
 
309
                 from a string for s conversions.
 
310
 
 
311
     o   The optional character h, specifying that a following d,
 
312
                 i, o, u, x, or X conversion corresponds to a short
 
313
                 int or unsigned short int argument, or that a
 
314
                 following n conversion corresponds to a pointer
 
315
                 to a short int argument.
 
316
 
 
317
     o   The optional character l (ell) specifying that a following
 
318
                 d, i, o, u, x, or X conversion applies to a pointer
 
319
                 to a long int or unsigned long int argument, or
 
320
                 that a following n conversion corresponds to a
 
321
                 pointer to a long int argument.
 
322
 
 
323
     o   The optional character q, specifying that a following d,
 
324
                 i, o, u, x, or X conversion corresponds to a quad_t
 
325
                 or u_quad_t argument, or that a following n
 
326
                 conversion corresponds to a quad_t argument.
 
327
         This value is always printed in HEX notation.  Tough.
 
328
         quad_t's are an OS system implementation, and should
 
329
         not be allowed.
 
330
 
 
331
     o   The character L specifying that a following e, E, f, g,
 
332
                 or G conversion corresponds to a long double
 
333
                 argument.
 
334
 
 
335
     o   A character that specifies the type of conversion to be applied.
 
336
 
 
337
 
 
338
     A field width or precision, or both, may be indicated by an asterisk `*'
 
339
     instead of a digit string.  In this case, an int argument supplies the
 
340
     field width or precision.  A negative field width is treated as a left
 
341
     adjustment flag followed by a positive field width; a negative precision
 
342
     is treated as though it were missing.
 
343
 
 
344
     The conversion specifiers and their meanings are:
 
345
 
 
346
     diouxX  The int (or appropriate variant) argument is converted to signed
 
347
                         decimal (d and i), unsigned octal (o), unsigned decimal
 
348
                         (u), or unsigned hexadecimal (x and X) notation.  The
 
349
                         letters abcdef are used for x conversions; the letters
 
350
                         ABCDEF are used for X conversions.  The precision, if
 
351
                         any, gives the minimum number of digits that must
 
352
                         appear; if the converted value requires fewer digits,
 
353
                         it is padded on the left with zeros.
 
354
 
 
355
     eE      The double argument is rounded and converted in the style
 
356
             [-]d.ddde+-dd where there is one digit before the decimal-point
 
357
                         character and the number of digits after it is equal
 
358
                         to the precision; if the precision is missing, it is
 
359
                         taken as 6; if the precision is zero, no decimal-point
 
360
                         character appears.  An E conversion uses the letter
 
361
                         E (rather than e) to introduce the exponent.
 
362
                         The exponent always contains at least two digits; if
 
363
                         the value is zero, the exponent is 00.
 
364
 
 
365
     f       The double argument is rounded and converted to decimal notation
 
366
             in the style [-]ddd.ddd, where the number of digits after the
 
367
             decimal-point character is equal to the precision specification.
 
368
             If the precision is missing, it is taken as 6; if the precision
 
369
             is explicitly zero, no decimal-point character appears.  If a
 
370
             decimal point appears, at least one digit appears before it.
 
371
 
 
372
     g       The double argument is converted in style f or e (or
 
373
                         E for G conversions).  The precision specifies the
 
374
                         number of significant digits.  If the precision is
 
375
                         missing, 6 digits are given; if the precision is zero,
 
376
                         it is treated as 1.  Style e is used if the exponent
 
377
                         from its conversion is less than -4 or greater than
 
378
                         or equal to the precision.  Trailing zeros are removed
 
379
                         from the fractional part of the result; a decimal
 
380
                         point appears only if it is followed by at least one
 
381
                         digit.
 
382
 
 
383
     c       The int argument is converted to an unsigned char,
 
384
             and the resulting character is written.
 
385
 
 
386
     s       The ``char *'' argument is expected to be a pointer to an array
 
387
                         of character type (pointer to a string).  Characters
 
388
                         from the array are written up to (but not including)
 
389
                         a terminating NUL character; if a precision is
 
390
                         specified, no more than the number specified are
 
391
                         written.  If a precision is given, no null character
 
392
                         need be present; if the precision is not specified,
 
393
                         or is greater than the size of the array, the array
 
394
                         must contain a terminating NUL character.
 
395
 
 
396
     %       A `%' is written. No argument is converted. The complete
 
397
             conversion specification is `%%'.
 
398
 
 
399
     In no case does a non-existent or small field width cause truncation of a
 
400
     field; if the result of a conversion is wider than the field width, the
 
401
     field is expanded to contain the conversion result.
 
402
 
 
403
EXAMPLES
 
404
     To print a date and time in the form `Sunday, July 3, 10:02', where
 
405
     weekday and month are pointers to strings:
 
406
 
 
407
           #include <stdio.h>
 
408
           fprintf(stdout, "%s, %s %d, %.2d:%.2d\n",
 
409
                   weekday, month, day, hour, min);
 
410
 
 
411
     To print pi to five decimal places:
 
412
 
 
413
           #include <math.h>
 
414
           #include <stdio.h>
 
415
           fprintf(stdout, "pi = %.5f\n", 4 * atan(1.0));
 
416
 
 
417
     To allocate a 128 byte string and print into it:
 
418
 
 
419
           #include <stdio.h>
 
420
           #include <stdlib.h>
 
421
           #include <stdarg.h>
 
422
           char *newfmt(const char *fmt, ...)
 
423
           {
 
424
                           char *p;
 
425
                           va_list ap;
 
426
                           if ((p = malloc(128)) == NULL)
 
427
                                   return (NULL);
 
428
                           va_start(ap, fmt);
 
429
                           (void) vsnprintf(p, 128, fmt, ap);
 
430
                           va_end(ap);
 
431
                           return (p);
 
432
           }
 
433
 
 
434
SEE ALSO
 
435
     printf(1),  scanf(3)
 
436
 
 
437
STANDARDS
 
438
     Turkey C Standardization and wimpy POSIX folks did not define
 
439
     snprintf or vsnprintf().
 
440
 
 
441
BUGS
 
442
     The conversion formats %D, %O, and %U are not standard and are provided
 
443
     only for backward compatibility.  The effect of padding the %p format
 
444
     with zeros (either by the `0' flag or by specifying a precision), and the
 
445
     benign effect (i.e., none) of the `#' flag on %n and %p conversions, as
 
446
     well as other nonsensical combinations such as %Ld, are not standard;
 
447
     such combinations should be avoided.
 
448
 
 
449
     The typedef names quad_t and u_quad_t are infelicitous.
 
450
 
 
451
*/
 
452
 
 
453
 
 
454
#include "config.h"
 
455
 
 
456
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
 
457
 
 
458
#include <sys/types.h>
 
459
#include <ctype.h>
 
460
#include <stdlib.h>
 
461
#if defined(HAVE_STRING_H)
 
462
# include <string.h>
 
463
#endif
 
464
#if defined(HAVE_STRINGS_H)
 
465
# include <strings.h>
 
466
#endif
 
467
#include <stdio.h>
 
468
 
 
469
/*
 
470
 * For testing, define these values
 
471
 */
 
472
#if 0
 
473
#define HAVE_STDARG_H 1
 
474
#define TEST 1
 
475
#define HAVE_QUAD_T 1
 
476
#endif
 
477
 
 
478
/**** ENDINCLUDE ****/
 
479
 
 
480
/*************************************************
 
481
 * KEEP THIS STRING - MODIFY AT THE END WITH YOUR REVISIONS
 
482
 * i.e. - the LOCAL REVISIONS part is for your use
 
483
 *************************************************/
 
484
 
 
485
 
 
486
 static char *const _id = "plp_snprintf V98.12.21 Copyright Patrick Powell 1988-2000 "
 
487
 "$Id: snprintf.c,v 1.1 2002/08/30 16:56:50 jmarcus Exp $"
 
488
 " LOCAL REVISIONS: Modified for Netatalk 2002/02/12 Burkhard Schmidt";
 
489
 
 
490
/* varargs declarations: */
 
491
 
 
492
# undef HAVE_STDARGS    /* let's hope that works everywhere (mj) */
 
493
# undef VA_LOCAL_DECL
 
494
# undef VA_START
 
495
# undef VA_SHIFT
 
496
# undef VA_END
 
497
 
 
498
#if defined(HAVE_STDARG_H)
 
499
# include <stdarg.h>
 
500
# define HAVE_STDARGS    /* let's hope that works everywhere (mj) */
 
501
# define VA_LOCAL_DECL   va_list ap;
 
502
# define VA_START(f)     va_start(ap, f)
 
503
# define VA_SHIFT(v,t)  ;       /* no-op for ANSI */
 
504
# define VA_END          va_end(ap)
 
505
#else
 
506
# if defined(HAVE_VARARGS_H)
 
507
#  include <varargs.h>
 
508
#  undef HAVE_STDARGS
 
509
#  define VA_LOCAL_DECL   va_list ap;
 
510
#  define VA_START(f)     va_start(ap)          /* f is ignored! */
 
511
#  define VA_SHIFT(v,t) v = va_arg(ap,t)
 
512
#  define VA_END                va_end(ap)
 
513
# else
 
514
XX ** NO VARARGS ** XX
 
515
# endif
 
516
#endif
 
517
 
 
518
union value {
 
519
#if defined(HAVE_QUAD_T)
 
520
        quad_t qvalue;
 
521
#endif
 
522
#if defined(HAVE_LONG_LONG)
 
523
        long long value;
 
524
#else
 
525
        long value;
 
526
#endif
 
527
        double dvalue;
 
528
};
 
529
 
 
530
#undef CVAL 
 
531
#define CVAL(s) (*((unsigned char *)s))
 
532
 
 
533
extern int errno;
 
534
 static char * plp_Errormsg ( int err, char *buffer );
 
535
 static void dopr( int visible_control, char **buffer, int *left,
 
536
        const char *format, va_list args );
 
537
 static void fmtstr( int visible_control, char **buffer, int *left,
 
538
        char *value, int ljust, int len, int zpad, int precision );
 
539
 static void fmtnum(  char **buffer, int *left,
 
540
        union value *value, int base, int dosign,
 
541
        int ljust, int len, int zpad, int precision );
 
542
#if defined(HAVE_QUAD_T)
 
543
 static void fmtquad(  char **buffer, int *left,
 
544
        union value *value, int base, int dosign,
 
545
        int ljust, int len, int zpad, int precision );
 
546
#endif
 
547
 static void fmtdouble( char **bufer, int *left,
 
548
        int fmt, double value,
 
549
        int ljust, int len, int zpad, int precision );
 
550
 static void dostr(  char **buffer, int *left, char *str );
 
551
 static void dopr_outch(  char **buffer, int *left, int c );
 
552
 
 
553
int plp_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
 
554
{
 
555
        int left;
 
556
        char *buffer;
 
557
        if( count < 0 ) count = 0;
 
558
        left = count;
 
559
        if( count == 0 ) str = 0;
 
560
        buffer = str;
 
561
        dopr( 1, &buffer, &left, fmt, args );
 
562
        /* fprintf(stderr,"str 0x%x, buffer 0x%x, count %d, left %d\n",
 
563
                (int)str, (int)buffer, count, left ); */
 
564
        if( str && count > 0 ){
 
565
                if( left > 0 ){
 
566
                        str[count-left] = 0;
 
567
                } else {
 
568
                        str[count-1] = 0;
 
569
                }
 
570
        }
 
571
        return(count - left);
 
572
}
 
573
 
 
574
int plp_unsafe_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
 
575
{
 
576
        int left;
 
577
        char *buffer;
 
578
        if( count < 0 ) count = 0;
 
579
        left = count;
 
580
        if( count == 0 ) str = 0;
 
581
        buffer = str;
 
582
        dopr( 0, &buffer, &left, fmt, args );
 
583
        /* fprintf(stderr,"str 0x%x, buffer 0x%x, count %d, left %d\n",
 
584
                (int)str, (int)buffer, count, left ); */
 
585
        if( str && count > 0 ){
 
586
                if( left > 0 ){
 
587
                        str[count-left] = 0;
 
588
                } else {
 
589
                        str[count-1] = 0;
 
590
                }
 
591
        }
 
592
        return(count - left);
 
593
}
 
594
 
 
595
/* VARARGS3 */
 
596
#ifdef HAVE_STDARGS
 
597
int plp_snprintf (char *str,size_t count,const char *fmt,...)
 
598
#else
 
599
int plp_snprintf (va_alist) va_dcl
 
600
#endif
 
601
{
 
602
#ifndef HAVE_STDARGS
 
603
    char *str;
 
604
        size_t count;
 
605
    char *fmt;
 
606
#endif
 
607
        int n = 0;
 
608
    VA_LOCAL_DECL
 
609
 
 
610
    VA_START (fmt);
 
611
    VA_SHIFT (str, char *);
 
612
    VA_SHIFT (count, size_t );
 
613
    VA_SHIFT (fmt, char *);
 
614
    n = plp_vsnprintf ( str, count, fmt, ap);
 
615
    VA_END;
 
616
        return( n );
 
617
}
 
618
 
 
619
 
 
620
/* VARARGS3 */
 
621
#ifdef HAVE_STDARGS
 
622
int plp_unsafe_snprintf (char *str,size_t count,const char *fmt,...)
 
623
#else
 
624
int plp_unsafe_snprintf (va_alist) va_dcl
 
625
#endif
 
626
{
 
627
#ifndef HAVE_STDARGS
 
628
    char *str;
 
629
        size_t count;
 
630
    char *fmt;
 
631
#endif
 
632
        int n = 0;
 
633
    VA_LOCAL_DECL
 
634
 
 
635
    VA_START (fmt);
 
636
    VA_SHIFT (str, char *);
 
637
    VA_SHIFT (count, size_t );
 
638
    VA_SHIFT (fmt, char *);
 
639
    n = plp_unsafe_vsnprintf ( str, count, fmt, ap);
 
640
    VA_END;
 
641
        return( n );
 
642
}
 
643
 static void dopr( int visible_control, char **buffer, int *left, const char *format, va_list args )
 
644
{
 
645
        int ch;
 
646
        union value value;
 
647
        int longflag = 0;
 
648
        int quadflag = 0;
 
649
        char *strvalue;
 
650
        int ljust;
 
651
        int len;
 
652
        int zpad;
 
653
        int precision;
 
654
        int set_precision;
 
655
        double dval;
 
656
        int err = errno;
 
657
        int base = 0;
 
658
        int signed_val = 0;
 
659
 
 
660
        while( (ch = *format++) ){
 
661
                switch( ch ){
 
662
                case '%':
 
663
                        longflag = quadflag =
 
664
                        ljust = len = zpad = base = signed_val = 0;
 
665
                        precision = -1; set_precision = 0;
 
666
                nextch: 
 
667
                        ch = *format++;
 
668
                        switch( ch ){
 
669
                        case 0:
 
670
                                dostr( buffer, left, "**end of format**" );
 
671
                                return;
 
672
                        case '-': ljust = 1; goto nextch;
 
673
                        case '.': set_precision = 1; precision = 0; goto nextch;
 
674
                        case '*': len = va_arg( args, int ); goto nextch;
 
675
                        case '0': /* set zero padding if len not set */
 
676
                                if(len==0 && set_precision == 0 ) zpad = '0';
 
677
                        case '1': case '2': case '3':
 
678
                        case '4': case '5': case '6':
 
679
                        case '7': case '8': case '9':
 
680
                                if( set_precision ){
 
681
                                        precision = precision*10 + ch - '0';
 
682
                                } else {
 
683
                                        len = len*10 + ch - '0';
 
684
                                }
 
685
                                goto nextch;
 
686
                        case 'l': ++longflag; goto nextch;
 
687
                        case 'q':
 
688
#if !defined( HAVE_QUAD_T )
 
689
                                        dostr( buffer, left, "*no quad_t support *");
 
690
                                        return;
 
691
#endif
 
692
                                        quadflag = 1;
 
693
                                        goto nextch;
 
694
                        case 'u': case 'U':
 
695
                                if( base == 0 ){ base = 10; signed_val = 0; }
 
696
                        case 'o': case 'O':
 
697
                                if( base == 0 ){ base = 8; signed_val = 0; }
 
698
                        case 'd': case 'D':
 
699
                                if( base == 0 ){ base = 10; signed_val = 1; }
 
700
                        case 'x':
 
701
                                if( base == 0 ){ base = 16; signed_val = 0; }
 
702
                        case 'X':
 
703
                                if( base == 0 ){ base = -16; signed_val = 0; }
 
704
#if defined( HAVE_QUAD_T )
 
705
                                if( quadflag ){
 
706
                                        value.qvalue = va_arg( args, quad_t );
 
707
                                        fmtquad( buffer, left,  &value,base,signed_val, ljust, len, zpad, precision );
 
708
                                        break;
 
709
                                } else
 
710
#endif
 
711
                                if( longflag > 1 ){
 
712
#if defined(HAVE_LONG_LONG)
 
713
                                        if( signed_val ){
 
714
                                        value.value = va_arg( args, long long );
 
715
                                        } else {
 
716
                                        value.value = va_arg( args, unsigned long long );
 
717
                                        }
 
718
#else
 
719
                                        if( signed_val ){
 
720
                                        value.value = va_arg( args, long );
 
721
                                        } else {
 
722
                                        value.value = va_arg( args, unsigned long );
 
723
                                        }
 
724
#endif
 
725
                                } else if( longflag ){
 
726
                                        if( signed_val ){
 
727
                                                value.value = va_arg( args, long );
 
728
                                        } else {
 
729
                                                value.value = va_arg( args, unsigned long );
 
730
                                        }
 
731
                                } else {
 
732
                                        if( signed_val ){
 
733
                                                value.value = va_arg( args, int );
 
734
                                        } else {
 
735
                                                value.value = va_arg( args, unsigned int );
 
736
                                        }
 
737
                                }
 
738
                                fmtnum( buffer, left,  &value,base,signed_val, ljust, len, zpad, precision ); break;
 
739
                        case 's':
 
740
                                strvalue = va_arg( args, char *);
 
741
                                fmtstr( visible_control, buffer, left, strvalue,ljust,len, zpad, precision );
 
742
                                break;
 
743
                        case 'c':
 
744
                                ch = va_arg( args, int );
 
745
                                { char b[2];
 
746
                                        b[0] = ch;
 
747
                                        b[1] = 0;
 
748
                                        fmtstr( 0, buffer, left, b,ljust,len, zpad, precision );
 
749
                                }
 
750
                                break;
 
751
                        case 'f': case 'g': case 'e':
 
752
                                dval = va_arg( args, double );
 
753
                                fmtdouble( buffer, left, ch, dval,ljust,len, zpad, precision ); break;
 
754
                        case 'm':
 
755
                                { char shortbuffer[32];
 
756
                                fmtstr( visible_control, buffer, left,
 
757
                                        plp_Errormsg(err, shortbuffer),ljust,len, zpad, precision );
 
758
                                }
 
759
                                break;
 
760
                        case '%': dopr_outch( buffer, left, ch ); continue;
 
761
                        default:
 
762
                                dostr(  buffer, left, "???????" );
 
763
                        }
 
764
                        longflag = 0;
 
765
                        break;
 
766
                default:
 
767
                        dopr_outch( buffer, left, ch );
 
768
                        break;
 
769
                }
 
770
        }
 
771
}
 
772
 
 
773
/*
 
774
 * Format '%[-]len[.precision]s'
 
775
 * -   = left justify (ljust)
 
776
 * len = minimum length
 
777
 * precision = numbers of chars in string to use
 
778
 */
 
779
 static void
 
780
fmtstr( int visible_control, char **buffer, int *left,
 
781
         char *value, int ljust, int len, int zpad, int precision )
 
782
{
 
783
        int padlen, strlenv, i, c;      /* amount to pad */
 
784
 
 
785
        if( value == 0 ){
 
786
                value = "<NULL>";
 
787
        }
 
788
        /* cheap strlen so you do not have library call */
 
789
        for( strlenv = i = 0; (c=CVAL(value+i)); ++i ){
 
790
                if( visible_control && iscntrl( c ) && c != '\t' && c != '\n' ){
 
791
                        ++strlenv;
 
792
                }
 
793
                ++strlenv;
 
794
        }
 
795
        if( precision > 0 && strlenv > precision ){
 
796
                strlenv = precision;
 
797
        }
 
798
        padlen = len - strlenv;
 
799
        if( padlen < 0 ) padlen = 0;
 
800
        if( ljust ) padlen = -padlen;
 
801
        while( padlen > 0 ) {
 
802
                dopr_outch( buffer, left, ' ' );
 
803
                --padlen;
 
804
        }
 
805
        /* output characters */
 
806
        for( i = 0; i < strlenv && (c = CVAL(value+i)); ++i ){
 
807
                if( visible_control && iscntrl( c ) && c != '\t' && c != '\n' ){
 
808
                        dopr_outch(buffer, left, '^');
 
809
                        c = ('@' | (c & 0x1F));
 
810
                }
 
811
                dopr_outch(buffer, left, c);
 
812
        }
 
813
        while( padlen < 0 ) {
 
814
                dopr_outch( buffer, left, ' ' );
 
815
                ++padlen;
 
816
        }
 
817
}
 
818
 
 
819
 static void
 
820
fmtnum( char **buffer, int *left,
 
821
        union value *value, int base, int dosign, int ljust,
 
822
        int len, int zpad, int precision )
 
823
{
 
824
        int signvalue = 0;
 
825
#if defined(HAVE_LONG_LONG)
 
826
        unsigned long long uvalue;
 
827
#else
 
828
        unsigned long uvalue;
 
829
#endif
 
830
        char convert[sizeof( union value) * 8 + 16];
 
831
        int place = 0;
 
832
        int padlen = 0; /* amount to pad */
 
833
        int caps = 0;
 
834
 
 
835
        /* fprintf(stderr,"value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n",
 
836
                value, base, dosign, ljust, len, zpad );/ **/
 
837
        uvalue = value->value;
 
838
        if( dosign ){
 
839
                if( value->value < 0 ) {
 
840
                        signvalue = '-';
 
841
                        uvalue = -value->value; 
 
842
                }
 
843
        }
 
844
        if( base < 0 ){
 
845
                caps = 1;
 
846
                base = -base;
 
847
        }
 
848
        do{
 
849
                convert[place++] =
 
850
                        (caps? "0123456789ABCDEF":"0123456789abcdef")
 
851
                         [uvalue % (unsigned)base  ];
 
852
                uvalue = (uvalue / (unsigned)base );
 
853
        }while(uvalue);
 
854
        convert[place] = 0;
 
855
        padlen = len - place;
 
856
        if( padlen < 0 ) padlen = 0;
 
857
        if( ljust ) padlen = -padlen;
 
858
        /* fprintf( stderr, "str '%s', place %d, sign %c, padlen %d\n",
 
859
                convert,place,signvalue,padlen); / **/
 
860
        if( zpad && padlen > 0 ){
 
861
                if( signvalue ){
 
862
                        dopr_outch( buffer, left, signvalue );
 
863
                        --padlen;
 
864
                        signvalue = 0;
 
865
                }
 
866
                while( padlen > 0 ){
 
867
                        dopr_outch( buffer, left, zpad );
 
868
                        --padlen;
 
869
                }
 
870
        }
 
871
        while( padlen > 0 ) {
 
872
                dopr_outch( buffer, left, ' ' );
 
873
                --padlen;
 
874
        }
 
875
        if( signvalue ) dopr_outch( buffer, left, signvalue );
 
876
        while( place > 0 ) dopr_outch( buffer, left, convert[--place] );
 
877
        while( padlen < 0 ){
 
878
                dopr_outch( buffer, left, ' ' );
 
879
                ++padlen;
 
880
        }
 
881
}
 
882
 
 
883
#if defined(HAVE_QUAD_T)
 
884
 
 
885
 static void
 
886
fmtquad( char **buffer, int *left,
 
887
        union value *value, int base, int dosign, int ljust,
 
888
        int len, int zpad, int precision )
 
889
{
 
890
        int signvalue = 0;
 
891
        int place = 0;
 
892
        int padlen = 0; /* amount to pad */
 
893
        int caps = 0;
 
894
        int i, c;
 
895
        union {
 
896
                quad_t qvalue;
 
897
                unsigned char qconvert[sizeof(quad_t)];
 
898
        } vvalue;
 
899
        char convert[2*sizeof(quad_t)+1];
 
900
 
 
901
        /* fprintf(stderr,"value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n",
 
902
                value, base, dosign, ljust, len, zpad );/ **/
 
903
        vvalue.qvalue = value->qvalue;
 
904
 
 
905
        if( base < 0 ){
 
906
                caps = 1;
 
907
        }
 
908
 
 
909
        for( i = 0; i < sizeof(quad_t); ++i ){
 
910
                c = vvalue.qconvert[i];
 
911
                convert[2*i] = 
 
912
                        (caps? "0123456789ABCDEF":"0123456789abcdef")[ (c >> 4) & 0xF];
 
913
                convert[2*i+1] = 
 
914
                        (caps? "0123456789ABCDEF":"0123456789abcdef")[ c  & 0xF];
 
915
        }
 
916
        convert[2*i] = 0;
 
917
 
 
918
        place = strlen(convert);
 
919
        padlen = len - place;
 
920
        if( padlen < 0 ) padlen = 0;
 
921
        if( ljust ) padlen = -padlen;
 
922
        /* fprintf( stderr, "str '%s', place %d, sign %c, padlen %d\n",
 
923
                convert,place,signvalue,padlen); / **/
 
924
        if( zpad && padlen > 0 ){
 
925
                if( signvalue ){
 
926
                        dopr_outch( buffer, left, signvalue );
 
927
                        --padlen;
 
928
                        signvalue = 0;
 
929
                }
 
930
                while( padlen > 0 ){
 
931
                        dopr_outch( buffer, left, zpad );
 
932
                        --padlen;
 
933
                }
 
934
        }
 
935
        while( padlen > 0 ) {
 
936
                dopr_outch( buffer, left, ' ' );
 
937
                --padlen;
 
938
        }
 
939
        if( signvalue ) dopr_outch( buffer, left, signvalue );
 
940
        while( place > 0 ) dopr_outch( buffer, left, convert[--place] );
 
941
        while( padlen < 0 ){
 
942
                dopr_outch( buffer, left, ' ' );
 
943
                ++padlen;
 
944
        }
 
945
}
 
946
 
 
947
#endif
 
948
 
 
949
 static void mystrcat(char *dest, char *src )
 
950
{
 
951
        if( dest && src ){
 
952
                dest += strlen(dest);
 
953
                strcpy(dest,src);
 
954
        }
 
955
}
 
956
 
 
957
 static void
 
958
fmtdouble( char **buffer, int *left,
 
959
        int fmt, double value, int ljust, int len, int zpad, int precision )
 
960
{
 
961
        char convert[sizeof( union value) * 8 + 16];
 
962
        char formatstr[128];
 
963
 
 
964
        /* fprintf(stderr,"len %d, precision %d\n", len, precision ); */
 
965
        if( len > (sizeof(convert) - 20) ){
 
966
                len = sizeof(convert) - 20;
 
967
        }
 
968
        if( precision >= 0 && precision > sizeof(convert) - 20 ){
 
969
                precision = sizeof(convert) - 20;
 
970
        }
 
971
        if( precision >= 0 && precision > len ) precision = len;
 
972
        strcpy( formatstr, "%" );
 
973
        if( ljust ) mystrcat(formatstr, "-" );
 
974
        if( zpad ) mystrcat(formatstr, "0" );
 
975
        if( len ){
 
976
                sprintf( formatstr+strlen(formatstr), "%d", len );
 
977
        }
 
978
        if( precision >= 0 ){
 
979
                sprintf( formatstr+strlen(formatstr), ".%d", precision );
 
980
        }
 
981
        sprintf( formatstr+strlen(formatstr), "%c", fmt );
 
982
        /* this is easier than trying to do the portable dtostr */
 
983
        /* fprintf(stderr,"format string '%s'\n", formatstr); */
 
984
        sprintf( convert, formatstr, value );
 
985
        dostr( buffer, left, convert );
 
986
}
 
987
 
 
988
 static void dostr( char **buffer, int *left, char *str  )
 
989
{
 
990
        if(str)while(*str) dopr_outch( buffer, left, *str++ );
 
991
}
 
992
 
 
993
 static void dopr_outch( char **buffer, int *left, int c )
 
994
{
 
995
        if( *left > 0 ){
 
996
                *(*buffer)++ = c;
 
997
        }
 
998
        *left -= 1;
 
999
}
 
1000
 
 
1001
 
 
1002
/****************************************************************************
 
1003
 * static char *plp_errormsg( int err )
 
1004
 *  returns a printable form of the
 
1005
 *  errormessage corresponding to the valie of err.
 
1006
 *  This is the poor man's version of sperror(), not available on all systems
 
1007
 *  Patrick Powell Tue Apr 11 08:05:05 PDT 1995
 
1008
 ****************************************************************************/
 
1009
/****************************************************************************/
 
1010
 
 
1011
#if !defined(HAVE_STRERROR)
 
1012
# undef  num_errors
 
1013
# if defined(HAVE_SYS_ERRLIST)
 
1014
#  if !defined(HAVE_DECL_SYS_ERRLIST)
 
1015
     extern const char *const sys_errlist[];
 
1016
#  endif
 
1017
#  if defined(HAVE_SYS_NERR)
 
1018
#   if !defined(HAVE_DECL_SYS_NERR)
 
1019
      extern int sys_nerr;
 
1020
#   endif
 
1021
#   define num_errors    (sys_nerr)
 
1022
#  endif
 
1023
# endif
 
1024
# if !defined(num_errors)
 
1025
#   define num_errors   (-1)            /* always use "errno=%d" */
 
1026
# endif
 
1027
#endif
 
1028
 
 
1029
 static char * plp_Errormsg ( int err, char *buffer /* int maxlen = 32 */)
 
1030
{
 
1031
    char *cp;
 
1032
 
 
1033
#if defined(HAVE_STRERROR)
 
1034
        cp = (void *)strerror(err);
 
1035
#else
 
1036
# if defined(HAVE_SYS_ERRLIST)
 
1037
    if (err >= 0 && err < num_errors) {
 
1038
                cp = (void *)sys_errlist[err];
 
1039
    } else
 
1040
# endif
 
1041
        {
 
1042
                (void) sprintf (buffer, "errno=%d", err);
 
1043
                cp = buffer;
 
1044
    }
 
1045
#endif
 
1046
    return (cp);
 
1047
}
 
1048
 
 
1049
#if defined(TEST)
 
1050
#include <stdio.h>
 
1051
int main( void )
 
1052
{
 
1053
        char buffer[128];
 
1054
        char *t;
 
1055
        char *test1 = "01234";
 
1056
        int n;
 
1057
        errno = 1;
 
1058
        buffer[0] = 0;
 
1059
        n = plp_snprintf( buffer, 0, (t="test")); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1060
        n = plp_snprintf( buffer, sizeof(buffer), (t="errno '%m'")); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1061
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1062
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%12s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1063
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%-12s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1064
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%12.2s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1065
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%-12.2s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1066
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1067
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%g"), 1.2345 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1068
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%12g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1069
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%12.1g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1070
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%12.2g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1071
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%12.3g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1072
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%0*d"), 6, 1 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1073
#if defined(HAVE_LONG_LONG)
 
1074
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%llx"), 1, 2, 3, 4 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1075
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%llx"), (long long)1, (long long)2 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1076
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%qx"), 1, 2, 3, 4 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1077
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%qx"), (quad_t)1, (quad_t)2 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1078
#endif
 
1079
        n = plp_snprintf( buffer, sizeof(buffer), (t = "0%x, 0%x"), (char *)(0x01234567), (char *)0, 0, 0, 0); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1080
        n = plp_snprintf( buffer, sizeof(buffer), (t = "0%x, 0%x"), (char *)(0x01234567), (char *)0x89ABCDEF, 0, 0, 0); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1081
        n = plp_snprintf( buffer, sizeof(buffer), (t = "0%x, 0%x"), t, 0, 0, 0, 0); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1082
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%f"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1083
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%f"), 1.2345 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1084
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%12f"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1085
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%12.2f"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1086
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1087
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%.0f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1088
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%0.0f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1089
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%1.0f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1090
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%1.5f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1091
        n = plp_snprintf( buffer, sizeof(buffer), (t = "%5.5f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer );
 
1092
        return(0);
 
1093
}
 
1094
#endif
 
1095
 
 
1096
#endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */
 
1097
 
 
1098
#ifndef HAVE_VSNPRINTF
 
1099
int vsnprintf(char *str, size_t count, const char *fmt, va_list args)
 
1100
{
 
1101
    int n;
 
1102
    
 
1103
    n = plp_vsnprintf(str, count, fmt, args);
 
1104
    
 
1105
    return(n);
 
1106
}
 
1107
#endif /* ! HAVE_VSNPRINTF */
 
1108
 
 
1109
#ifndef HAVE_SNPRINTF
 
1110
#ifdef HAVE_STDARGS
 
1111
int snprintf (char *str,size_t count,const char *fmt,...)
 
1112
#else
 
1113
int snprintf (va_alist) va_dcl
 
1114
#endif
 
1115
{
 
1116
#ifndef HAVE_STDARGS
 
1117
    char *str;
 
1118
        size_t count;
 
1119
    char *fmt;
 
1120
#endif
 
1121
        int n = 0;
 
1122
    VA_LOCAL_DECL
 
1123
 
 
1124
    VA_START (fmt);
 
1125
    VA_SHIFT (str, char *);
 
1126
    VA_SHIFT (count, size_t );
 
1127
    VA_SHIFT (fmt, char *);
 
1128
    n = plp_vsnprintf ( str, count, fmt, ap);
 
1129
    VA_END;
 
1130
        return( n );
 
1131
}
 
1132
#endif /* ! HAVE_VNSPRINTF */