287 #define PORTABLE_SNPRINTF_VERSION_MAJOR 2 288 #define PORTABLE_SNPRINTF_VERSION_MINOR 2 290 #if defined(NEED_ASPRINTF) || defined(NEED_ASNPRINTF) || defined(NEED_VASPRINTF) || defined(NEED_VASNPRINTF) 291 # if defined(NEED_SNPRINTF_ONLY) 292 # undef NEED_SNPRINTF_ONLY 294 # if !defined(PREFER_PORTABLE_SNPRINTF) 295 # define PREFER_PORTABLE_SNPRINTF 299 #if defined(SOLARIS_BUG_COMPATIBLE) && !defined(SOLARIS_COMPATIBLE) 300 #define SOLARIS_COMPATIBLE 303 #if defined(HPUX_BUG_COMPATIBLE) && !defined(HPUX_COMPATIBLE) 304 #define HPUX_COMPATIBLE 307 #if defined(DIGITAL_UNIX_BUG_COMPATIBLE) && !defined(DIGITAL_UNIX_COMPATIBLE) 308 #define DIGITAL_UNIX_COMPATIBLE 311 #if defined(PERL_BUG_COMPATIBLE) && !defined(PERL_COMPATIBLE) 312 #define PERL_COMPATIBLE 315 #if defined(LINUX_BUG_COMPATIBLE) && !defined(LINUX_COMPATIBLE) 316 #define LINUX_COMPATIBLE 319 #include <sys/types.h> 330 #define isdigit(c) ((c) >= '0' && (c) <= '9') 342 #if defined(__alpha__) || defined(__alpha) 343 # define breakeven_point 2 345 #if defined(__i386__) || defined(__i386) 346 # define breakeven_point 12 349 # define breakeven_point 10 351 #if defined(__sparc__) || defined(__sparc) 352 # define breakeven_point 33 359 #ifndef breakeven_point 360 # define breakeven_point 6 363 #define fast_memcpy(d,s,n) \ 364 { register size_t nn = (size_t)(n); \ 365 if (nn >= breakeven_point) memcpy((d), (s), nn); \ 367 register char *dd; register const char *ss; \ 368 for (ss=(s), dd=(d); nn>0; nn--) *dd++ = *ss++; } } 370 #define fast_memset(d,c,n) \ 371 { register size_t nn = (size_t)(n); \ 372 if (nn >= breakeven_point) memset((d), (int)(c), nn); \ 374 register char *dd; register const int cc=(int)(c); \ 375 for (dd=(d); nn>0; nn--) *dd++ = cc; } } 379 #if defined(NEED_ASPRINTF) 380 int asprintf (
char **ptr,
const char *fmt, ...);
382 #if defined(NEED_VASPRINTF) 383 int vasprintf (
char **ptr,
const char *fmt, va_list ap);
385 #if defined(NEED_ASNPRINTF) 386 int asnprintf (
char **ptr,
size_t str_m,
const char *fmt, ...);
388 #if defined(NEED_VASNPRINTF) 389 int vasnprintf (
char **ptr,
size_t str_m,
const char *fmt, va_list ap);
392 #if defined(HAVE_SNPRINTF) 397 #define portable_snprintf snprintf 398 #if !defined(NEED_SNPRINTF_ONLY) 399 #define portable_vsnprintf vsnprintf 403 #if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF) 405 #if !defined(NEED_SNPRINTF_ONLY) 413 @(#)snprintf.c, v2.2: Mark Martinec, <mark.martinec@ijs.si>\n\ 414 @(#)snprintf.c, v2.2: Copyright 1999, Mark Martinec. Frontier Artistic License applies.\n\ 415 @(#)snprintf.c, v2.2: http://www.ijs.si/software/snprintf/\n";
417 #if defined(NEED_ASPRINTF) 418 int asprintf(
char **ptr,
const char *fmt, ...) {
428 *ptr = (
char *) malloc(str_m = (
size_t)str_l + 1);
429 if (*ptr == NULL) { errno = ENOMEM; str_l = -1; }
435 assert(str_l2 == str_l);
441 #if defined(NEED_VASPRINTF) 442 int vasprintf(
char **ptr,
const char *fmt, va_list ap) {
453 *ptr = (
char *) malloc(str_m = (
size_t)str_l + 1);
454 if (*ptr == NULL) { errno = ENOMEM; str_l = -1; }
457 assert(str_l2 == str_l);
463 #if defined(NEED_ASNPRINTF) 464 int asnprintf (
char **ptr,
size_t str_m,
const char *fmt, ...) {
473 if ((
size_t)str_l + 1 < str_m) str_m = (size_t)str_l + 1;
477 *ptr = (
char *) malloc(str_m);
478 if (*ptr == NULL) { errno = ENOMEM; str_l = -1; }
484 assert(str_l2 == str_l);
491 #if defined(NEED_VASNPRINTF) 492 int vasnprintf (
char **ptr,
size_t str_m,
const char *fmt, va_list ap) {
502 if ((
size_t)str_l + 1 < str_m) str_m = (size_t)str_l + 1;
506 *ptr = (
char *) malloc(str_m);
507 if (*ptr == NULL) { errno = ENOMEM; str_l = -1; }
510 assert(str_l2 == str_l);
521 #if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF) 523 #if !defined(NEED_SNPRINTF_ONLY) 535 #if defined(NEED_SNPRINTF_ONLY) 541 #if defined(NEED_SNPRINTF_ONLY) 551 #if defined(NEED_SNPRINTF_ONLY) 560 const char *q = strchr(p+1,
'%');
561 size_t n = !q ? strlen(p) : (q-p);
563 size_t avail = str_m-str_l;
568 const char *starting_p;
569 size_t min_field_width = 0, precision = 0;
570 int zero_padding = 0, precision_specified = 0, justify_left = 0;
571 int alternate_form = 0, force_sign = 0;
572 int space_for_positive = 1;
574 char length_modifier =
'\0';
580 unsigned char uchar_arg;
585 size_t number_of_zeros_to_pad = 0;
589 size_t zero_padding_insertion_ind = 0;
592 char fmt_spec =
'\0';
599 while (*p ==
'0' || *p ==
'-' || *p ==
'+' ||
600 *p ==
' ' || *p ==
'#' || *p ==
'\'') {
602 case '0': zero_padding = 1;
break;
603 case '-': justify_left = 1;
break;
604 case '+': force_sign = 1; space_for_positive = 0;
break;
605 case ' ': force_sign = 1;
607 #ifdef PERL_COMPATIBLE 609 space_for_positive = 1;
612 case '#': alternate_form = 1;
break;
622 p++; j = va_arg(ap,
int);
623 if (j >= 0) min_field_width = j;
624 else { min_field_width = -j; justify_left = 1; }
625 }
else if (
isdigit((
int)(*p))) {
628 unsigned int uj = *p++ -
'0';
629 while (
isdigit((
int)(*p))) uj = 10*uj + (
unsigned int)(*p++ -
'0');
630 min_field_width = uj;
634 p++; precision_specified = 1;
636 int j = va_arg(ap,
int);
638 if (j >= 0) precision = j;
640 precision_specified = 0; precision = 0;
648 }
else if (
isdigit((
int)(*p))) {
651 unsigned int uj = *p++ -
'0';
652 while (
isdigit((
int)(*p))) uj = 10*uj + (
unsigned int)(*p++ -
'0');
657 if (*p ==
'h' || *p ==
'l') {
658 length_modifier = *p; p++;
659 if (length_modifier ==
'l' && *p ==
'l') {
660 #ifdef SNPRINTF_LONGLONG_SUPPORT 661 length_modifier =
'2';
663 length_modifier =
'l';
671 case 'i': fmt_spec =
'd';
break;
672 case 'D': fmt_spec =
'd'; length_modifier =
'l';
break;
673 case 'U': fmt_spec =
'u'; length_modifier =
'l';
break;
674 case 'O': fmt_spec =
'o'; length_modifier =
'l';
break;
682 length_modifier =
'\0';
686 #if !defined(SOLARIS_COMPATIBLE) && !defined(HPUX_COMPATIBLE) 694 int j = va_arg(ap,
int);
695 uchar_arg = (
unsigned char) j;
696 str_arg = (
const char *) &uchar_arg;
700 str_arg = va_arg(ap,
const char *);
701 if (!str_arg) str_arg_l = 0;
703 else if (!precision_specified) str_arg_l = strlen(str_arg);
705 else if (precision == 0) str_arg_l = 0;
708 const char *q = (
const char*)(memchr(str_arg,
'\0',
709 precision <= 0x7fffffff ? precision : 0x7fffffff));
710 str_arg_l = !q ? precision : (q-str_arg);
716 case 'd':
case 'u':
case 'o':
case 'x':
case 'X':
case 'p': {
725 int int_arg = 0;
unsigned int uint_arg = 0;
728 long int long_arg = 0;
unsigned long int ulong_arg = 0;
731 void *ptr_arg = NULL;
734 #ifdef SNPRINTF_LONGLONG_SUPPORT 735 long long int long_long_arg = 0;
736 unsigned long long int ulong_long_arg = 0;
739 if (fmt_spec ==
'p') {
750 #ifdef SOLARIS_COMPATIBLE 751 # ifdef SOLARIS_BUG_COMPATIBLE 754 if (length_modifier ==
'2') length_modifier =
'\0';
757 length_modifier =
'\0';
759 ptr_arg = va_arg(ap,
void *);
760 if (ptr_arg != NULL) arg_sign = 1;
761 }
else if (fmt_spec ==
'd') {
762 switch (length_modifier) {
770 int_arg = va_arg(ap,
int);
771 if (int_arg > 0) arg_sign = 1;
772 else if (int_arg < 0) arg_sign = -1;
775 long_arg = va_arg(ap,
long int);
776 if (long_arg > 0) arg_sign = 1;
777 else if (long_arg < 0) arg_sign = -1;
779 #ifdef SNPRINTF_LONGLONG_SUPPORT 781 long_long_arg = va_arg(ap,
long long int);
782 if (long_long_arg > 0) arg_sign = 1;
783 else if (long_long_arg < 0) arg_sign = -1;
788 switch (length_modifier) {
791 uint_arg = va_arg(ap,
unsigned int);
792 if (uint_arg) arg_sign = 1;
795 ulong_arg = va_arg(ap,
unsigned long int);
796 if (ulong_arg) arg_sign = 1;
798 #ifdef SNPRINTF_LONGLONG_SUPPORT 800 ulong_long_arg = va_arg(ap,
unsigned long long int);
801 if (ulong_long_arg) arg_sign = 1;
806 str_arg = tmp; str_arg_l = 0;
812 #ifndef PERL_COMPATIBLE 813 if (precision_specified) zero_padding = 0;
815 if (fmt_spec ==
'd') {
816 if (force_sign && arg_sign >= 0)
817 tmp[str_arg_l++] = space_for_positive ?
' ' :
'+';
820 #ifdef LINUX_COMPATIBLE 821 }
else if (fmt_spec ==
'p' && force_sign && arg_sign > 0) {
822 tmp[str_arg_l++] = space_for_positive ?
' ' :
'+';
824 }
else if (alternate_form) {
825 if (arg_sign != 0 && (fmt_spec ==
'x' || fmt_spec ==
'X') )
826 { tmp[str_arg_l++] =
'0'; tmp[str_arg_l++] = fmt_spec; }
828 #ifdef HPUX_COMPATIBLE 829 else if (fmt_spec ==
'p' 832 #ifndef HPUX_BUG_COMPATIBLE
836 ) { tmp[str_arg_l++] =
'0'; tmp[str_arg_l++] =
'x'; }
839 zero_padding_insertion_ind = str_arg_l;
840 if (!precision_specified) precision = 1;
841 if (precision == 0 && arg_sign == 0
842 #
if defined(HPUX_BUG_COMPATIBLE) || defined(LINUX_COMPATIBLE)
853 char f[5];
int f_l = 0;
855 if (!length_modifier) { }
856 else if (length_modifier==
'2') { f[f_l++] =
'l'; f[f_l++] =
'l'; }
857 else f[f_l++] = length_modifier;
858 f[f_l++] = fmt_spec; f[f_l++] =
'\0';
859 if (fmt_spec ==
'p') str_arg_l += sprintf(tmp+str_arg_l, f, ptr_arg);
860 else if (fmt_spec ==
'd') {
861 switch (length_modifier) {
863 case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, int_arg);
break;
864 case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, long_arg);
break;
865 #ifdef SNPRINTF_LONGLONG_SUPPORT 866 case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,long_long_arg);
break;
870 switch (length_modifier) {
872 case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, uint_arg);
break;
873 case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, ulong_arg);
break;
874 #ifdef SNPRINTF_LONGLONG_SUPPORT 875 case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,ulong_long_arg);
break;
881 if (zero_padding_insertion_ind < str_arg_l &&
882 tmp[zero_padding_insertion_ind] ==
'-') {
883 zero_padding_insertion_ind++;
885 if (zero_padding_insertion_ind+1 < str_arg_l &&
886 tmp[zero_padding_insertion_ind] ==
'0' &&
887 (tmp[zero_padding_insertion_ind+1] ==
'x' ||
888 tmp[zero_padding_insertion_ind+1] ==
'X') ) {
889 zero_padding_insertion_ind += 2;
892 {
size_t num_of_digits = str_arg_l - zero_padding_insertion_ind;
893 if (alternate_form && fmt_spec ==
'o' 894 #ifdef HPUX_COMPATIBLE
897 #ifdef DIGITAL_UNIX_BUG_COMPATIBLE
900 && !(zero_padding_insertion_ind < str_arg_l
901 && tmp[zero_padding_insertion_ind] ==
'0')
904 if (!precision_specified || precision < num_of_digits+1) {
908 precision = num_of_digits+1; precision_specified = 1;
912 if (num_of_digits < precision)
913 number_of_zeros_to_pad = precision - num_of_digits;
916 if (!justify_left && zero_padding) {
917 size_t n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
918 if (n > 0) number_of_zeros_to_pad += n;
924 #ifndef DIGITAL_UNIX_COMPATIBLE 925 justify_left = 1; min_field_width = 0;
927 #if defined(PERL_COMPATIBLE) || defined(LINUX_COMPATIBLE) 929 str_arg = starting_p; str_arg_l = p - starting_p;
935 str_arg = p; str_arg_l = 0;
945 size_t n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
948 size_t avail = str_m-str_l;
949 fast_memset(str+str_l, (zero_padding?
'0':
' '), (n>avail?avail:n));
956 if (number_of_zeros_to_pad <= 0) {
959 zero_padding_insertion_ind = 0;
962 size_t n = zero_padding_insertion_ind;
965 size_t avail = str_m-str_l;
966 fast_memcpy(str+str_l, str_arg, (n>avail?avail:n));
971 n = number_of_zeros_to_pad;
974 size_t avail = str_m-str_l;
982 {
size_t n = str_arg_l - zero_padding_insertion_ind;
985 size_t avail = str_m-str_l;
986 fast_memcpy(str+str_l, str_arg+zero_padding_insertion_ind,
994 size_t n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
997 size_t avail = str_m-str_l;
1005 #if defined(NEED_SNPRINTF_ONLY) 1011 str[str_l <= str_m-1 ? str_l : str_m-1] =
'\0';
#define portable_snprintf
#define fast_memset(d, c, n)
#define fast_memcpy(d, s, n)
#define portable_vsnprintf