source: trunk/third/gettext/lib/vasprintf.c @ 16931

Revision 16931, 4.4 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r16930, which included commits to RCS files with non-trunk default branches.
Line 
1/* Like vsprintf but provides a pointer to malloc'd storage, which must
2   be freed by the caller.
3   Copyright (C) 1994, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
4
5This program is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation; either version 2, or (at your option)
8any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
18
19#ifdef HAVE_CONFIG_H
20# include <config.h>
21#endif
22
23#include <stdio.h>
24#include <string.h>
25#include <stdlib.h>
26
27#if __STDC__
28# include <stdarg.h>
29#else
30# include <varargs.h>
31#endif
32
33#include <math.h>
34
35#ifdef TEST
36int global_total_width;
37#endif
38
39static int
40int_vasprintf (result, format, args)
41     char **result;
42     const char *format;
43     va_list *args;
44{
45  const char *p = format;
46  /* Add one to make sure that it is never zero, which might cause malloc
47     to return NULL.  */
48  int total_width = strlen (format) + 1;
49  va_list ap;
50
51  memcpy (&ap, args, sizeof (va_list));
52
53  while (*p != '\0')
54    {
55      if (*p++ == '%')
56        {
57          while (strchr ("-+ #0", *p))
58            ++p;
59          if (*p == '*')
60            {
61              ++p;
62              total_width += abs (va_arg (ap, int));
63            }
64          else
65            total_width += strtoul (p, (char **) &p, 10);
66          if (*p == '.')
67            {
68              ++p;
69              if (*p == '*')
70                {
71                  ++p;
72                  total_width += abs (va_arg (ap, int));
73                }
74              else
75                total_width += strtoul (p, (char **) &p, 10);
76            }
77          while (strchr ("hlLjtz", *p))
78            ++p;
79          /* Should be big enough for any format specifier except %s
80             and floats.  */
81          total_width += 30;
82          switch (*p)
83            {
84            case 'd':
85            case 'i':
86            case 'o':
87            case 'u':
88            case 'x':
89            case 'X':
90            case 'c':
91              (void) va_arg (ap, int);
92              break;
93            case 'f':
94              {
95                double arg = va_arg (ap, double);
96                if (arg >= 1.0 || arg <= -1.0)
97                  /* Since an ieee double can have an exponent of 307, we'll
98                     make the buffer wide enough to cover the gross case. */
99                  total_width += 307;
100              }
101              break;
102            case 'e':
103            case 'E':
104            case 'g':
105            case 'G':
106              (void) va_arg (ap, double);
107              break;
108            case 's':
109              total_width += strlen (va_arg (ap, char *));
110              break;
111            case 'p':
112            case 'n':
113              (void) va_arg (ap, char *);
114              break;
115            }
116          p++;
117        }
118    }
119#ifdef TEST
120  global_total_width = total_width;
121#endif
122  *result = malloc (total_width);
123  if (*result != NULL)
124    return vsprintf (*result, format, *args);
125  else
126    return 0;
127}
128
129int
130vasprintf (result, format, args)
131     char **result;
132     const char *format;
133     va_list args;
134{
135  return int_vasprintf (result, format, &args);
136}
137
138int
139asprintf
140#if __STDC__
141     (char **result, const char *format, ...)
142#else
143     (result, va_alist)
144     char **result;
145     va_dcl
146#endif
147{
148  va_list args;
149  int done;
150
151#if __STDC__
152  va_start (args, format);
153#else
154  char *format;
155  va_start (args);
156  format = va_arg (args, char *);
157#endif
158  done = vasprintf (result, format, args);
159  va_end (args);
160
161  return done;
162}
163
164/* ========================= test program ========================= */
165
166#ifdef TEST
167
168#include <float.h>
169
170void
171checkit
172#if __STDC__
173     (const char* format, ...)
174#else
175     (va_alist)
176     va_dcl
177#endif
178{
179  va_list args;
180  char *result;
181
182#if __STDC__
183  va_start (args, format);
184#else
185  char *format;
186  va_start (args);
187  format = va_arg (args, char *);
188#endif
189  vasprintf (&result, format, args);
190  if (strlen (result) < global_total_width)
191    printf ("PASS: ");
192  else
193    printf ("FAIL: ");
194  printf ("%d %s\n", global_total_width, result);
195}
196
197int
198main ()
199{
200  checkit ("%d", 0x12345678);
201  checkit ("%200d", 5);
202  checkit ("%.300d", 6);
203  checkit ("%100.150d", 7);
204  checkit ("%s", "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
205777777777777777777333333333333366666666666622222222222777777777777733333");
206  checkit ("%f%s%d%s", 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx");
207  checkit ("%e", DBL_MIN);
208  checkit ("%e", DBL_MAX);
209  checkit ("%.400f", DBL_MIN);
210  checkit ("%f", DBL_MAX);
211  checkit ("%g", DBL_MIN);
212  checkit ("%g", DBL_MAX);
213  return 0;
214}
215
216#endif /* TEST */
Note: See TracBrowser for help on using the repository browser.