Home | History | Annotate | Download | only in stdio
      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