1
/**************************************************************************
2
* Copyright 1994-2000 Patrick Powell, San Diego, CA <papowell@astart.com>
4
* Modified for Netatalk 2002/02/12 Burkhard Schmidt <bs@cpfs.mpg.de>
5
**************************************************************************/
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
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.
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,
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.
34
This version of snprintf is VERY limited by modern standards.
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.
43
COPYRIGHT AND TERMS OF USE:
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
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
57
The next include line is expected to work in conjunction with the
58
GNU CONFIGURE utility. You should define the following macros
61
HAVE_STDARG_H - if the <stdargs.h> include file is available
62
HAVE_VARARG_H - if the <varargs.h> include file is available
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
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
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:
81
AC_CHECK_FUNCS(strerror);
82
AC_CACHE_CHECK(for errno,
85
AC_TRY_LINK(,[extern int errno; return (errno);],
86
ac_cv_errno=yes, ac_cv_errno=no)
88
if test "$ac_cv_errno" = yes; then
90
AC_CACHE_CHECK(for errno declaration,
103
],[return(sys_nerr);],
104
ac_cv_decl_errno=yes, ac_cv_decl_errno=no)
106
if test "$ac_cv_decl_errno" = yes; then
107
AC_DEFINE(HAVE_DECL_ERRNO)
111
AC_CACHE_CHECK(for sys_nerr,
114
AC_TRY_LINK(,[extern int sys_nerr; return (sys_nerr);],
115
ac_cv_sys_nerr=yes, ac_cv_sys_nerr=no)
117
if test "$ac_cv_sys_nerr" = yes; then
118
AC_DEFINE(HAVE_SYS_NERR)
119
AC_CACHE_CHECK(for sys_nerr declaration,
129
#endif],[return(sys_nerr);],
130
ac_cv_decl_sys_nerr_def=yes, ac_cv_decl_sys_nerr_def=no)
132
if test "$ac_cv_decl_sys_nerr" = yes; then
133
AC_DEFINE(HAVE_DECL_SYS_NERR)
138
AC_CACHE_CHECK(for sys_errlist array,
140
[AC_TRY_LINK(,[extern char *sys_errlist[];
142
ac_cv_sys_errlist=yes, ac_cv_sys_errlist=no)
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,
156
#endif],[char *s = sys_errlist[0]; return(*s);],
157
ac_cv_decl_sys_errlist=yes, ac_cv_decl_sys_errlist=no)
159
if test "$ac_cv_decl_sys_errlist" = yes; then
160
AC_DEFINE(HAVE_DECL_SYS_ERRLIST)
166
AC_CACHE_CHECK(checking for long long,
171
#include <sys/types.h>
172
], [printf("%d",sizeof(long long));],
173
ac_cv_long_long=yes, ac_cv_long_long=no)
175
if test $ac_cv_long_long = yes; then
176
AC_DEFINE(HAVE_LONG_LONG)
179
AC_CACHE_CHECK(checking for long double,
184
#include <sys/types.h>
185
], [printf("%d",sizeof(long double));],
186
ac_cv_long_double=yes, ac_cv_long_double=no)
188
if test $ac_cv_long_double = yes; then
189
AC_DEFINE(HAVE_LONG_DOUBLE)
192
AC_CACHE_CHECK(checking for quad_t,
197
#include <sys/types.h>
198
], [printf("%d",sizeof(quad_t));],
199
ac_cv_quad_t=yes, ac_cv_quad_t=no)
201
if test $ac_cv_quad_t = yes; then
202
AC_DEFINE(HAVE_QUAD_T)
208
plp_snprintf, plp_vsnprintf - formatted output conversion
215
plp_snprintf(const char *format, size_t size, va_list ap);
217
plp_unsafe_snprintf(const char *format, size_t size, va_list ap);
219
AKA snprintf and unsafe_snprintf in the documentation below
222
vsnprintf(char *str, size_t size, const char *format, va_list ap);
224
unsafe_vsnprintf(char *str, size_t size, const char *format, va_list ap);
226
AKA vsnprintf and unsafe_vsnprintf in the documentation below
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
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.
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.
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
270
o Zero or more of the following flags:
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.
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
285
- A space, specifying that a blank should be left before
286
a positive number produced by a signed conversion (d, e, E, f,
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.
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
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.
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.
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.
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
331
o The character L specifying that a following e, E, f, g,
332
or G conversion corresponds to a long double
335
o A character that specifies the type of conversion to be applied.
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.
344
The conversion specifiers and their meanings are:
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.
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.
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.
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
383
c The int argument is converted to an unsigned char,
384
and the resulting character is written.
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.
396
% A `%' is written. No argument is converted. The complete
397
conversion specification is `%%'.
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.
404
To print a date and time in the form `Sunday, July 3, 10:02', where
405
weekday and month are pointers to strings:
408
fprintf(stdout, "%s, %s %d, %.2d:%.2d\n",
409
weekday, month, day, hour, min);
411
To print pi to five decimal places:
415
fprintf(stdout, "pi = %.5f\n", 4 * atan(1.0));
417
To allocate a 128 byte string and print into it:
422
char *newfmt(const char *fmt, ...)
426
if ((p = malloc(128)) == NULL)
429
(void) vsnprintf(p, 128, fmt, ap);
438
Turkey C Standardization and wimpy POSIX folks did not define
439
snprintf or vsnprintf().
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.
449
The typedef names quad_t and u_quad_t are infelicitous.
456
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
458
#include <sys/types.h>
461
#if defined(HAVE_STRING_H)
464
#if defined(HAVE_STRINGS_H)
465
# include <strings.h>
470
* For testing, define these values
473
#define HAVE_STDARG_H 1
475
#define HAVE_QUAD_T 1
478
/**** ENDINCLUDE ****/
480
/*************************************************
481
* KEEP THIS STRING - MODIFY AT THE END WITH YOUR REVISIONS
482
* i.e. - the LOCAL REVISIONS part is for your use
483
*************************************************/
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";
490
/* varargs declarations: */
492
# undef HAVE_STDARGS /* let's hope that works everywhere (mj) */
493
# undef VA_LOCAL_DECL
498
#if defined(HAVE_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)
506
# if defined(HAVE_VARARGS_H)
507
# include <varargs.h>
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)
514
XX ** NO VARARGS ** XX
519
#if defined(HAVE_QUAD_T)
522
#if defined(HAVE_LONG_LONG)
531
#define CVAL(s) (*((unsigned char *)s))
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 );
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 );
553
int plp_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
557
if( count < 0 ) count = 0;
559
if( count == 0 ) str = 0;
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 ){
571
return(count - left);
574
int plp_unsafe_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
578
if( count < 0 ) count = 0;
580
if( count == 0 ) str = 0;
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 ){
592
return(count - left);
597
int plp_snprintf (char *str,size_t count,const char *fmt,...)
599
int plp_snprintf (va_alist) va_dcl
611
VA_SHIFT (str, char *);
612
VA_SHIFT (count, size_t );
613
VA_SHIFT (fmt, char *);
614
n = plp_vsnprintf ( str, count, fmt, ap);
622
int plp_unsafe_snprintf (char *str,size_t count,const char *fmt,...)
624
int plp_unsafe_snprintf (va_alist) va_dcl
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);
643
static void dopr( int visible_control, char **buffer, int *left, const char *format, va_list args )
660
while( (ch = *format++) ){
663
longflag = quadflag =
664
ljust = len = zpad = base = signed_val = 0;
665
precision = -1; set_precision = 0;
670
dostr( buffer, left, "**end of format**" );
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':
681
precision = precision*10 + ch - '0';
683
len = len*10 + ch - '0';
686
case 'l': ++longflag; goto nextch;
688
#if !defined( HAVE_QUAD_T )
689
dostr( buffer, left, "*no quad_t support *");
695
if( base == 0 ){ base = 10; signed_val = 0; }
697
if( base == 0 ){ base = 8; signed_val = 0; }
699
if( base == 0 ){ base = 10; signed_val = 1; }
701
if( base == 0 ){ base = 16; signed_val = 0; }
703
if( base == 0 ){ base = -16; signed_val = 0; }
704
#if defined( HAVE_QUAD_T )
706
value.qvalue = va_arg( args, quad_t );
707
fmtquad( buffer, left, &value,base,signed_val, ljust, len, zpad, precision );
712
#if defined(HAVE_LONG_LONG)
714
value.value = va_arg( args, long long );
716
value.value = va_arg( args, unsigned long long );
720
value.value = va_arg( args, long );
722
value.value = va_arg( args, unsigned long );
725
} else if( longflag ){
727
value.value = va_arg( args, long );
729
value.value = va_arg( args, unsigned long );
733
value.value = va_arg( args, int );
735
value.value = va_arg( args, unsigned int );
738
fmtnum( buffer, left, &value,base,signed_val, ljust, len, zpad, precision ); break;
740
strvalue = va_arg( args, char *);
741
fmtstr( visible_control, buffer, left, strvalue,ljust,len, zpad, precision );
744
ch = va_arg( args, int );
748
fmtstr( 0, buffer, left, b,ljust,len, zpad, precision );
751
case 'f': case 'g': case 'e':
752
dval = va_arg( args, double );
753
fmtdouble( buffer, left, ch, dval,ljust,len, zpad, precision ); break;
755
{ char shortbuffer[32];
756
fmtstr( visible_control, buffer, left,
757
plp_Errormsg(err, shortbuffer),ljust,len, zpad, precision );
760
case '%': dopr_outch( buffer, left, ch ); continue;
762
dostr( buffer, left, "???????" );
767
dopr_outch( buffer, left, ch );
774
* Format '%[-]len[.precision]s'
775
* - = left justify (ljust)
776
* len = minimum length
777
* precision = numbers of chars in string to use
780
fmtstr( int visible_control, char **buffer, int *left,
781
char *value, int ljust, int len, int zpad, int precision )
783
int padlen, strlenv, i, c; /* amount to pad */
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' ){
795
if( precision > 0 && strlenv > precision ){
798
padlen = len - strlenv;
799
if( padlen < 0 ) padlen = 0;
800
if( ljust ) padlen = -padlen;
801
while( padlen > 0 ) {
802
dopr_outch( buffer, left, ' ' );
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));
811
dopr_outch(buffer, left, c);
813
while( padlen < 0 ) {
814
dopr_outch( buffer, left, ' ' );
820
fmtnum( char **buffer, int *left,
821
union value *value, int base, int dosign, int ljust,
822
int len, int zpad, int precision )
825
#if defined(HAVE_LONG_LONG)
826
unsigned long long uvalue;
828
unsigned long uvalue;
830
char convert[sizeof( union value) * 8 + 16];
832
int padlen = 0; /* amount to pad */
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;
839
if( value->value < 0 ) {
841
uvalue = -value->value;
850
(caps? "0123456789ABCDEF":"0123456789abcdef")
851
[uvalue % (unsigned)base ];
852
uvalue = (uvalue / (unsigned)base );
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 ){
862
dopr_outch( buffer, left, signvalue );
867
dopr_outch( buffer, left, zpad );
871
while( padlen > 0 ) {
872
dopr_outch( buffer, left, ' ' );
875
if( signvalue ) dopr_outch( buffer, left, signvalue );
876
while( place > 0 ) dopr_outch( buffer, left, convert[--place] );
878
dopr_outch( buffer, left, ' ' );
883
#if defined(HAVE_QUAD_T)
886
fmtquad( char **buffer, int *left,
887
union value *value, int base, int dosign, int ljust,
888
int len, int zpad, int precision )
892
int padlen = 0; /* amount to pad */
897
unsigned char qconvert[sizeof(quad_t)];
899
char convert[2*sizeof(quad_t)+1];
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;
909
for( i = 0; i < sizeof(quad_t); ++i ){
910
c = vvalue.qconvert[i];
912
(caps? "0123456789ABCDEF":"0123456789abcdef")[ (c >> 4) & 0xF];
914
(caps? "0123456789ABCDEF":"0123456789abcdef")[ c & 0xF];
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 ){
926
dopr_outch( buffer, left, signvalue );
931
dopr_outch( buffer, left, zpad );
935
while( padlen > 0 ) {
936
dopr_outch( buffer, left, ' ' );
939
if( signvalue ) dopr_outch( buffer, left, signvalue );
940
while( place > 0 ) dopr_outch( buffer, left, convert[--place] );
942
dopr_outch( buffer, left, ' ' );
949
static void mystrcat(char *dest, char *src )
952
dest += strlen(dest);
958
fmtdouble( char **buffer, int *left,
959
int fmt, double value, int ljust, int len, int zpad, int precision )
961
char convert[sizeof( union value) * 8 + 16];
964
/* fprintf(stderr,"len %d, precision %d\n", len, precision ); */
965
if( len > (sizeof(convert) - 20) ){
966
len = sizeof(convert) - 20;
968
if( precision >= 0 && precision > sizeof(convert) - 20 ){
969
precision = sizeof(convert) - 20;
971
if( precision >= 0 && precision > len ) precision = len;
972
strcpy( formatstr, "%" );
973
if( ljust ) mystrcat(formatstr, "-" );
974
if( zpad ) mystrcat(formatstr, "0" );
976
sprintf( formatstr+strlen(formatstr), "%d", len );
978
if( precision >= 0 ){
979
sprintf( formatstr+strlen(formatstr), ".%d", precision );
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 );
988
static void dostr( char **buffer, int *left, char *str )
990
if(str)while(*str) dopr_outch( buffer, left, *str++ );
993
static void dopr_outch( char **buffer, int *left, int c )
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
/****************************************************************************/
1011
#if !defined(HAVE_STRERROR)
1013
# if defined(HAVE_SYS_ERRLIST)
1014
# if !defined(HAVE_DECL_SYS_ERRLIST)
1015
extern const char *const sys_errlist[];
1017
# if defined(HAVE_SYS_NERR)
1018
# if !defined(HAVE_DECL_SYS_NERR)
1019
extern int sys_nerr;
1021
# define num_errors (sys_nerr)
1024
# if !defined(num_errors)
1025
# define num_errors (-1) /* always use "errno=%d" */
1029
static char * plp_Errormsg ( int err, char *buffer /* int maxlen = 32 */)
1033
#if defined(HAVE_STRERROR)
1034
cp = (void *)strerror(err);
1036
# if defined(HAVE_SYS_ERRLIST)
1037
if (err >= 0 && err < num_errors) {
1038
cp = (void *)sys_errlist[err];
1042
(void) sprintf (buffer, "errno=%d", err);
1055
char *test1 = "01234";
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 );
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 );
1096
#endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */
1098
#ifndef HAVE_VSNPRINTF
1099
int vsnprintf(char *str, size_t count, const char *fmt, va_list args)
1103
n = plp_vsnprintf(str, count, fmt, args);
1107
#endif /* ! HAVE_VSNPRINTF */
1109
#ifndef HAVE_SNPRINTF
1111
int snprintf (char *str,size_t count,const char *fmt,...)
1113
int snprintf (va_alist) va_dcl
1116
#ifndef HAVE_STDARGS
1125
VA_SHIFT (str, char *);
1126
VA_SHIFT (count, size_t );
1127
VA_SHIFT (fmt, char *);
1128
n = plp_vsnprintf ( str, count, fmt, ap);
1132
#endif /* ! HAVE_VNSPRINTF */