3 /* _PDCLIB_print( const char *, struct _PDCLIB_status_t * )
5 This file is part of the Public Domain C Library (PDCLib).
6 Permission is granted to use, modify, and / or redistribute at will.
15 /* Using an integer's bits as flags for both the conversion flags and length
18 /* FIXME: one too many flags to work on a 16-bit machine */
29 #define E_intmax 1<<10
31 #define E_ptrdiff 1<<12
32 #define E_intptr 1<<13
33 #define E_ldouble 1<<14
35 #define E_unsigned 1<<16
37 /* This macro delivers a given character to either a memory buffer or a stream,
38 depending on the contents of 'status' (struct _PDCLIB_status_t).
39 x - the character to be delivered
40 i - pointer to number of characters already delivered in this call
41 n - pointer to maximum number of characters to be delivered in this call
42 s - the buffer into which the character shall be delivered
44 #define DELIVER( x ) \
46 if ( status->i < status->n ) { \
47 if ( status->stream != NULL ) { \
48 status->stream->buffer[status->stream->bufidx++] = x; \
49 if ( ( status->stream->bufidx == status->stream->bufsize ) \
50 || ( ( status->stream->status & _IOLBF ) && ( x == '\n' ) ) \
51 || ( status->stream->status & _IONBF ) ) \
52 fflush( status->stream ); \
54 status->s[status->i] = x; \
59 /* This function recursively converts a given integer value to a character
60 stream. The conversion is done under the control of a given status struct
61 and written either to a character string or a stream, depending on that
62 same status struct. The status struct also keeps the function from exceeding
63 snprintf() limits, and enables any necessary padding / prefixing of the
64 output once the number of characters to be printed is known, which happens
65 at the lowermost recursion level.
67 static void int2base( intmax_t value, struct _PDCLIB_status_t * status )
69 /* Registering the character being printed at the end of the function here
70 already so it will be taken into account when the deepestmost recursion
71 does the prefix / padding stuff.
74 if ( ( value / status->base ) != 0 )
76 /* More digits to be done - recurse deeper */
77 int2base( value / status->base, status );
81 /* We reached the last digit, the deepest point of our recursion, and
82 only now know how long the number to be printed actually is. Now we
83 have to do the sign, prefix, width, and precision padding stuff
84 before printing the numbers while we resurface from the recursion.
86 /* At worst, we need two prefix characters (hex prefix). */
87 char preface[3] = "\0";
89 if ( ( status->flags & E_alt ) && ( status->base == 16 || status->base == 8 ) )
91 /* Octal / hexadecimal prefix for "%#" conversions */
92 preface[ preidx++ ] = '0';
93 if ( status->base == 16 )
95 preface[ preidx++ ] = ( status->flags & E_lower ) ? 'x' : 'X';
100 /* Negative sign for negative values - at all times. */
101 preface[ preidx++ ] = '-';
103 else if ( ! ( status->flags & E_unsigned ) )
105 /* plus sign / extra space are only for unsigned conversions */
106 if ( status->flags & E_plus )
108 preface[ preidx++ ] = '+';
110 else if ( status->flags & E_space )
112 preface[ preidx++ ] = ' ';
116 size_t prec_pads = ( status->prec > status->this ) ? ( status->prec - status->this ) : 0;
117 if ( ! ( status->flags & ( E_minus | E_zero ) ) )
119 /* Space padding is only done if no zero padding or left alignment
120 is requested. Leave space for any prefixes determined above.
122 /* The number of characters to be printed, plus prefixes if any. */
123 /* This line contained probably the most stupid, time-wasting bug
124 I've ever perpetrated. Greetings to Samface, DevL, and all
125 sceners at Breakpoint 2006.
127 size_t characters = preidx + ( ( status->this > status->prec ) ? status->this : status->prec );
128 if ( status->width > characters )
130 for ( size_t i = 0; i < status->width - characters; ++i )
136 if ( status->i < status->n )
138 if ( status->stream != 0 )
141 status->stream->buffer[status->stream->bufidx++] = (char)' ',
142 if ( ( status->stream->bufidx == status->stream->bufsize )
143 || ( ( status->stream->status & 2 ) && (char)' ' == '\n' )
144 || ( status->stream->status & 4 ) )
145 fflush( status->stream )
148 else status->s[status->i] = ' ';
157 /* Now we did the padding, do the prefixes (if any). */
159 while ( preface[ preidx ] != '\0' )
161 DELIVER( preface[ preidx++ ] );
164 if ( ( ! ( status->flags & E_minus ) ) && ( status->flags & E_zero ) )
166 /* If field is not left aligned, and zero padding is requested, do
169 while ( status->this < status->width )
175 /* Do the precision padding if necessary. */
176 for ( size_t i = 0; i < prec_pads; ++i )
182 /* Recursion tail - print the current digit. */
184 int digit = value % status->base;
189 if ( status->flags & E_lower )
191 /* Lowercase letters. Same array used for strto...(). */
192 DELIVER( _PDCLIB_digits[ digit ] );
196 /* Uppercase letters. Array only used here, only 0-F. */
197 DELIVER( _PDCLIB_Xdigits[ digit ] );
202 const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status )
204 const char * orig_spec = spec;
205 if ( *(++spec) == '%' )
207 /* %% -> print single '%' */
211 /* Initializing status structure */
218 /* First come 0..n flags */
224 /* left-aligned output */
225 status->flags |= E_minus;
229 /* positive numbers prefixed with '+' */
230 status->flags |= E_plus;
234 /* alternative format (leading 0x for hex, 0 for octal) */
235 status->flags |= E_alt;
239 /* positive numbers prefixed with ' ' */
240 status->flags |= E_space;
244 /* right-aligned padding done with '0' instead of ' ' */
245 status->flags |= E_zero;
249 /* not a flag, exit flag parsing */
250 status->flags |= E_done;
253 } while ( ! ( status->flags & E_done ) );
255 /* Optional field width */
258 /* Retrieve width value from argument stack */
260 int width = va_arg( status->arg, int );
263 status->flags |= E_minus;
264 status->width = width * -1; /* FIXME: Should be abs( width ) */
268 status->width = width;
271 /* FIXME: Old version - with unsigned status->width, condition <0 is never true */
272 if ( ( status->width = va_arg( status->arg, int ) ) < 0 )
274 /* Negative value is '-' flag plus absolute value */
275 status->flags |= E_minus;
283 /* If a width is given, strtol() will return its value. If not given,
284 strtol() will return zero. In both cases, endptr will point to the
285 rest of the conversion specifier - just what we need.
287 status->width = (int)strtol( spec, (char**)&spec, 10 );
290 /* Optional precision */
296 /* Retrieve precision value from argument stack. A negative value
297 is as if no precision is given - as precision is initalized to
298 EOF (negative), there is no need for testing for negative here.
300 status->prec = va_arg( status->arg, int );
305 status->prec = (int)strtol( spec, &endptr, 10 );
306 if ( spec == endptr )
308 /* Decimal point but no number - bad conversion specifier. */
313 /* Having a precision cancels out any zero flag. */
314 status->flags ^= E_zero;
317 /* Optional length modifier
318 We step one character ahead in any case, and step back only if we find
319 there has been no length modifier (or step ahead another character if it
320 has been "hh" or "ll").
328 status->flags |= E_char;
334 status->flags |= E_short;
340 /* ll -> long long */
341 status->flags |= E_llong;
347 status->flags |= E_long;
351 /* j -> intmax_t, which might or might not be long long */
352 status->flags |= E_intmax;
355 /* z -> size_t, which might or might not be unsigned int */
356 status->flags |= E_size;
359 /* t -> ptrdiff_t, which might or might not be long */
360 status->flags |= E_ptrdiff;
363 /* L -> long double */
364 status->flags |= E_ldouble;
371 /* Conversion specifier */
381 status->flags |= E_unsigned;
385 status->flags |= E_unsigned;
389 status->flags |= ( E_lower | E_unsigned );
393 status->flags |= E_unsigned;
406 /* TODO: Flags, wide chars. */
407 DELIVER( va_arg( status->arg, int ) );
410 /* TODO: Flags, wide chars. */
412 char * s = va_arg( status->arg, char * );
420 /* TODO: E_long -> E_intptr */
422 status->flags |= ( E_lower | E_unsigned | E_alt | E_long );
426 int * val = va_arg( status->arg, int * );
431 /* No conversion specifier. Bad conversion. */
435 /* Do the actual output based on our findings */
436 if ( status->base != 0 )
438 /* Integer conversions */
439 /* TODO: Check for invalid flag combinations. */
440 if ( status->flags & E_unsigned )
443 switch ( status->flags & ( E_char | E_short | E_long | E_llong | E_size ) )
446 value = (uintmax_t)(unsigned char)va_arg( status->arg, int );
449 value = (uintmax_t)(unsigned short)va_arg( status->arg, int );
452 value = (uintmax_t)va_arg( status->arg, unsigned int );
455 value = (uintmax_t)va_arg( status->arg, unsigned long );
458 value = (uintmax_t)va_arg( status->arg, unsigned long long );
461 value = (uintmax_t)va_arg( status->arg, size_t );
465 if ( ( value / status->base ) != 0 )
467 int2base( (intmax_t)(value / status->base), status );
469 int digit = value % status->base;
474 if ( status->flags & E_lower )
476 DELIVER( _PDCLIB_digits[ digit ] );
480 DELIVER( _PDCLIB_Xdigits[ digit ] );
485 switch ( status->flags & ( E_char | E_short | E_long | E_llong | E_intmax ) )
488 int2base( (intmax_t)(char)va_arg( status->arg, int ), status );
491 int2base( (intmax_t)(short)va_arg( status->arg, int ), status );
494 int2base( (intmax_t)va_arg( status->arg, int ), status );
497 int2base( (intmax_t)va_arg( status->arg, long ), status );
500 int2base( (intmax_t)va_arg( status->arg, long long ), status );
503 int2base( (intmax_t)va_arg( status->arg, ptrdiff_t ), status );
506 int2base( va_arg( status->arg, intmax_t ), status );
510 if ( status->flags & E_minus )
512 while ( status->this < status->width )
518 if ( status->i >= status->n )
520 status->s[status->n - 1] = '\0';
527 #include <_PDCLIB_test.h>
532 static int testprintf( char * buffer, size_t n, const char * format, ... )
534 /* Members: base, flags, n, i, this, s, width, prec, stream, arg */
535 struct _PDCLIB_status_t status = { 0, 0, n, 0, 0, buffer, 0, 0, NULL, NULL };
536 memset( buffer, '\0', 100 );
537 va_start( status.arg, format );
538 if ( *(_PDCLIB_print( format, &status )) != '\0' )
540 printf( "_PDCLIB_print() did not return end-of-specifier on '%s'.\n", format );
543 va_end( status.arg );
550 TESTCASE( testprintf( buffer, 100, "%hhd", CHAR_MIN ) == 4 );
551 TESTCASE( strcmp( buffer, "-128" ) == 0 );
552 TESTCASE( testprintf( buffer, 100, "%hhd", CHAR_MAX ) == 3 );
553 TESTCASE( strcmp( buffer, "127" ) == 0 );
554 TESTCASE( testprintf( buffer, 100, "%hhd", 0 ) == 1 );
555 TESTCASE( strcmp( buffer, "0" ) == 0 );
556 TESTCASE( testprintf( buffer, 100, "%hd", SHRT_MIN ) == 6 );
557 TESTCASE( strcmp( buffer, "-32768" ) == 0 );
558 TESTCASE( testprintf( buffer, 100, "%hd", SHRT_MAX ) == 5 );
559 TESTCASE( strcmp( buffer, "32767" ) == 0 );
560 TESTCASE( testprintf( buffer, 100, "%hd", 0 ) == 1 );
561 TESTCASE( strcmp( buffer, "0" ) == 0 );
562 TESTCASE( testprintf( buffer, 100, "%d", INT_MIN ) == 11 );
563 TESTCASE( strcmp( buffer, "-2147483648" ) == 0 );
564 TESTCASE( testprintf( buffer, 100, "%d", INT_MAX ) == 10 );
565 TESTCASE( strcmp( buffer, "2147483647" ) == 0 );
566 TESTCASE( testprintf( buffer, 100, "%d", 0 ) == 1 );
567 TESTCASE( strcmp( buffer, "0" ) == 0 );
568 TESTCASE( testprintf( buffer, 100, "%ld", LONG_MIN ) == 11 );
569 TESTCASE( strcmp( buffer, "-2147483648" ) == 0 );
570 TESTCASE( testprintf( buffer, 100, "%ld", LONG_MAX ) == 10 );
571 TESTCASE( strcmp( buffer, "2147483647" ) == 0 );
572 TESTCASE( testprintf( buffer, 100, "%ld", 0l ) == 1 );
573 TESTCASE( strcmp( buffer, "0" ) == 0 );
574 TESTCASE( testprintf( buffer, 100, "%lld", LLONG_MIN ) == 20 );
575 TESTCASE( strcmp( buffer, "-9223372036854775808" ) == 0 );
576 TESTCASE( testprintf( buffer, 100, "%lld", LLONG_MAX ) == 19 );
577 TESTCASE( strcmp( buffer, "9223372036854775807" ) == 0 );
578 TESTCASE( testprintf( buffer, 100, "%lld", 0ll ) );
579 TESTCASE( strcmp( buffer, "0" ) == 0 );
580 TESTCASE( testprintf( buffer, 100, "%hhu", UCHAR_MAX ) == 3 );
581 TESTCASE( strcmp( buffer, "255" ) == 0 );
582 TESTCASE( testprintf( buffer, 100, "%hhu", (unsigned char)-1 ) == 3 );
583 TESTCASE( strcmp( buffer, "255" ) == 0 );
584 TESTCASE( testprintf( buffer, 100, "%hu", USHRT_MAX ) == 5 );
585 TESTCASE( strcmp( buffer, "65535" ) == 0 );
586 TESTCASE( testprintf( buffer, 100, "%hu", (unsigned short)-1 ) == 5 );
587 TESTCASE( strcmp( buffer, "65535" ) == 0 );
588 TESTCASE( testprintf( buffer, 100, "%u", UINT_MAX ) == 10 );
589 TESTCASE( strcmp( buffer, "4294967295" ) == 0 );
590 TESTCASE( testprintf( buffer, 100, "%u", -1u ) == 10 );
591 TESTCASE( strcmp( buffer, "4294967295" ) == 0 );
592 TESTCASE( testprintf( buffer, 100, "%lu", ULONG_MAX ) == 10 );
593 TESTCASE( strcmp( buffer, "4294967295" ) == 0 );
594 TESTCASE( testprintf( buffer, 100, "%lu", -1ul ) == 10 );
595 TESTCASE( strcmp( buffer, "4294967295" ) == 0 );
596 TESTCASE( testprintf( buffer, 100, "%llu", ULLONG_MAX ) == 20 );
597 TESTCASE( strcmp( buffer, "18446744073709551615" ) == 0 );
598 TESTCASE( testprintf( buffer, 100, "%llu", -1ull ) == 20 );
599 TESTCASE( strcmp( buffer, "18446744073709551615" ) == 0 );
600 TESTCASE( testprintf( buffer, 100, "%X", UINT_MAX ) == 8 );
601 TESTCASE( strcmp( buffer, "FFFFFFFF" ) == 0 );
602 TESTCASE( testprintf( buffer, 100, "%#X", -1u ) == 10 );
603 TESTCASE( strcmp( buffer, "0XFFFFFFFF" ) == 0 );
604 TESTCASE( testprintf( buffer, 100, "%x", UINT_MAX ) == 8 );
605 TESTCASE( strcmp( buffer, "ffffffff" ) == 0 );
606 TESTCASE( testprintf( buffer, 100, "%#x", -1u ) == 10 );
607 TESTCASE( strcmp( buffer, "0xffffffff" ) == 0 );
608 TESTCASE( testprintf( buffer, 100, "%o", UINT_MAX ) == 11 );
609 TESTCASE( strcmp( buffer, "37777777777" ) == 0 );
610 TESTCASE( testprintf( buffer, 100, "%#o", -1u ) == 12 );
611 TESTCASE( strcmp( buffer, "037777777777" ) == 0 );
612 TESTCASE( testprintf( buffer, 100, "%+d", INT_MIN ) == 11 );
613 TESTCASE( strcmp( buffer, "-2147483648" ) == 0 );
614 TESTCASE( testprintf( buffer, 100, "%+d", INT_MAX ) == 11 );
615 TESTCASE( strcmp( buffer, "+2147483647" ) == 0 );
616 TESTCASE( testprintf( buffer, 100, "%+d", 0 ) == 2 );
617 TESTCASE( strcmp( buffer, "+0" ) == 0 );
618 TESTCASE( testprintf( buffer, 100, "%+u", UINT_MAX ) == 10 );
619 TESTCASE( strcmp( buffer, "4294967295" ) == 0 );
620 TESTCASE( testprintf( buffer, 100, "%+u", -1u ) == 10 );
621 TESTCASE( strcmp( buffer, "4294967295" ) == 0 );
622 TESTCASE( testprintf( buffer, 100, "% d", INT_MIN ) == 11 );
623 TESTCASE( strcmp( buffer, "-2147483648" ) == 0 );
624 TESTCASE( testprintf( buffer, 100, "% d", INT_MAX ) == 11 );
625 TESTCASE( strcmp( buffer, " 2147483647" ) == 0 );
626 TESTCASE( testprintf( buffer, 100, "% d", 0 ) == 2 );
627 TESTCASE( strcmp( buffer, " 0" ) == 0 );
628 TESTCASE( testprintf( buffer, 100, "% u", UINT_MAX ) == 10 );
629 TESTCASE( strcmp( buffer, "4294967295" ) == 0 );
630 TESTCASE( testprintf( buffer, 100, "% u", -1u ) == 10 );
631 TESTCASE( strcmp( buffer, "4294967295" ) == 0 );
632 TESTCASE( testprintf( buffer, 100, "%9d", INT_MIN ) == 11 );
633 TESTCASE( strcmp( buffer, "-2147483648" ) == 0 );
634 TESTCASE( testprintf( buffer, 100, "%9d", INT_MAX ) == 10 );
635 TESTCASE( strcmp( buffer, "2147483647" ) == 0 );
636 TESTCASE( testprintf( buffer, 100, "%10d", INT_MIN ) == 11 );
637 TESTCASE( strcmp( buffer, "-2147483648" ) == 0 );
638 TESTCASE( testprintf( buffer, 100, "%10d", INT_MAX ) == 10 );
639 TESTCASE( strcmp( buffer, "2147483647" ) == 0 );
640 TESTCASE( testprintf( buffer, 100, "%11d", INT_MIN ) == 11 );
641 TESTCASE( strcmp( buffer, "-2147483648" ) == 0 );
642 TESTCASE( testprintf( buffer, 100, "%11d", INT_MAX ) == 11 );
643 TESTCASE( strcmp( buffer, " 2147483647" ) == 0 );
644 TESTCASE( testprintf( buffer, 100, "%12d", INT_MIN ) == 12 );
645 TESTCASE( strcmp( buffer, " -2147483648" ) == 0 );
646 TESTCASE( testprintf( buffer, 100, "%12d", INT_MAX ) == 12 );
647 TESTCASE( strcmp( buffer, " 2147483647" ) == 0 );
648 TESTCASE( testprintf( buffer, 100, "%-9d", INT_MIN ) == 11 );
649 TESTCASE( strcmp( buffer, "-2147483648" ) == 0 );
650 TESTCASE( testprintf( buffer, 100, "%-9d", INT_MAX ) == 10 );
651 TESTCASE( strcmp( buffer, "2147483647" ) == 0 );
652 TESTCASE( testprintf( buffer, 100, "%-10d", INT_MIN ) == 11 );
653 TESTCASE( strcmp( buffer, "-2147483648" ) == 0 );
654 TESTCASE( testprintf( buffer, 100, "%-10d", INT_MAX ) == 10 );
655 TESTCASE( strcmp( buffer, "2147483647" ) == 0 );
656 TESTCASE( testprintf( buffer, 100, "%-11d", INT_MIN ) == 11 );
657 TESTCASE( strcmp( buffer, "-2147483648" ) == 0 );
658 TESTCASE( testprintf( buffer, 100, "%-11d", INT_MAX ) == 11 );
659 TESTCASE( strcmp( buffer, "2147483647 " ) == 0 );
660 TESTCASE( testprintf( buffer, 100, "%-12d", INT_MIN ) == 12 );
661 TESTCASE( strcmp( buffer, "-2147483648 " ) == 0 );
662 TESTCASE( testprintf( buffer, 100, "%-12d", INT_MAX ) == 12 );
663 TESTCASE( strcmp( buffer, "2147483647 " ) == 0 );
664 TESTCASE( testprintf( buffer, 100, "%09d", INT_MIN ) == 11 );
665 TESTCASE( strcmp( buffer, "-2147483648" ) == 0 );
666 TESTCASE( testprintf( buffer, 100, "%09d", INT_MAX ) == 10 );
667 TESTCASE( strcmp( buffer, "2147483647" ) == 0 );
668 TESTCASE( testprintf( buffer, 100, "%010d", INT_MIN ) == 11 );
669 TESTCASE( strcmp( buffer, "-2147483648" ) == 0 );
670 TESTCASE( testprintf( buffer, 100, "%010d", INT_MAX ) == 10 );
671 TESTCASE( strcmp( buffer, "2147483647" ) == 0 );
672 TESTCASE( testprintf( buffer, 100, "%011d", INT_MIN ) == 11 );
673 TESTCASE( strcmp( buffer, "-2147483648" ) == 0 );
674 TESTCASE( testprintf( buffer, 100, "%011d", INT_MAX ) == 11 );
675 TESTCASE( strcmp( buffer, "02147483647" ) == 0 );
676 TESTCASE( testprintf( buffer, 100, "%012d", INT_MIN ) == 12 );
677 TESTCASE( strcmp( buffer, "-02147483648" ) == 0 );
678 TESTCASE( testprintf( buffer, 100, "%012d", INT_MAX ) == 12 );
679 TESTCASE( strcmp( buffer, "002147483647" ) == 0 );
680 TESTCASE( testprintf( buffer, 100, "%-09d", INT_MIN ) == 11 );
681 TESTCASE( strcmp( buffer, "-2147483648" ) == 0 );
682 TESTCASE( testprintf( buffer, 100, "%-09d", INT_MAX ) == 10 );
683 TESTCASE( strcmp( buffer, "2147483647" ) == 0 );
684 TESTCASE( testprintf( buffer, 100, "%-010d", INT_MIN ) == 11 );
685 TESTCASE( strcmp( buffer, "-2147483648" ) == 0 );
686 TESTCASE( testprintf( buffer, 100, "%-010d", INT_MAX ) == 10 );
687 TESTCASE( strcmp( buffer, "2147483647" ) == 0 );
688 TESTCASE( testprintf( buffer, 100, "%-011d", INT_MIN ) == 11 );
689 TESTCASE( strcmp( buffer, "-2147483648" ) == 0 );
690 TESTCASE( testprintf( buffer, 100, "%-011d", INT_MAX ) == 11 );
691 TESTCASE( strcmp( buffer, "2147483647 " ) == 0 );
692 TESTCASE( testprintf( buffer, 100, "%-012d", INT_MIN ) == 12 );
693 TESTCASE( strcmp( buffer, "-2147483648 " ) == 0 );
694 TESTCASE( testprintf( buffer, 100, "%-012d", INT_MAX ) == 12 );
695 TESTCASE( strcmp( buffer, "2147483647 " ) == 0 );
696 TESTCASE( testprintf( buffer, 8, "%9d", INT_MAX ) == 10 );
697 TESTCASE( strcmp( buffer, "2147483" ) == 0 );
698 TESTCASE( testprintf( buffer, 8, "%9d", INT_MIN ) == 11 );
699 TESTCASE( strcmp( buffer, "-214748" ) == 0 );
700 TESTCASE( testprintf( buffer, 9, "%9d", INT_MAX ) == 10 );
701 TESTCASE( strcmp( buffer, "21474836" ) == 0 );
702 TESTCASE( testprintf( buffer, 9, "%9d", INT_MIN ) == 11 );
703 TESTCASE( strcmp( buffer, "-2147483" ) == 0 );
704 TESTCASE( testprintf( buffer, 10, "%9d", INT_MAX ) == 10 );
705 TESTCASE( strcmp( buffer, "214748364" ) == 0 );
706 TESTCASE( testprintf( buffer, 10, "%9d", INT_MIN ) == 11 );
707 TESTCASE( strcmp( buffer, "-21474836" ) == 0 );
708 TESTCASE( testprintf( buffer, 9, "%10d", INT_MAX ) == 10 );
709 TESTCASE( strcmp( buffer, "21474836" ) == 0 );
710 TESTCASE( testprintf( buffer, 9, "%10d", INT_MIN ) == 11 );
711 TESTCASE( strcmp( buffer, "-2147483" ) == 0 );
712 TESTCASE( testprintf( buffer, 10, "%10d", INT_MAX ) == 10 );
713 TESTCASE( strcmp( buffer, "214748364" ) == 0 );
714 TESTCASE( testprintf( buffer, 10, "%10d", INT_MIN ) == 11 );
715 TESTCASE( strcmp( buffer, "-21474836" ) == 0 );
716 TESTCASE( testprintf( buffer, 11, "%10d", INT_MAX ) == 10 );
717 TESTCASE( strcmp( buffer, "2147483647" ) == 0 );
718 TESTCASE( testprintf( buffer, 11, "%10d", INT_MIN ) == 11 );
719 TESTCASE( strcmp( buffer, "-214748364" ) == 0 );
720 TESTCASE( testprintf( buffer, 10, "%11d", INT_MAX ) == 11 );
721 TESTCASE( strcmp( buffer, " 21474836" ) == 0 );
722 TESTCASE( testprintf( buffer, 10, "%11d", INT_MIN ) == 11 );
723 TESTCASE( strcmp( buffer, "-21474836" ) == 0 );
724 TESTCASE( testprintf( buffer, 11, "%11d", INT_MAX ) == 11 );
725 TESTCASE( strcmp( buffer, " 214748364" ) == 0 );
726 TESTCASE( testprintf( buffer, 11, "%11d", INT_MIN ) == 11 );
727 TESTCASE( strcmp( buffer, "-214748364" ) == 0 );
728 TESTCASE( testprintf( buffer, 12, "%11d", INT_MAX ) == 11 );
729 TESTCASE( strcmp( buffer, " 2147483647" ) == 0 );
730 TESTCASE( testprintf( buffer, 12, "%11d", INT_MIN ) == 11 );
731 TESTCASE( strcmp( buffer, "-2147483648" ) == 0 );
732 TESTCASE( testprintf( buffer, 11, "%12d", INT_MAX ) == 12 );
733 TESTCASE( strcmp( buffer, " 21474836" ) == 0 );
734 TESTCASE( testprintf( buffer, 11, "%12d", INT_MIN ) == 12 );
735 TESTCASE( strcmp( buffer, " -21474836" ) == 0 );
736 TESTCASE( testprintf( buffer, 12, "%12d", INT_MAX ) == 12 );
737 TESTCASE( strcmp( buffer, " 214748364" ) == 0 );
738 TESTCASE( testprintf( buffer, 12, "%12d", INT_MIN ) == 12 );
739 TESTCASE( strcmp( buffer, " -214748364" ) == 0 );
740 TESTCASE( testprintf( buffer, 13, "%12d", INT_MAX ) == 12 );
741 TESTCASE( strcmp( buffer, " 2147483647" ) == 0 );
742 TESTCASE( testprintf( buffer, 13, "%12d", INT_MIN ) == 12 );
743 TESTCASE( strcmp( buffer, " -2147483648" ) == 0 );
744 TESTCASE( testprintf( buffer, 100, "%030.20d", INT_MAX ) == 30 );
745 TESTCASE( strcmp( buffer, " 00000000002147483647" ) == 0 );
746 TESTCASE( testprintf( buffer, 100, "%.6x", UINT_MAX ) == 8 );
747 TESTCASE( strcmp( buffer, "ffffffff" ) == 0 );
748 TESTCASE( testprintf( buffer, 100, "%#6.3x", UINT_MAX ) == 10 );
749 TESTCASE( strcmp( buffer, "0xffffffff" ) == 0 );
750 TESTCASE( testprintf( buffer, 100, "%#3.6x", UINT_MAX ) == 10 );
751 TESTCASE( strcmp( buffer, "0xffffffff" ) == 0 );
752 TESTCASE( testprintf( buffer, 100, "%.6d", INT_MIN ) == 11 );
753 TESTCASE( strcmp( buffer, "-2147483648" ) == 0 );
754 TESTCASE( testprintf( buffer, 100, "%6.3d", INT_MIN ) == 11 );
755 TESTCASE( strcmp( buffer, "-2147483648" ) == 0 );
756 TESTCASE( testprintf( buffer, 100, "%3.6d", INT_MIN ) == 11 );
757 TESTCASE( strcmp( buffer, "-2147483648" ) == 0 );
758 TESTCASE( testprintf( buffer, 100, "%#0.6x", UINT_MAX ) == 10 );
759 TESTCASE( strcmp( buffer, "0xffffffff" ) == 0 );
760 TESTCASE( testprintf( buffer, 100, "%#06.3x", UINT_MAX ) == 10 );
761 TESTCASE( strcmp( buffer, "0xffffffff" ) == 0 );
762 TESTCASE( testprintf( buffer, 100, "%#03.6x", UINT_MAX ) == 10 );
763 TESTCASE( strcmp( buffer, "0xffffffff" ) == 0 );
764 TESTCASE( testprintf( buffer, 100, "%#0.6d", INT_MAX ) == 10 );
765 TESTCASE( strcmp( buffer, "2147483647" ) == 0 );
766 TESTCASE( testprintf( buffer, 100, "%#06.3d", INT_MAX ) == 10 );
767 TESTCASE( strcmp( buffer, "2147483647" ) == 0 );
768 TESTCASE( testprintf( buffer, 100, "%#03.6d", INT_MAX ) == 10 );
769 TESTCASE( strcmp( buffer, "2147483647" ) == 0 );
770 TESTCASE( testprintf( buffer, 100, "%#+.6d", INT_MAX ) == 11 );
771 TESTCASE( strcmp( buffer, "+2147483647" ) == 0 );
772 TESTCASE( testprintf( buffer, 100, "%#+6.3d", INT_MAX ) == 11 );
773 TESTCASE( strcmp( buffer, "+2147483647" ) == 0 );
774 TESTCASE( testprintf( buffer, 100, "%#+3.6d", INT_MAX ) == 11 );
775 TESTCASE( strcmp( buffer, "+2147483647" ) == 0 );
776 TESTCASE( testprintf( buffer, 100, "%+0.6d", INT_MAX ) == 11 );
777 TESTCASE( strcmp( buffer, "+2147483647" ) == 0 );
778 TESTCASE( testprintf( buffer, 100, "%+06.3d", INT_MAX ) == 11 );
779 TESTCASE( strcmp( buffer, "+2147483647" ) == 0 );
780 TESTCASE( testprintf( buffer, 100, "%+03.6d", INT_MAX ) == 11 );
781 TESTCASE( strcmp( buffer, "+2147483647" ) == 0 );
782 TESTCASE( testprintf( buffer, 100, "%c", 'x' ) == 1 );
783 TESTCASE( strcmp( buffer, "x" ) == 0 );
784 TESTCASE( testprintf( buffer, 100, "%s", "abcdef" ) == 6 );
785 TESTCASE( strcmp( buffer, "abcdef" ) == 0 );
786 TESTCASE( testprintf( buffer, 100, "%p", (void *)0xdeadbeef ) == 10 );
787 TESTCASE( strcmp( buffer, "0xdeadbeef" ) == 0 );