1*eb9ea332Schristos /* $NetBSD: vswprintf.c,v 1.6 2013/05/19 21:45:00 christos Exp $ */
2f432bbb6Schristos
3f432bbb6Schristos /*
4f432bbb6Schristos * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
5f432bbb6Schristos * All rights reserved.
6f432bbb6Schristos *
7f432bbb6Schristos * Redistribution and use in source and binary forms, with or without
8f432bbb6Schristos * modification, are permitted provided that the following conditions
9f432bbb6Schristos * are met:
10f432bbb6Schristos * 1. Redistributions of source code must retain the above copyright
11f432bbb6Schristos * notice, this list of conditions and the following disclaimer.
12f432bbb6Schristos * 2. Redistributions in binary form must reproduce the above copyright
13f432bbb6Schristos * notice, this list of conditions and the following disclaimer in the
14f432bbb6Schristos * documentation and/or other materials provided with the distribution.
15f432bbb6Schristos * 3. The name of the author may not be used to endorse or promote products
16f432bbb6Schristos * derived from this software without specific prior written permission.
17f432bbb6Schristos *
18f432bbb6Schristos * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19f432bbb6Schristos * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20f432bbb6Schristos * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21f432bbb6Schristos * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22f432bbb6Schristos * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23f432bbb6Schristos * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24f432bbb6Schristos * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25f432bbb6Schristos * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26f432bbb6Schristos * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27f432bbb6Schristos * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28f432bbb6Schristos */
29f432bbb6Schristos
30f432bbb6Schristos #include <sys/cdefs.h>
31f432bbb6Schristos #if defined(LIBC_SCCS) && !defined(lint)
32f432bbb6Schristos #if 0
33f432bbb6Schristos __FBSDID("$FreeBSD: src/lib/libc/stdio/vswprintf.c,v 1.6 2005/02/21 19:41:44 fjoe Exp $");
34f432bbb6Schristos #else
35*eb9ea332Schristos __RCSID("$NetBSD: vswprintf.c,v 1.6 2013/05/19 21:45:00 christos Exp $");
36f432bbb6Schristos #endif
37f432bbb6Schristos #endif /* LIBC_SCCS and not lint */
38f432bbb6Schristos
392561b634Sjoerg #include "namespace.h"
40f432bbb6Schristos #include <errno.h>
412561b634Sjoerg #include <locale.h>
42f432bbb6Schristos #include <stdio.h>
43f432bbb6Schristos #include <stdlib.h>
44f432bbb6Schristos #include <wchar.h>
45f432bbb6Schristos #include <stdarg.h>
462561b634Sjoerg
47f432bbb6Schristos #include "reentrant.h"
482561b634Sjoerg #include "setlocale_local.h"
49f432bbb6Schristos #include "local.h"
50f432bbb6Schristos
__weak_alias(vswprintf_l,_vswprintf_l)512561b634Sjoerg __weak_alias(vswprintf_l, _vswprintf_l)
522561b634Sjoerg
53f432bbb6Schristos int
542561b634Sjoerg vswprintf_l(wchar_t * __restrict s, size_t n, locale_t loc,
552561b634Sjoerg const wchar_t * __restrict fmt, va_list ap)
56f432bbb6Schristos {
57f432bbb6Schristos static const mbstate_t initial;
58f432bbb6Schristos mbstate_t mbs;
59f432bbb6Schristos FILE f;
60f432bbb6Schristos char *mbp;
61f432bbb6Schristos int ret, sverrno;
62f432bbb6Schristos size_t nwc;
63f432bbb6Schristos struct __sfileext fext;
64f432bbb6Schristos
65f432bbb6Schristos if (n == 0) {
66f432bbb6Schristos errno = EINVAL;
67526d9427Schristos return -1;
68f432bbb6Schristos }
69f432bbb6Schristos
70f432bbb6Schristos _FILEEXT_SETUP(&f, &fext);
71f432bbb6Schristos f._file = -1;
72f432bbb6Schristos f._flags = __SWR | __SSTR | __SALC;
73*eb9ea332Schristos f._bf._base = f._p = malloc(128);
74f432bbb6Schristos if (f._bf._base == NULL) {
75f432bbb6Schristos errno = ENOMEM;
76526d9427Schristos return -1;
77f432bbb6Schristos }
78f432bbb6Schristos f._bf._size = f._w = 127; /* Leave room for the NUL */
792561b634Sjoerg ret = __vfwprintf_unlocked_l(&f, loc, fmt, ap);
80f432bbb6Schristos if (ret < 0) {
81f432bbb6Schristos sverrno = errno;
82f432bbb6Schristos free(f._bf._base);
83f432bbb6Schristos errno = sverrno;
84526d9427Schristos return -1;
85f432bbb6Schristos }
86f432bbb6Schristos *f._p = '\0';
87f432bbb6Schristos mbp = (char *)f._bf._base;
88f432bbb6Schristos /*
89f432bbb6Schristos * XXX Undo the conversion from wide characters to multibyte that
90f432bbb6Schristos * fputwc() did in __vfwprintf().
91f432bbb6Schristos */
92f432bbb6Schristos mbs = initial;
932561b634Sjoerg nwc = mbsrtowcs_l(s, (void *)&mbp, n, &mbs, loc);
94f432bbb6Schristos free(f._bf._base);
95f432bbb6Schristos if (nwc == (size_t)-1) {
96f432bbb6Schristos errno = EILSEQ;
97526d9427Schristos return -1;
98f432bbb6Schristos }
99f432bbb6Schristos if (nwc == n) {
100f432bbb6Schristos s[n - 1] = L'\0';
101f432bbb6Schristos errno = EOVERFLOW;
102526d9427Schristos return -1;
103f432bbb6Schristos }
104f432bbb6Schristos
105526d9427Schristos return ret;
106f432bbb6Schristos }
1072561b634Sjoerg
1082561b634Sjoerg int
vswprintf(wchar_t * __restrict s,size_t n,const wchar_t * __restrict fmt,va_list ap)1092561b634Sjoerg vswprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt,
1102561b634Sjoerg va_list ap)
1112561b634Sjoerg {
112e0ac190eSjoerg return vswprintf_l(s, n, _current_locale(), fmt, ap);
1132561b634Sjoerg }
114