]>
Commit | Line | Data |
---|---|---|
224c7076 A |
1 | /* $OpenBSD: vasprintf.c,v 1.4 1998/06/21 22:13:47 millert Exp $ */ |
2 | ||
3 | /* | |
4 | * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com> | |
5 | * All rights reserved. | |
6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | |
15 | * 3. The name of the author may not be used to endorse or promote products | |
16 | * derived from this software without specific prior written permission. | |
17 | * | |
18 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, | |
19 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY | |
20 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | |
21 | * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
22 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
24 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
26 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
27 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
28 | */ | |
29 | ||
30 | #include <sys/cdefs.h> | |
31 | #if 0 | |
32 | __FBSDID("FreeBSD: src/lib/libc/stdio/vasprintf.c,v 1.16 2002/08/21 16:19:57 mike Exp "); | |
33 | #endif | |
34 | __FBSDID("$FreeBSD: src/lib/libc/stdio/vswprintf.c,v 1.5 2004/04/07 09:55:05 tjr Exp $"); | |
35 | ||
36 | #include "xlocale_private.h" | |
37 | ||
38 | #include <errno.h> | |
39 | #include <stdio.h> | |
40 | #include <stdlib.h> | |
41 | #include <wchar.h> | |
42 | #include "local.h" | |
43 | ||
44 | int | |
45 | vswprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, | |
46 | __va_list ap) | |
47 | { | |
48 | static const mbstate_t initial; | |
49 | mbstate_t mbs; | |
50 | FILE f; | |
51 | struct __sFILEX ext; | |
52 | char *mbp; | |
53 | int ret, sverrno; | |
54 | size_t conv; | |
55 | locale_t loc = __current_locale(); | |
56 | ||
57 | if (n == 0) { | |
58 | errno = EINVAL; | |
59 | return (-1); | |
60 | } | |
61 | ||
62 | f._file = -1; | |
63 | f._flags = __SWR | __SSTR | __SALC; | |
64 | f._bf._base = f._p = (unsigned char *)malloc(128); | |
65 | if (f._bf._base == NULL) { | |
66 | errno = ENOMEM; | |
67 | return (-1); | |
68 | } | |
69 | f._bf._size = f._w = 127; /* Leave room for the NUL */ | |
70 | f._extra = &ext; | |
71 | INITEXTRA(&f); | |
72 | ret = __vfwprintf(&f, loc, fmt, ap); | |
73 | if (ret < 0) { | |
74 | sverrno = errno; | |
75 | free(f._bf._base); | |
76 | errno = sverrno; | |
77 | return (-1); | |
78 | } | |
79 | *f._p = '\0'; | |
80 | mbp = (char *)f._bf._base; | |
81 | /* | |
82 | * XXX Undo the conversion from wide characters to multibyte that | |
83 | * fputwc() did in __vfwprintf(). | |
84 | */ | |
85 | mbs = initial; | |
86 | if ((conv = mbsrtowcs_l(s, (const char **)&mbp, n, &mbs, loc)) == (size_t)-1) { | |
87 | free(f._bf._base); | |
88 | errno = EILSEQ; | |
89 | return (-1); | |
90 | } | |
91 | free(f._bf._base); | |
92 | if (conv >= n) { | |
93 | s[n - 1] = L'\0'; | |
94 | errno = EOVERFLOW; | |
95 | return (-1); | |
96 | } | |
97 | ||
98 | return (ret); | |
99 | } | |
100 | ||
101 | int | |
102 | vswprintf_l(wchar_t * __restrict s, size_t n, locale_t loc, | |
103 | const wchar_t * __restrict fmt, __va_list ap) | |
104 | { | |
105 | static const mbstate_t initial; | |
106 | mbstate_t mbs; | |
107 | FILE f; | |
108 | struct __sFILEX ext; | |
109 | char *mbp; | |
110 | int ret, sverrno; | |
111 | size_t conv; | |
112 | ||
113 | NORMALIZE_LOCALE(loc); | |
114 | if (n == 0) { | |
115 | errno = EINVAL; | |
116 | return (-1); | |
117 | } | |
118 | ||
119 | f._file = -1; | |
120 | f._flags = __SWR | __SSTR | __SALC; | |
121 | f._bf._base = f._p = (unsigned char *)malloc(128); | |
122 | if (f._bf._base == NULL) { | |
123 | errno = ENOMEM; | |
124 | return (-1); | |
125 | } | |
126 | f._bf._size = f._w = 127; /* Leave room for the NUL */ | |
127 | f._extra = &ext; | |
128 | INITEXTRA(&f); | |
129 | ret = __vfwprintf(&f, loc, fmt, ap); | |
130 | if (ret < 0) { | |
131 | sverrno = errno; | |
132 | free(f._bf._base); | |
133 | errno = sverrno; | |
134 | return (-1); | |
135 | } | |
136 | *f._p = '\0'; | |
137 | mbp = (char *)f._bf._base; | |
138 | /* | |
139 | * XXX Undo the conversion from wide characters to multibyte that | |
140 | * fputwc() did in __vfwprintf(). | |
141 | */ | |
142 | mbs = initial; | |
143 | if ((conv = mbsrtowcs_l(s, (const char **)&mbp, n, &mbs, loc)) == (size_t)-1) { | |
144 | free(f._bf._base); | |
145 | errno = EILSEQ; | |
146 | return (-1); | |
147 | } | |
148 | free(f._bf._base); | |
149 | if (conv >= n) { | |
150 | s[n - 1] = L'\0'; | |
151 | errno = EOVERFLOW; | |
152 | return (-1); | |
153 | } | |
154 | ||
155 | return (ret); | |
156 | } |