~ubuntu-branches/ubuntu/precise/wget/precise-proposed

« back to all changes in this revision

Viewing changes to src/snprintf.c

  • Committer: Bazaar Package Importer
  • Author(s): Noèl Köthe
  • Date: 2005-06-26 16:46:25 UTC
  • mfrom: (1.1.1 upstream) (2.1.1 sarge)
  • Revision ID: james.westby@ubuntu.com-20050626164625-jjcde8hyztx7xq7o
Tags: 1.10-2
* wget-fix_error--save-headers patch from upstream
  (closes: Bug#314728)
* don't pattern-match server redirects patch from upstream
  (closes: Bug#163243)
* correct de.po typos
  (closes: Bug#313883)
* wget-E_html_behind_file_counting fix problem with adding the
  numbers after the html extension
* updated Standards-Version: to 3.6.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
70
70
 *    don't declare argument types to (v)snprintf if stdarg is not used.
71
71
 *    use int instead of short int as 2nd arg to va_arg.
72
72
 *
 
73
 *  alexk (INN) 2002-08-21
 
74
 *    use LLONG in fmtfp to handle more characters during floating
 
75
 *    point conversion.
 
76
 *
 
77
 *  herb (Samba) 2002-12-19
 
78
 *    actually print args for %g and %e
 
79
 *
 
80
 *  Hrvoje Niksic <hniksic@xemacs.org> 2005-04-15
 
81
 *    use the PARAMS macro to handle prototypes.
 
82
 *    write function definitions in the ansi2knr-friendly way.
 
83
 *    if string precision is specified, don't read VALUE past it.
 
84
 *    fix bug in fmtfp that caused 0.01 to be printed as 0.1.
 
85
 *    don't include <ctype.h> because none of it is used.
 
86
 *    interpret precision as number of significant digits with %g
 
87
 *    omit trailing decimal zeros with %g
 
88
 *
73
89
 **************************************************************/
74
90
 
75
91
#ifdef HAVE_CONFIG_H
76
92
# include <config.h>
77
93
#endif
78
94
 
 
95
/* For testing purposes, always compile in the code. */
 
96
#ifdef TEST_SNPRINTF
 
97
# undef HAVE_SNPRINTF
 
98
# undef HAVE_VSNPRINTF
 
99
# ifndef SIZEOF_LONG_LONG
 
100
#  ifdef __GNUC__
 
101
#   define SIZEOF_LONG_LONG 8
 
102
#  endif
 
103
# endif
 
104
#endif
 
105
 
79
106
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
80
107
 
81
 
#include <string.h>
 
108
#ifdef HAVE_STRING_H
 
109
# include <string.h>
 
110
#else
 
111
# include <strings.h>
 
112
#endif
82
113
#include <sys/types.h>
83
114
#include <stdio.h>              /* for NULL */
84
 
#include <safe-ctype.h>
85
115
 
86
116
/* varargs declarations: */
87
117
 
113
143
# define LLONG long
114
144
#endif
115
145
 
 
146
/* If we're running the test suite, rename snprintf and vsnprintf to
 
147
   avoid conflicts with the system version.  */
 
148
#ifdef TEST_SNPRINTF
 
149
# define snprintf test_snprintf
 
150
# define vsnprintf test_vsnprintf
 
151
#endif
 
152
 
116
153
#ifdef HAVE_STDARGS
117
154
int snprintf (char *str, size_t count, const char *fmt, ...);
118
155
int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);
121
158
int vsnprintf ();
122
159
#endif
123
160
 
124
 
static int dopr (char *buffer, size_t maxlen, const char *format, 
125
 
                 va_list args);
126
 
static int fmtstr (char *buffer, size_t *currlen, size_t maxlen,
127
 
                   char *value, int flags, int min, int max);
128
 
static int fmtint (char *buffer, size_t *currlen, size_t maxlen,
129
 
                   LLONG value, int base, int min, int max, int flags);
130
 
static int fmtfp (char *buffer, size_t *currlen, size_t maxlen,
131
 
                  LDOUBLE fvalue, int min, int max, int flags);
132
 
static int dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c );
 
161
#ifndef PARAMS
 
162
# define PARAMS(x) x
 
163
#endif
 
164
 
 
165
static int dopr PARAMS ((char *buffer, size_t maxlen, const char *format, 
 
166
                         va_list args));
 
167
static int fmtstr PARAMS ((char *buffer, size_t *currlen, size_t maxlen,
 
168
                           const char *value, int flags, int min, int max));
 
169
static int fmtint PARAMS ((char *buffer, size_t *currlen, size_t maxlen,
 
170
                           LLONG value, int base, int min, int max, int flags));
 
171
static int fmtfp PARAMS ((char *buffer, size_t *currlen, size_t maxlen,
 
172
                          LDOUBLE fvalue, int min, int max, int flags));
 
173
static int dopr_outch PARAMS ((char *buffer, size_t *currlen, size_t maxlen,
 
174
                               char c));
133
175
 
134
176
/*
135
177
 * dopr(): poor man's version of doprintf
154
196
#define DP_F_ZERO       (1 << 4)
155
197
#define DP_F_UP         (1 << 5)
156
198
#define DP_F_UNSIGNED   (1 << 6)
 
199
#define DP_F_FP_G       (1 << 7)
157
200
 
158
201
/* Conversion Flags */
159
202
#define DP_C_SHORT   1
165
208
#define MAX(p,q) ((p >= q) ? p : q)
166
209
#define MIN(p,q) ((p <= q) ? p : q)
167
210
 
168
 
static int dopr (char *buffer, size_t maxlen, const char *format, va_list args)
 
211
static int
 
212
dopr (char *buffer, size_t maxlen, const char *format, va_list args)
169
213
{
170
214
  char ch;
171
215
  LLONG value;
309
353
      case 'd':
310
354
      case 'i':
311
355
        if (cflags == DP_C_SHORT) 
312
 
          value = (short int)va_arg (args, int);
 
356
          value = (short int) va_arg (args, int);
313
357
        else if (cflags == DP_C_LONG)
314
358
          value = va_arg (args, long int);
315
359
        else if (cflags == DP_C_LLONG)
321
365
      case 'o':
322
366
        flags |= DP_F_UNSIGNED;
323
367
        if (cflags == DP_C_SHORT)
324
 
          value = (unsigned short int)va_arg (args, unsigned int);
 
368
          value = (unsigned short int) va_arg (args, unsigned int);
325
369
        else if (cflags == DP_C_LONG)
326
370
          value = va_arg (args, unsigned long int);
327
371
        else if (cflags == DP_C_LLONG)
333
377
      case 'u':
334
378
        flags |= DP_F_UNSIGNED;
335
379
        if (cflags == DP_C_SHORT)
336
 
          value = (unsigned short int)va_arg (args, unsigned int);
 
380
          value = (unsigned short int) va_arg (args, unsigned int);
337
381
        else if (cflags == DP_C_LONG)
338
382
          value = va_arg (args, unsigned long int);
339
383
        else if (cflags == DP_C_LLONG)
347
391
      case 'x':
348
392
        flags |= DP_F_UNSIGNED;
349
393
        if (cflags == DP_C_SHORT)
350
 
          value = (unsigned short int)va_arg (args, unsigned int);
 
394
          value = (unsigned short int) va_arg (args, unsigned int);
351
395
        else if (cflags == DP_C_LONG)
352
396
          value = va_arg (args, unsigned long int);
353
397
        else if (cflags == DP_C_LLONG)
361
405
          fvalue = va_arg (args, LDOUBLE);
362
406
        else
363
407
          fvalue = va_arg (args, double);
364
 
        /* um, floating point? */
365
408
        total += fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
366
409
        break;
367
410
      case 'E':
371
414
          fvalue = va_arg (args, LDOUBLE);
372
415
        else
373
416
          fvalue = va_arg (args, double);
 
417
        total += fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
374
418
        break;
375
419
      case 'G':
376
420
        flags |= DP_F_UP;
377
421
      case 'g':
 
422
        flags |= DP_F_FP_G;
378
423
        if (cflags == DP_C_LDOUBLE)
379
424
          fvalue = va_arg (args, LDOUBLE);
380
425
        else
381
426
          fvalue = va_arg (args, double);
 
427
        if (max == 0)
 
428
          /* C99 says: if precision [for %g] is zero, it is taken as one */
 
429
          max = 1;
 
430
        total += fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
382
431
        break;
383
432
      case 'c':
384
433
        total += dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
451
500
  return total;
452
501
}
453
502
 
454
 
static int fmtstr (char *buffer, size_t *currlen, size_t maxlen,
455
 
                   char *value, int flags, int min, int max)
 
503
static int
 
504
fmtstr (char *buffer, size_t *currlen, size_t maxlen,
 
505
        const char *value, int flags, int min, int max)
456
506
{
457
507
  int padlen, strln;     /* amount to pad */
458
508
  int cnt = 0;
460
510
  
461
511
  if (value == 0)
462
512
  {
463
 
    value = "<NULL>";
 
513
    value = "(null)";
464
514
  }
465
515
 
466
 
  for (strln = 0; value[strln]; ++strln); /* strlen */
467
 
  if (max >= 0 && max < strln)
468
 
    strln = max;
 
516
  if (max < 0)
 
517
    strln = strlen (value);
 
518
  else
 
519
    /* When precision is specified, don't read VALUE past precision. */
 
520
    /*strln = strnlen (value, max);*/
 
521
    for (strln = 0; strln < max && value[strln]; ++strln);
469
522
  padlen = min - strln;
470
523
  if (padlen < 0) 
471
524
    padlen = 0;
492
545
 
493
546
/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
494
547
 
495
 
static int fmtint (char *buffer, size_t *currlen, size_t maxlen,
496
 
                   LLONG value, int base, int min, int max, int flags)
 
548
static int
 
549
fmtint (char *buffer, size_t *currlen, size_t maxlen,
 
550
        LLONG value, int base, int min, int max, int flags)
497
551
{
498
552
  int signvalue = 0;
499
553
  unsigned LLONG uvalue;
587
641
  return total;
588
642
}
589
643
 
590
 
static LDOUBLE abs_val (LDOUBLE value)
 
644
static LDOUBLE
 
645
abs_val (LDOUBLE value)
591
646
{
592
647
  LDOUBLE result = value;
593
648
 
597
652
  return result;
598
653
}
599
654
 
600
 
static LDOUBLE pow10 (int exp)
 
655
static LDOUBLE
 
656
pow10 (int exp)
601
657
{
602
658
  LDOUBLE result = 1;
603
659
 
610
666
  return result;
611
667
}
612
668
 
613
 
static long round (LDOUBLE value)
 
669
static LLONG
 
670
round (LDOUBLE value)
614
671
{
615
 
  long intpart;
 
672
  LLONG intpart;
616
673
 
617
674
  intpart = value;
618
675
  value = value - intpart;
622
679
  return intpart;
623
680
}
624
681
 
625
 
static int fmtfp (char *buffer, size_t *currlen, size_t maxlen,
626
 
                  LDOUBLE fvalue, int min, int max, int flags)
 
682
static int
 
683
fmtfp (char *buffer, size_t *currlen, size_t maxlen,
 
684
       LDOUBLE fvalue, int min, int max, int flags)
627
685
{
628
686
  int signvalue = 0;
629
687
  LDOUBLE ufvalue;
630
 
  char iconvert[20];
631
 
  char fconvert[20];
 
688
  char iconvert[24];
 
689
  char fconvert[24];
632
690
  int iplace = 0;
633
691
  int fplace = 0;
634
692
  int padlen = 0; /* amount to pad */
635
693
  int zpadlen = 0; 
636
 
  int caps = 0;
637
694
  int total = 0;
638
 
  long intpart;
639
 
  long fracpart;
 
695
  LLONG intpart;
 
696
  LLONG fracpart;
 
697
  LLONG mask10;
 
698
  int leadingfrac0s = 0; /* zeros at the start of fractional part */
 
699
  int omitzeros = 0;
 
700
  int omitcount = 0;
640
701
  
641
702
  /* 
642
703
   * AIX manpage says the default is 0, but Solaris says the default
662
723
 
663
724
  intpart = ufvalue;
664
725
 
 
726
  /* With %g precision is the number of significant digits, which
 
727
     includes the digits in intpart. */
 
728
  if (flags & DP_F_FP_G)
 
729
    {
 
730
      if (intpart != 0)
 
731
        {
 
732
          /* For each digit of INTPART, print one less fractional digit. */
 
733
          LLONG temp = intpart;
 
734
          for (temp = intpart; temp != 0; temp /= 10)
 
735
            --max;
 
736
          if (max < 0)
 
737
            max = 0;
 
738
        }
 
739
      else
 
740
        {
 
741
          /* For each leading 0 in fractional part, print one more
 
742
             fractional digit. */
 
743
          LDOUBLE temp;
 
744
          if (ufvalue != 0)
 
745
            for (temp = ufvalue; temp < 0.1; temp *= 10)
 
746
              ++max;
 
747
        }
 
748
    }
 
749
 
 
750
  /* C99: trailing zeros are removed from the fractional portion of the
 
751
     result unless the # flag is specified */
 
752
  if ((flags & DP_F_FP_G) && !(flags & DP_F_NUM))
 
753
    omitzeros = 1;
 
754
 
 
755
#if SIZEOF_LONG_LONG > 0
 
756
# define MAX_DIGITS 18          /* grok more digits with long long */
 
757
#else
 
758
# define MAX_DIGITS 9           /* just long */
 
759
#endif
 
760
 
665
761
  /* 
666
 
   * Sorry, we only support 9 digits past the decimal because of our 
667
 
   * conversion method
 
762
   * Sorry, we only support several digits past the decimal because of
 
763
   * our conversion method
668
764
   */
669
 
  if (max > 9)
670
 
    max = 9;
 
765
  if (max > MAX_DIGITS)
 
766
    max = MAX_DIGITS;
 
767
 
 
768
  /* Factor of 10 with the needed number of digits, e.g. 1000 for max==3 */
 
769
  mask10 = pow10 (max);
671
770
 
672
771
  /* We "cheat" by converting the fractional part to integer by
673
772
   * multiplying by a factor of 10
674
773
   */
675
 
  fracpart = round ((pow10 (max)) * (ufvalue - intpart));
 
774
  fracpart = round (mask10 * (ufvalue - intpart));
676
775
 
677
 
  if (fracpart >= pow10 (max))
 
776
  if (fracpart >= mask10)
678
777
  {
679
778
    intpart++;
680
 
    fracpart -= pow10 (max);
 
779
    fracpart -= mask10;
681
780
  }
 
781
  else if (fracpart != 0)
 
782
    /* If fracpart has less digits than the 10* mask, we need to
 
783
       manually insert leading 0s.  For example 2.01's fractional part
 
784
       requires one leading zero to distinguish it from 2.1. */
 
785
    while (fracpart < mask10 / 10)
 
786
      {
 
787
        ++leadingfrac0s;
 
788
        mask10 /= 10;
 
789
      }
682
790
 
683
791
#ifdef DEBUG_SNPRINTF
684
792
  dprint (1, (debugfile, "fmtfp: %f =? %d.%d\n", fvalue, intpart, fracpart));
686
794
 
687
795
  /* Convert integer part */
688
796
  do {
689
 
    iconvert[iplace++] =
690
 
      (caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10];
 
797
    iconvert[iplace++] = '0' + intpart % 10;
691
798
    intpart = (intpart / 10);
692
 
  } while(intpart && (iplace < 20));
693
 
  if (iplace == 20) iplace--;
 
799
  } while(intpart && (iplace < sizeof(iconvert)));
 
800
  if (iplace == sizeof(iconvert)) iplace--;
694
801
  iconvert[iplace] = 0;
695
802
 
696
803
  /* Convert fractional part */
697
804
  do {
698
 
    fconvert[fplace++] =
699
 
      (caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10];
 
805
    fconvert[fplace++] = '0' + fracpart % 10;
700
806
    fracpart = (fracpart / 10);
701
 
  } while(fracpart && (fplace < 20));
702
 
  if (fplace == 20) fplace--;
 
807
  } while(fracpart && (fplace < sizeof(fconvert)));
 
808
  while (leadingfrac0s-- > 0 && fplace < sizeof(fconvert))
 
809
    fconvert[fplace++] = '0';
 
810
  if (fplace == sizeof(fconvert)) fplace--;
703
811
  fconvert[fplace] = 0;
 
812
  if (omitzeros)
 
813
    while (omitcount < fplace && fconvert[omitcount] == '0')
 
814
      ++omitcount;
704
815
 
705
816
  /* -1 for decimal point, another -1 if we are printing a sign */
706
 
  padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); 
