Sync usage with man page.
[netbsd-mini2440.git] / gnu / dist / gettext / gettext-tools / lib / vasprintf.c
blobd04b63e08c016851aa5836796eea6cb9ffa33729
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 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
23 /* Specification. */
24 #include "vasprintf.h"
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #include <math.h>
32 #ifdef TEST
33 size_t global_total_width;
34 #endif
36 static int
37 int_vasprintf (char **result, const char *format, va_list *args)
39 const char *p = format;
40 /* Add one to make sure that it is never zero, which might cause malloc
41 to return NULL. */
42 size_t total_width = strlen (format) + 1;
43 va_list ap = *args;
45 while (*p != '\0')
47 if (*p++ == '%')
49 while (strchr ("-+ #0", *p))
50 ++p;
51 if (*p == '*')
53 ++p;
54 total_width += abs (va_arg (ap, int));
56 else
57 total_width += strtoul (p, (char **) &p, 10);
58 if (*p == '.')
60 ++p;
61 if (*p == '*')
63 ++p;
64 total_width += abs (va_arg (ap, int));
66 else
67 total_width += strtoul (p, (char **) &p, 10);
69 while (strchr ("hlLjtz", *p))
70 ++p;
71 /* Should be big enough for any format specifier except %s
72 and floats. */
73 total_width += 30;
74 switch (*p)
76 case 'd':
77 case 'i':
78 case 'o':
79 case 'u':
80 case 'x':
81 case 'X':
82 case 'c':
83 (void) va_arg (ap, int);
84 break;
85 case 'f':
86 case 'F':
88 double arg = va_arg (ap, double);
89 if (arg >= 1.0 || arg <= -1.0)
90 /* Since an ieee double can have an exponent of 307, we'll
91 make the buffer wide enough to cover the gross case. */
92 total_width += 307;
94 break;
95 case 'e':
96 case 'E':
97 case 'g':
98 case 'G':
99 (void) va_arg (ap, double);
100 break;
101 case 's':
102 total_width += strlen (va_arg (ap, char *));
103 break;
104 case 'p':
105 case 'n':
106 (void) va_arg (ap, char *);
107 break;
109 p++;
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;
123 vasprintf (char **result, const char *format, va_list args)
125 return int_vasprintf (result, format, &args);
129 asprintf (char **result, const char *format, ...)
131 va_list args;
132 int done;
134 va_start (args, format);
135 done = vasprintf (result, format, args);
136 va_end (args);
138 return done;
141 /* ========================= test program ========================= */
143 #ifdef TEST
145 #include <float.h>
147 void
148 checkit (const char* format, ...)
150 va_list args;
151 char *result;
153 va_start (args, format);
154 vasprintf (&result, format, args);
155 if (strlen (result) < global_total_width)
156 printf ("PASS: ");
157 else
158 printf ("FAIL: ");
159 printf ("%lu %s\n", (unsigned long) global_total_width, result);
163 main ()
165 checkit ("%d", 0x12345678);
166 checkit ("%200d", 5);
167 checkit ("%.300d", 6);
168 checkit ("%100.150d", 7);
169 checkit ("%s", "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
170 777777777777777777333333333333366666666666622222222222777777777777733333");
171 checkit ("%f%s%d%s", 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx");
172 checkit ("%e", DBL_MIN);
173 checkit ("%e", DBL_MAX);
174 checkit ("%.400f", DBL_MIN);
175 checkit ("%f", DBL_MAX);
176 checkit ("%g", DBL_MIN);
177 checkit ("%g", DBL_MAX);
178 return 0;
181 #endif /* TEST */