xref: /netbsd-src/lib/libc/stdio/vswprintf.c (revision eb9ea33272499c4bfc9b7eb8a216563ce5926fde)
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