Mon, 28 Jan 2013 17:37:18 +0100
Correct socket error reporting improvement with IPv6 portable code,
after helpful recommendation by Saúl Ibarra Corretgé on OSips devlist.
1 /* Like vsprintf but provides a pointer to malloc'd storage, which must
2 be freed by the caller.
3 Copyright (C) 1994, 2003 Free Software Foundation, Inc.
5 This file is part of the libiberty library.
6 Libiberty is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
11 Libiberty is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with libiberty; see the file COPYING.LIB. If
18 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include "vasprintf.h"
27 /*
29 @deftypefn Extension int vasprintf (char **@var{resptr}, const char *@var{format}, va_list @var{args})
31 Like @code{vsprintf}, but instead of passing a pointer to a buffer,
32 you pass a pointer to a pointer. This function will compute the size
33 of the buffer needed, allocate memory with @code{malloc}, and store a
34 pointer to the allocated memory in @code{*@var{resptr}}. The value
35 returned is the same as @code{vsprintf} would return. If memory could
36 not be allocated, minus one is returned and @code{NULL} is stored in
37 @code{*@var{resptr}}.
39 @end deftypefn
41 */
43 static int int_vasprintf(char **, const char *, va_list);
45 static int
46 int_vasprintf (result, format, args)
47 char **result;
48 const char *format;
49 va_list args;
50 {
51 const char *p = format;
52 /* Add one to make sure that it is never zero, which might cause malloc
53 to return NULL. */
54 int total_width = strlen (format) + 1;
55 va_list ap;
57 memcpy ((void *) &ap, (const void *) &args, sizeof (va_list));
59 while (*p != '\0')
60 {
61 if (*p++ == '%')
62 {
63 while (strchr ("-+ #0", *p))
64 ++p;
65 if (*p == '*')
66 {
67 ++p;
68 total_width += abs (va_arg (ap, int));
69 }
70 else
71 total_width += strtoul (p, (char **) &p, 10);
72 if (*p == '.')
73 {
74 ++p;
75 if (*p == '*')
76 {
77 ++p;
78 total_width += abs (va_arg (ap, int));
79 }
80 else
81 total_width += strtoul (p, (char **) &p, 10);
82 }
83 while (strchr ("hlL", *p))
84 ++p;
85 /* Should be big enough for any format specifier except %s and floats. */
86 total_width += 30;
87 switch (*p)
88 {
89 case 'd':
90 case 'i':
91 case 'o':
92 case 'u':
93 case 'x':
94 case 'X':
95 case 'c':
96 (void) va_arg (ap, int);
97 break;
98 case 'f':
99 case 'e':
100 case 'E':
101 case 'g':
102 case 'G':
103 (void) va_arg (ap, double);
104 /* Since an ieee double can have an exponent of 307, we'll
105 make the buffer wide enough to cover the gross case. */
106 total_width += 307;
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 *result = (char *) malloc (total_width);
120 if (*result != NULL)
121 return vsprintf (*result, format, args);
122 else
123 return -1;
124 }
126 int
127 vasprintf (result, format, args)
128 char **result;
129 const char *format;
130 va_list args;
131 {
132 return int_vasprintf (result, format, args);
133 }