• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/gettext-0.17/gnulib-local/lib/
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-2003, 2006-2007 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 3 of the License, or
8(at your option) any 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, see <http://www.gnu.org/licenses/>.  */
17
18#include <config.h>
19
20/* Specification.  */
21#include <stdio.h>
22
23#include <stdio.h>
24#include <string.h>
25#include <stdlib.h>
26#include <stdarg.h>
27#include <math.h>
28
29#ifdef TEST
30size_t global_total_width;
31#endif
32
33static int
34int_vasprintf (char **result, const char *format, va_list args)
35{
36  const char *p = format;
37  /* Add one to make sure that it is never zero, which might cause malloc
38     to return NULL.  */
39  size_t total_width = strlen (format) + 1;
40  va_list ap;
41
42  va_copy (ap, args);
43  while (*p != '\0')
44    {
45      if (*p++ == '%')
46	{
47	  while (strchr ("-+ #0", *p))
48	    ++p;
49	  if (*p == '*')
50	    {
51	      ++p;
52	      total_width += abs (va_arg (ap, int));
53	    }
54	  else
55	    total_width += strtoul (p, (char **) &p, 10);
56	  if (*p == '.')
57	    {
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	    }
67	  while (strchr ("hlLjtz", *p))
68	    ++p;
69	  /* Should be big enough for any format specifier except %s
70	     and floats.  */
71	  total_width += 30;
72	  switch (*p)
73	    {
74	    case 'd':
75	    case 'i':
76	    case 'o':
77	    case 'u':
78	    case 'x':
79	    case 'X':
80	    case 'c':
81	      (void) va_arg (ap, int);
82	      break;
83	    case 'f':
84	    case 'F':
85	      {
86		double arg = va_arg (ap, double);
87		if (arg >= 1.0 || arg <= -1.0)
88		  /* Since an ieee double can have an exponent of 307, we'll
89		     make the buffer wide enough to cover the gross case. */
90		  total_width += 307;
91	      }
92	      break;
93	    case 'e':
94	    case 'E':
95	    case 'g':
96	    case 'G':
97	      (void) va_arg (ap, double);
98	      break;
99	    case 's':
100	      total_width += strlen (va_arg (ap, char *));
101	      break;
102	    case 'p':
103	    case 'n':
104	      (void) va_arg (ap, char *);
105	      break;
106	    }
107	  p++;
108	}
109    }
110  va_end (ap);
111
112#ifdef TEST
113  global_total_width = total_width;
114#endif
115  *result = malloc (total_width);
116  if (*result != NULL)
117    return vsprintf (*result, format, args);
118  else
119    return -1;
120}
121
122int
123vasprintf (char **result, const char *format, va_list args)
124{
125  return int_vasprintf (result, format, args);
126}
127
128int
129asprintf (char **result, const char *format, ...)
130{
131  va_list args;
132  int done;
133
134  va_start (args, format);
135  done = vasprintf (result, format, args);
136  va_end (args);
137
138  return done;
139}
140
141/* ========================= test program ========================= */
142
143#ifdef TEST
144
145#include <float.h>
146
147void
148checkit (const char* format, ...)
149{
150  va_list args;
151  char *result;
152
153  va_start (args, format);
154  vasprintf (&result, format, args);
155  va_end (args);
156  if (strlen (result) < global_total_width)
157    printf ("PASS: ");
158  else
159    printf ("FAIL: ");
160  printf ("%lu %s\n", (unsigned long) global_total_width, result);
161}
162
163int
164main ()
165{
166  checkit ("%d", 0x12345678);
167  checkit ("%200d", 5);
168  checkit ("%.300d", 6);
169  checkit ("%100.150d", 7);
170  checkit ("%s", "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
171777777777777777777333333333333366666666666622222222222777777777777733333");
172  checkit ("%f%s%d%s", 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx");
173  checkit ("%e", DBL_MIN);
174  checkit ("%e", DBL_MAX);
175  checkit ("%.400f", DBL_MIN);
176  checkit ("%f", DBL_MAX);
177  checkit ("%g", DBL_MIN);
178  checkit ("%g", DBL_MAX);
179  return 0;
180}
181
182#endif /* TEST */
183