1c5604d0aSTim J. Robbins /* $OpenBSD: vasprintf.c,v 1.4 1998/06/21 22:13:47 millert Exp $ */
2c5604d0aSTim J. Robbins
3d915a14eSPedro F. Giffuni /*-
4d915a14eSPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
5d915a14eSPedro F. Giffuni *
6c5604d0aSTim J. Robbins * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
7c5604d0aSTim J. Robbins * All rights reserved.
8c5604d0aSTim J. Robbins *
93c87aa1dSDavid Chisnall * Copyright (c) 2011 The FreeBSD Foundation
10*5b5fa75aSEd Maste *
113c87aa1dSDavid Chisnall * Portions of this software were developed by David Chisnall
123c87aa1dSDavid Chisnall * under sponsorship from the FreeBSD Foundation.
133c87aa1dSDavid Chisnall *
14c5604d0aSTim J. Robbins * Redistribution and use in source and binary forms, with or without
15c5604d0aSTim J. Robbins * modification, are permitted provided that the following conditions
16c5604d0aSTim J. Robbins * are met:
17c5604d0aSTim J. Robbins * 1. Redistributions of source code must retain the above copyright
18c5604d0aSTim J. Robbins * notice, this list of conditions and the following disclaimer.
19c5604d0aSTim J. Robbins * 2. Redistributions in binary form must reproduce the above copyright
20c5604d0aSTim J. Robbins * notice, this list of conditions and the following disclaimer in the
21c5604d0aSTim J. Robbins * documentation and/or other materials provided with the distribution.
22c5604d0aSTim J. Robbins * 3. The name of the author may not be used to endorse or promote products
23c5604d0aSTim J. Robbins * derived from this software without specific prior written permission.
24c5604d0aSTim J. Robbins *
25c5604d0aSTim J. Robbins * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
26c5604d0aSTim J. Robbins * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27c5604d0aSTim J. Robbins * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
28c5604d0aSTim J. Robbins * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29c5604d0aSTim J. Robbins * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30c5604d0aSTim J. Robbins * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
31c5604d0aSTim J. Robbins * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32c5604d0aSTim J. Robbins * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
33c5604d0aSTim J. Robbins * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
34c5604d0aSTim J. Robbins * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35c5604d0aSTim J. Robbins */
36c5604d0aSTim J. Robbins
37c5604d0aSTim J. Robbins #include <errno.h>
38666d00d3SDavid Schultz #include <limits.h>
39c5604d0aSTim J. Robbins #include <stdio.h>
40c5604d0aSTim J. Robbins #include <stdlib.h>
41c5604d0aSTim J. Robbins #include <wchar.h>
42c5604d0aSTim J. Robbins #include "local.h"
433c87aa1dSDavid Chisnall #include "xlocale_private.h"
44c5604d0aSTim J. Robbins
45c5604d0aSTim J. Robbins int
vswprintf_l(wchar_t * __restrict s,size_t n,locale_t locale,const wchar_t * __restrict fmt,__va_list ap)463c87aa1dSDavid Chisnall vswprintf_l(wchar_t * __restrict s, size_t n, locale_t locale,
473c87aa1dSDavid Chisnall const wchar_t * __restrict fmt, __va_list ap)
48c5604d0aSTim J. Robbins {
4993996f6dSTim J. Robbins static const mbstate_t initial;
5093996f6dSTim J. Robbins mbstate_t mbs;
511b0181dfSJohn Baldwin FILE f = FAKE_FILE;
52c5604d0aSTim J. Robbins char *mbp;
5323b6f790STim J. Robbins int ret, sverrno;
54f1defde9SMax Khon size_t nwc;
553c87aa1dSDavid Chisnall FIX_LOCALE(locale);
56c5604d0aSTim J. Robbins
57c5604d0aSTim J. Robbins if (n == 0) {
58c5604d0aSTim J. Robbins errno = EINVAL;
59c5604d0aSTim J. Robbins return (-1);
60c5604d0aSTim J. Robbins }
61666d00d3SDavid Schultz if (n - 1 > INT_MAX) {
62666d00d3SDavid Schultz errno = EOVERFLOW;
63666d00d3SDavid Schultz *s = L'\0';
64666d00d3SDavid Schultz return (-1);
65666d00d3SDavid Schultz }
66c5604d0aSTim J. Robbins
67c5604d0aSTim J. Robbins f._flags = __SWR | __SSTR | __SALC;
68c5604d0aSTim J. Robbins f._bf._base = f._p = (unsigned char *)malloc(128);
69c5604d0aSTim J. Robbins if (f._bf._base == NULL) {
70c5604d0aSTim J. Robbins errno = ENOMEM;
7104acf365SDavid Schultz *s = L'\0';
72c5604d0aSTim J. Robbins return (-1);
73c5604d0aSTim J. Robbins }
74c5604d0aSTim J. Robbins f._bf._size = f._w = 127; /* Leave room for the NUL */
753c87aa1dSDavid Chisnall ret = __vfwprintf(&f, locale, fmt, ap);
7623b6f790STim J. Robbins if (ret < 0) {
7723b6f790STim J. Robbins sverrno = errno;
7823b6f790STim J. Robbins free(f._bf._base);
7923b6f790STim J. Robbins errno = sverrno;
8004acf365SDavid Schultz *s = L'\0';
8123b6f790STim J. Robbins return (-1);
8223b6f790STim J. Robbins }
83c5604d0aSTim J. Robbins *f._p = '\0';
84c5604d0aSTim J. Robbins mbp = f._bf._base;
85c5604d0aSTim J. Robbins /*
86c5604d0aSTim J. Robbins * XXX Undo the conversion from wide characters to multibyte that
87c5604d0aSTim J. Robbins * fputwc() did in __vfwprintf().
88c5604d0aSTim J. Robbins */
8993996f6dSTim J. Robbins mbs = initial;
903c87aa1dSDavid Chisnall nwc = mbsrtowcs_l(s, (const char **)&mbp, n, &mbs, locale);
91c5604d0aSTim J. Robbins free(f._bf._base);
92f1defde9SMax Khon if (nwc == (size_t)-1) {
93c5604d0aSTim J. Robbins errno = EILSEQ;
9404acf365SDavid Schultz *s = L'\0';
95c5604d0aSTim J. Robbins return (-1);
96c5604d0aSTim J. Robbins }
97f1defde9SMax Khon if (nwc == n) {
98c5604d0aSTim J. Robbins s[n - 1] = L'\0';
99c5604d0aSTim J. Robbins errno = EOVERFLOW;
100c5604d0aSTim J. Robbins return (-1);
101c5604d0aSTim J. Robbins }
102c5604d0aSTim J. Robbins
103c5604d0aSTim J. Robbins return (ret);
104c5604d0aSTim J. Robbins }
1053c87aa1dSDavid Chisnall int
vswprintf(wchar_t * __restrict s,size_t n,const wchar_t * __restrict fmt,__va_list ap)1063c87aa1dSDavid Chisnall vswprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt,
1073c87aa1dSDavid Chisnall __va_list ap)
1083c87aa1dSDavid Chisnall {
1093c87aa1dSDavid Chisnall return vswprintf_l(s, n, __get_locale(), fmt, ap);
1103c87aa1dSDavid Chisnall }
111