xref: /reactos/dll/3rdparty/libtirpc/src/asprintf.c (revision 4561998a)
1 /* Copyright (c) 2004 Darren Tucker.
2  *
3  * Based originally on asprintf.c from OpenBSD:
4  * Copyright (c) 1997 Todd C. Miller <Todd.Miller AT courtesan.com>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 //extern int vsnprintf();
20 #include <wintirpc.h>
21 #include <stdio.h>
22 #ifndef __REACTOS__
23 #include <varargs.h>
24 #endif
25 
26 /* Include vasprintf() if not on your OS. */
27 #ifndef HAVE_VASPRINTF
28 
29 #include <errno.h>
30 #include <limits.h>
31 #include <stdarg.h>
32 #include <stdlib.h>
33 
34 #ifndef VA_COPY
35 # ifdef HAVE_VA_COPY
36 #  define VA_COPY(dest, src) va_copy(dest, src)
37 # else
38 #  ifdef HAVE___VA_COPY
39 #   define VA_COPY(dest, src) __va_copy(dest, src)
40 #  else
41 #   define VA_COPY(dest, src) (dest) = (src)
42 #  endif
43 # endif
44 #endif
45 
46 #define INIT_SZ 128
47 
48 int
49 vasprintf(char **str, const char *fmt, va_list ap)
50 {
51         int ret = -1;
52         va_list ap2;
53         char *string, *newstr;
54         size_t len;
55 
56         VA_COPY(ap2, ap);
57         if ((string = malloc(INIT_SZ)) == NULL)
58                 goto fail;
59 
60         ret = _vsnprintf(string, INIT_SZ, fmt, ap2);
61         if (ret >= 0 && ret < INIT_SZ) { /* succeeded with initial alloc */
62                 *str = string;
63         } else if (ret == INT_MAX || ret < 0) { /* Bad length */
64                 goto fail;
65         } else {        /* bigger than initial, realloc allowing for nul */
66                 len = (size_t)ret + 1;
67                 if ((newstr = realloc(string, len)) == NULL) {
68                         free(string);
69                         goto fail;
70                 } else {
71                         va_end(ap2);
72                         VA_COPY(ap2, ap);
73                         ret = _vsnprintf(newstr, len, fmt, ap2);
74                         if (ret >= 0 && (size_t)ret < len) {
75                                 *str = newstr;
76                         } else { /* failed with realloc'ed string, give up */
77                                 free(newstr);
78                                 goto fail;
79                         }
80                 }
81         }
82         va_end(ap2);
83         return (ret);
84 
85 fail:
86         *str = NULL;
87         errno = ENOMEM;
88         va_end(ap2);
89         return (-1);
90 }
91 #endif
92 
93 /* Include asprintf() if not on your OS. */
94 #ifndef HAVE_ASPRINTF
95 int asprintf(char **str, const char *fmt, ...)
96 {
97         va_list ap;
98         int ret;
99 
100         *str = NULL;
101         va_start(ap, fmt);
102         ret = vasprintf(str, fmt, ap);
103         va_end(ap);
104 
105         return ret;
106 }
107 #endif
108