xref: /illumos-gate/usr/src/lib/libc/port/stdio/mse.c (revision 85bb5f1d)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include "lint.h"
30 #include "mtlib.h"
31 #include "mbstatet.h"
32 #include "file64.h"
33 #include <sys/types.h>
34 #include <stdio.h>
35 #include <wchar.h>
36 #include <thread.h>
37 #include <synch.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include "libc.h"
41 #include "stdiom.h"
42 #include "mse.h"
43 
44 /*
45  * DESCRIPTION:
46  * This function sets the error indicator for the specified stream.
47  * This is a private API for the L10N method functions, especially
48  * for fgetwc().
49  *
50  * The stream needs to have been properly locked.  Usually, the wrapper
51  * function of fgetwc() locks the stream.
52  */
53 void
54 __fseterror_u(FILE *iop)
55 {
56 	iop->_flag |= _IOERR;
57 }
58 
59 /*
60  * DESCRIPTION:
61  * This function/macro gets the orientation bound to the specified iop.
62  *
63  * RETURNS:
64  * _WC_MODE	if iop has been bound to Wide orientation
65  * _BYTE_MODE	if iop has been bound to Byte orientation
66  * _NO_MODE	if iop has been bound to neither Wide nor Byte
67  */
68 _IOP_orientation_t
69 _getorientation(FILE *iop)
70 {
71 	if (GET_BYTE_MODE(iop))
72 		return (_BYTE_MODE);
73 	else if (GET_WC_MODE(iop))
74 		return (_WC_MODE);
75 
76 	return (_NO_MODE);
77 }
78 
79 /*
80  * DESCRIPTION:
81  * This function/macro sets the orientation to the specified iop.
82  *
83  * INPUT:
84  * flag may take one of the following:
85  *	_WC_MODE	Wide orientation
86  *	_BYTE_MODE	Byte orientation
87  *	_NO_MODE	Unoriented
88  */
89 void
90 _setorientation(FILE *iop, _IOP_orientation_t mode)
91 {
92 	switch (mode) {
93 	case _NO_MODE:
94 		CLEAR_BYTE_MODE(iop);
95 		CLEAR_WC_MODE(iop);
96 		break;
97 	case _BYTE_MODE:
98 		CLEAR_WC_MODE(iop);
99 		SET_BYTE_MODE(iop);
100 		break;
101 	case _WC_MODE:
102 		CLEAR_BYTE_MODE(iop);
103 		SET_WC_MODE(iop);
104 		break;
105 	}
106 }
107 
108 static mbstate_t	**__top_mbstates = NULL;
109 static mutex_t	__top_mbstates_lock = DEFAULTMUTEX;
110 
111 void
112 _clear_internal_mbstate(void)
113 {
114 	int	i;
115 
116 	lmutex_lock(&__top_mbstates_lock);
117 	if (__top_mbstates) {
118 		for (i = 0; i <= _MAX_MB_FUNC; i++) {
119 			if (*(__top_mbstates + i)) {
120 				lfree(*(__top_mbstates + i),
121 				    sizeof (mbstate_t));
122 			}
123 		}
124 		lfree(__top_mbstates,
125 		    (_MAX_MB_FUNC + 1) * sizeof (mbstate_t *));
126 		__top_mbstates = NULL;
127 	}
128 	lmutex_unlock(&__top_mbstates_lock);
129 }
130 
131 mbstate_t *
132 _get_internal_mbstate(int item)
133 {
134 	if (item < 0 || item > _MAX_MB_FUNC)
135 		return (NULL);
136 
137 	lmutex_lock(&__top_mbstates_lock);
138 	if (__top_mbstates == NULL) {
139 		__top_mbstates =
140 		    lmalloc((_MAX_MB_FUNC + 1) * sizeof (mbstate_t *));
141 		if (__top_mbstates == NULL) {
142 			lmutex_unlock(&__top_mbstates_lock);
143 			return (NULL);
144 		}
145 		*(__top_mbstates + item) = lmalloc(sizeof (mbstate_t));
146 		if (*(__top_mbstates + item) == NULL) {
147 			lmutex_unlock(&__top_mbstates_lock);
148 			return (NULL);
149 		}
150 		lmutex_unlock(&__top_mbstates_lock);
151 		return (*(__top_mbstates + item));
152 	}
153 	if (*(__top_mbstates + item) == NULL) {
154 		*(__top_mbstates + item) = lmalloc(sizeof (mbstate_t));
155 		if (*(__top_mbstates + item) == NULL) {
156 			lmutex_unlock(&__top_mbstates_lock);
157 			return (NULL);
158 		}
159 	}
160 	lmutex_unlock(&__top_mbstates_lock);
161 	return (*(__top_mbstates + item));
162 }
163 
164 /*
165  * From page 32 of XSH5
166  * Once a wide-character I/O function has been applied
167  * to a stream without orientation, the stream becomes
168  * wide-orientated.  Similarly, once a byte I/O function
169  * has been applied to a stream without orientation,
170  * the stream becomes byte-orientated.  Only a call to
171  * the freopen() function or the fwide() function can
172  * otherwise alter the orientation of a stream.
173  */
174 
175 /*
176  * void
177  * _set_orientation_byte(FILE *iop)
178  *
179  * Note: this is now implemented as macro __SET_ORIENTATION_BYTE()
180  *       (in libc/inc/mse.h) for performance improvement.
181  */
182 
183 /* Returns the value of 'ps->__nconsumed' */
184 char
185 __mbst_get_nconsumed(const mbstate_t *ps)
186 {
187 	return (ps->__nconsumed);
188 }
189 
190 /* Sets 'n' to 'ps->__nconsumed' */
191 void
192 __mbst_set_nconsumed(mbstate_t *ps, char n)
193 {
194 	ps->__nconsumed = n;
195 }
196 
197 /* Copies 'len' bytes from '&ps->__consumed[index]' to 'str' */
198 int
199 __mbst_get_consumed_array(const mbstate_t *ps, char *str,
200 	size_t index, size_t len)
201 {
202 	if ((index + len) > 8) {
203 		/* The max size of __consumed[] is 8 */
204 		return (-1);
205 	}
206 	(void) memcpy((void *)str, (const void *)&ps->__consumed[index], len);
207 	return (0);
208 }
209 
210 /* Copies 'len' bytes from 'str' to '&ps->__consumed[index]' */
211 int
212 __mbst_set_consumed_array(mbstate_t *ps, const char *str,
213 	size_t index, size_t len)
214 {
215 	if ((index + len) > 8) {
216 		/* The max size of __consumed[] is 8 */
217 		return (-1);
218 	}
219 	(void) memcpy((void *)&ps->__consumed[index], (const void *)str, len);
220 	return (0);
221 }
222 
223 /* Returns 'ps->__lc_locale' */
224 void *
225 __mbst_get_locale(const mbstate_t *ps)
226 {
227 	return (ps->__lc_locale);
228 }
229 
230 /* Sets 'loc' to 'ps->__lc_locale' */
231 void
232 __mbst_set_locale(mbstate_t *ps, const void *loc)
233 {
234 	ps->__lc_locale = (void *)loc;
235 }
236