1 | /* Copyright (C) 1994-2022 Free Software Foundation, Inc. |
2 | This file is part of the GNU C Library. |
3 | |
4 | The GNU C Library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Lesser General Public |
6 | License as published by the Free Software Foundation; either |
7 | version 2.1 of the License, or (at your option) any later version. |
8 | |
9 | The GNU C Library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Lesser General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Lesser General Public |
15 | License along with the GNU C Library; if not, see |
16 | <https://www.gnu.org/licenses/>. |
17 | |
18 | As a special exception, if you link the code in this file with |
19 | files compiled with a GNU compiler to produce an executable, |
20 | that does not cause the resulting executable to be covered by |
21 | the GNU Lesser General Public License. This exception does not |
22 | however invalidate any other reasons why the executable file |
23 | might be covered by the GNU Lesser General Public License. |
24 | This exception applies to code released by its copyright holders |
25 | in files containing the exception. */ |
26 | |
27 | #include "libioP.h" |
28 | #include "strfile.h" |
29 | |
30 | |
31 | static wint_t _IO_wstrn_overflow (FILE *fp, wint_t c) __THROW; |
32 | |
33 | static wint_t |
34 | _IO_wstrn_overflow (FILE *fp, wint_t c) |
35 | { |
36 | /* When we come to here this means the user supplied buffer is |
37 | filled. But since we must return the number of characters which |
38 | would have been written in total we must provide a buffer for |
39 | further use. We can do this by writing on and on in the overflow |
40 | buffer in the _IO_wstrnfile structure. */ |
41 | _IO_wstrnfile *snf = (_IO_wstrnfile *) fp; |
42 | |
43 | if (fp->_wide_data->_IO_buf_base != snf->overflow_buf) |
44 | { |
45 | _IO_wsetb (fp, snf->overflow_buf, |
46 | snf->overflow_buf + (sizeof (snf->overflow_buf) |
47 | / sizeof (wchar_t)), 0); |
48 | |
49 | fp->_wide_data->_IO_write_base = snf->overflow_buf; |
50 | fp->_wide_data->_IO_read_base = snf->overflow_buf; |
51 | fp->_wide_data->_IO_read_ptr = snf->overflow_buf; |
52 | fp->_wide_data->_IO_read_end = (snf->overflow_buf |
53 | + (sizeof (snf->overflow_buf) |
54 | / sizeof (wchar_t))); |
55 | } |
56 | |
57 | fp->_wide_data->_IO_write_ptr = snf->overflow_buf; |
58 | fp->_wide_data->_IO_write_end = snf->overflow_buf; |
59 | |
60 | /* Since we are not really interested in storing the characters |
61 | which do not fit in the buffer we simply ignore it. */ |
62 | return c; |
63 | } |
64 | |
65 | |
66 | const struct _IO_jump_t _IO_wstrn_jumps libio_vtable attribute_hidden = |
67 | { |
68 | JUMP_INIT_DUMMY, |
69 | JUMP_INIT(finish, _IO_wstr_finish), |
70 | JUMP_INIT(overflow, (_IO_overflow_t) _IO_wstrn_overflow), |
71 | JUMP_INIT(underflow, (_IO_underflow_t) _IO_wstr_underflow), |
72 | JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow), |
73 | JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail), |
74 | JUMP_INIT(xsputn, _IO_wdefault_xsputn), |
75 | JUMP_INIT(xsgetn, _IO_wdefault_xsgetn), |
76 | JUMP_INIT(seekoff, _IO_wstr_seekoff), |
77 | JUMP_INIT(seekpos, _IO_default_seekpos), |
78 | JUMP_INIT(setbuf, _IO_default_setbuf), |
79 | JUMP_INIT(sync, _IO_default_sync), |
80 | JUMP_INIT(doallocate, _IO_wdefault_doallocate), |
81 | JUMP_INIT(read, _IO_default_read), |
82 | JUMP_INIT(write, _IO_default_write), |
83 | JUMP_INIT(seek, _IO_default_seek), |
84 | JUMP_INIT(close, _IO_default_close), |
85 | JUMP_INIT(stat, _IO_default_stat), |
86 | JUMP_INIT(showmanyc, _IO_default_showmanyc), |
87 | JUMP_INIT(imbue, _IO_default_imbue) |
88 | }; |
89 | |
90 | |
91 | int |
92 | __vswprintf_internal (wchar_t *string, size_t maxlen, const wchar_t *format, |
93 | va_list args, unsigned int mode_flags) |
94 | { |
95 | _IO_wstrnfile sf; |
96 | int ret; |
97 | struct _IO_wide_data wd; |
98 | #ifdef _IO_MTSAFE_IO |
99 | sf.f._sbf._f._lock = NULL; |
100 | #endif |
101 | |
102 | if (maxlen == 0) |
103 | /* Since we have to write at least the terminating L'\0' a buffer |
104 | length of zero always makes the function fail. */ |
105 | return -1; |
106 | |
107 | _IO_no_init (&sf.f._sbf._f, _IO_USER_LOCK, 0, &wd, &_IO_wstrn_jumps); |
108 | _IO_fwide (&sf.f._sbf._f, 1); |
109 | string[0] = L'\0'; |
110 | _IO_wstr_init_static (&sf.f._sbf._f, string, maxlen - 1, string); |
111 | ret = __vfwprintf_internal ((FILE *) &sf.f._sbf, format, args, mode_flags); |
112 | |
113 | if (sf.f._sbf._f._wide_data->_IO_buf_base == sf.overflow_buf) |
114 | /* ISO C99 requires swprintf/vswprintf to return an error if the |
115 | output does not fit in the provided buffer. */ |
116 | return -1; |
117 | |
118 | /* Terminate the string. */ |
119 | *sf.f._sbf._f._wide_data->_IO_write_ptr = '\0'; |
120 | |
121 | return ret; |
122 | } |
123 | |
124 | int |
125 | __vswprintf (wchar_t *string, size_t maxlen, const wchar_t *format, |
126 | va_list args) |
127 | { |
128 | return __vswprintf_internal (string, maxlen, format, args, 0); |
129 | } |
130 | ldbl_weak_alias (__vswprintf, vswprintf) |
131 | |