707
 
  zpadlen = max - fplace;
 
817
  padlen = min - iplace - (max - omitcount) - 1 - ((signvalue) ? 1 : 0);
 
818
  if (!omitzeros)
 
819
    zpadlen = max - fplace;
708
820
  if (zpadlen < 0)
709
821
    zpadlen = 0;
710
822
  if (padlen < 0) 
741
853
   * Decimal point.  This should probably use locale to find the correct
742
854
   * char to print out.
743
855
   */
744
 
  if (max > 0)
 
856
  if (max > 0 && (fplace > omitcount || zpadlen > 0))
745
857
  {
746
858
    total += dopr_outch (buffer, currlen, maxlen, '.');
747
859
 
748
 
    while (fplace > 0) 
 
860
    while (fplace > omitcount) 
749
861
      total += dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
750
862
  }
751
863
 
764
876
  return total;
765
877
}
766
878
 
767
 
static int dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c)
 
879
static int
 
880
dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c)
768
881
{
769
882
  if (*currlen + 1 < maxlen)
770
883
    buffer[(*currlen)++] = c;
772
885
}
773
886
 
774
887
#ifndef HAVE_VSNPRINTF
775
 
int vsnprintf (char *str, size_t count, const char *fmt, va_list args)
 
888
int
 
889
vsnprintf (char *str, size_t count, const char *fmt, va_list args)
776
890
{
777
891
  if (str != NULL)
778
892
    str[0] = 0;
781
895
#endif /* !HAVE_VSNPRINTF */
782
896
 
783
897
#ifndef HAVE_SNPRINTF
784
 
/* VARARGS3 */
785
 
#ifdef HAVE_STDARGS
786
 
int snprintf (char *str,size_t count,const char *fmt,...)
787
 
#else
788
 
int snprintf (va_alist) va_dcl
789
 
#endif
 
898
int
 
899
snprintf (char *str, size_t count,const char *fmt,...)
790
900
{
791
901
#ifndef HAVE_STDARGS
792
902
  char *str;
809
919
 
810
920
#ifdef TEST_SNPRINTF
811
921
 
812
 
#include <stdio.h>
 
922
# ifndef LONG_STRING
 
923
#  define LONG_STRING 1024
 
924
# endif
813
925
 
814
 
#ifndef LONG_STRING
815
 
#define LONG_STRING 1024
816
 
#endif
817
 
int main (void)
 
926
int
 
927
main (void)
818
928
{
819
929
  char buf1[LONG_STRING];
820
930
  char buf2[LONG_STRING];
821
931
  char *fp_fmt[] = {
 
932
    /* %f formats */
 
933
    "%f",
822
934
    "%-1.5f",
823
935
    "%1.5f",
824
936
    "%123.9f",
832
944
    "%3.2f",
833
945
    "%.0f",
834
946
    "%.1f",
 
947
    "%#10.1f",
 
948
#if SIZEOF_LONG_LONG != 0
 
949
    "%.16f",
 
950
    "%18.16f",
 
951
    "%-16.16f",
 
952
#endif
 
953
    /* %g formats */
 
954
    "%g",
 
955
    "%1.5g",
 
956
    "%-1.5g",
 
957
    "%.9g",
 
958
    "%123.9g",
 
959
    "%#123.9g",
 
960
#if SIZEOF_LONG_LONG != 0
 
961
    "%.16g",
 
962
    "%20.16g",
 
963
#endif
835
964
    NULL
836
965
  };
837
966
  double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, 
838
 
    0.9996, 1.996, 4.136, 0};
 
967
                       0.9996, 1.996, 4.136, 0.00205, 0.0001, 321.000009,
 
968
                       0};
839
969
  char *int_fmt[] = {
840
970
    "%-1.5d",
841
971
    "%1.5d",
922
1052
#endif
923
1053
 
924
1054
  printf ("%d tests failed out of %d.\n", fail, num);
 
1055
  return 0;
925
1056
}
926
 
#endif /* SNPRINTF_TEST */
 
1057
#endif /* TEST_SNPRINTF */