📄 setlocal.c
字号:
/***
*setlocal.c - Contains the setlocale function
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* Contains the setlocale() function.
*
*******************************************************************************/
#include <locale.h>
#include <internal.h>
#if !defined (_WIN32)
static char _clocalestr[] = "C";
#else /* !defined (_WIN32) */
#include <cruntime.h>
#include <setlocal.h>
#include <mtdll.h>
#include <malloc.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h> /* for strtol */
#include <dbgint.h>
#include <ctype.h>
#include <awint.h>
#include <mbctype.h>
#include <rterr.h>
void * __cdecl __removelocaleref( pthreadlocinfo);
void __cdecl __addlocaleref( pthreadlocinfo);
void __cdecl __freetlocinfo(pthreadlocinfo);
/* C locale */
extern char __clocalestr[];
#ifdef _DEBUG
// free as much of memory as possible in debug mode to minimise leaks.
#include <sect_attribs.h>
#include <internal.h>
void __cdecl _locterm(void);
_CRTALLOC(".CRT$XPX") static _PVFV pterm = _locterm;
#endif /* _DEBUG */
__declspec(selectany) struct {
const char * catname;
char * locale;
int (* init)(threadlocinfo *);
} const __lc_category[LC_MAX-LC_MIN+1] = {
/* code assumes locale initialization is "__clocalestr" */
{ "LC_ALL", NULL, __init_dummy /* never called */ },
{ "LC_COLLATE", __clocalestr, __init_collate },
{ "LC_CTYPE", __clocalestr, __init_ctype },
{ "LC_MONETARY",__clocalestr, __init_monetary },
{ "LC_NUMERIC", __clocalestr, __init_numeric },
{ "LC_TIME", __clocalestr, __init_time }
};
static const char _first_127char[] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,101,102,
103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,
120,121,122,123,124,125,126,127
};
extern threadlocinfo __initiallocinfo;
extern const unsigned short _wctype[];
static const short *_ctype_loc_style = _wctype+2;
int __locale_changed=0;
/*
* Flag indicating whether or not setlocale() is active. Its value is the
* number of setlocale() calls currently active.
*
* WARNING - This flag and query function are obsolete, and are here only to
* preserve existing exports for binary compatibility.
*/
_CRTIMP int __setlc_active;
_CRTIMP int __cdecl ___setlc_active_func(void)
{
return __setlc_active;
}
/*
* Flag indicating whether or not a function which references the locale
* without having locked it is active. Its value is the number of such
* functions.
*
* WARNING - This flag and query function are obsolete, and are here only to
* preserve existing exports for binary compatibility.
*/
_CRTIMP int __unguarded_readlc_active;
_CRTIMP int * __cdecl ___unguarded_readlc_active_add_func(void)
{
return &__unguarded_readlc_active;
}
/* helper function prototypes */
char * _expandlocale(char *, char *, size_t, LC_ID *, UINT *, int);
void _strcats(char *, size_t, int, ...);
void __lc_lctostr(char *, size_t, const LC_STRINGS *);
int __lc_strtolc(LC_STRINGS *, const char *);
static char * __cdecl _setlocale_set_cat(pthreadlocinfo, int, const char *);
static char * __cdecl _setlocale_get_all(pthreadlocinfo);
static pthreadlocinfo __cdecl _updatetlocinfo_nolock(void);
static char * __cdecl _setlocale_nolock(pthreadlocinfo, int, const char *);
int __cdecl _setmbcp_nolock(int, pthreadmbcinfo);
pthreadlocinfo __cdecl _updatetlocinfoEx_nolock(pthreadlocinfo *, pthreadlocinfo);
#endif /* !defined (_WIN32) */
/***
*
* _copytlocinfo_nolock(pthreadlocinfo ptlocid, pthreadlocinfo ptlocis)
*
* Purpose:
* Copy the contents of ptlocis to ptlocid and increase the refcount of all the
* elements in ptlocid after copy.
*
******************************************************************************/
static void __cdecl _copytlocinfo_nolock(
pthreadlocinfo ptlocid,
pthreadlocinfo ptlocis)
{
if (ptlocis != NULL && ptlocid != NULL && ptlocid != ptlocis) {
*ptlocid = *ptlocis;
ptlocid->refcount = 0;
__addlocaleref(ptlocid);
}
}
/***
* _configthreadlocale(int i)
*
* Purpose:
* To set _ownlocale flag on threadinfo sturct. If this flag is set, this thread
* is going own it's threadlocinfo struct. Setlocale call on other thread will have
* no effect on this thread's locale. If 0 is passed then nothing is changed, but
* current status is returned.
* Exit :
* Returns the current status - i.e. per thread locale is enabled or not.
*
*******************************************************************************/
int __cdecl _configthreadlocale(int i)
{
/*
* ownlocale flag struct:
* bits: 000000000000000000000000000000P1
* P is set when _ENABLE_PER_THREAD_LOCALE is called for this thread
* or _ENABLE_PER_THREAD_LOCALE_NEW was set when this thread was created.
*
* __globallocalestatus structure:
* bits: 11111111111111111111111111111N1G
* G is set if _ENABLE_PER_THREAD_LOCALE_GLOBAL is set.
* G is 0 if _ENABLE_PER_THREAD_LOCALE_GLOBAL is not set.
* N is set if _ENABLE_PER_THREAD_LOCALE_NEW is set.
* N is 0 if _ENABLE_PER_THREAD_LOCALE_NEW is not set.
*/
_ptiddata ptd = _getptd();
int retval = (ptd->_ownlocale & _PER_THREAD_LOCALE_BIT)==0 ? _DISABLE_PER_THREAD_LOCALE:_ENABLE_PER_THREAD_LOCALE;
switch(i)
{
case _ENABLE_PER_THREAD_LOCALE :
ptd->_ownlocale = ptd->_ownlocale | _PER_THREAD_LOCALE_BIT;
break;
case _DISABLE_PER_THREAD_LOCALE :
ptd->_ownlocale = ptd->_ownlocale & ~_PER_THREAD_LOCALE_BIT;
break;
case 0 :
break;
/* used only during dll startup for linkopt */
case -1 :
__globallocalestatus=-1;
break;
default :
_VALIDATE_RETURN(("Invalid parameter for _configthreadlocale",0),EINVAL,-1);
break;
}
return retval;
}
#ifdef _DEBUG
void __cdecl _locterm(void)
{
if (__ptlocinfo != &__initiallocinfo) {
_mlock(_SETLOCALE_LOCK);
__try
{
__ptlocinfo = _updatetlocinfoEx_nolock(&__ptlocinfo, &__initiallocinfo);
}
__finally
{
_munlock(_SETLOCALE_LOCK);
}
}
}
#endif /* _DEBUG */
/***
* void sync_legacy_variables_lk()
*
* Purpose:
* Syncs all the legacy locale specific variables to the global locale.
*
*******************************************************************************/
static __inline void sync_legacy_variables_lk()
{
__lconv = __ptlocinfo->lconv;
_pctype = __ptlocinfo->pctype;
__mb_cur_max = __ptlocinfo->mb_cur_max;
}
/***
*_free_locale() - free threadlocinfo
*
*Purpose:
* Free up the per-thread locale info structure specified by the passed
* pointer.
*
*Entry:
* pthreadlocinfo ptloci
*
*Exit:
*
*Exceptions:
*
*******************************************************************************/
void __cdecl _free_locale(
_locale_t plocinfo
)
{
if (plocinfo != NULL)
{
_mlock(_MB_CP_LOCK);
__try
{
if (plocinfo->mbcinfo != NULL &&
InterlockedDecrement(&(plocinfo->mbcinfo->refcount)) == 0 &&
plocinfo->mbcinfo != &__initialmbcinfo )
{
_free_crt(plocinfo->mbcinfo);
}
}
__finally
{
_munlock(_MB_CP_LOCK);
}
if (plocinfo->locinfo != NULL)
{
/*
* this portion has to be in locale lock as there may be case when
* not this thread but some other thread is still holding to this
* locale and is also trying to free this locale. In this case
* we may end up leaking memory.
*/
_mlock(_SETLOCALE_LOCK);
__try
{
__removelocaleref(plocinfo->locinfo);
if ( (plocinfo->locinfo != NULL) &&
(plocinfo->locinfo->refcount == 0) &&
(plocinfo->locinfo != &__initiallocinfo) )
__freetlocinfo(plocinfo->locinfo);
}
__finally
{
_munlock(_SETLOCALE_LOCK);
}
}
/*
* set plocinfo structure to zero. This will reduce the chance of
* using plocinfo after it is being freed.
*/
plocinfo->locinfo = (void *)(((char *)NULL) + 0xbaadf00d);
plocinfo->mbcinfo = (void *)(((char *)NULL) + 0xbaadf00d);
_free_crt(plocinfo);
}
}
/* __free_locale will be removed in the next LKG */
void __cdecl __free_locale(
_locale_t plocinfo
)
{
_free_locale(plocinfo);
}
/***
* _locale_t _create_locale(int category, char *locale) -
* Set one or all locale categories of global locale structure
*
* Purpose:
* The _create_locale() routine allows the user to create a _locale_t
* object that can be used with other locale functions.
*
* Entry:
* int category = One of the locale categories defined in locale.h
* char *locale = String identifying a specific locale.
*
* Exit:
* If supplied locale pointer != NULL:
*
* If locale string is '\0', set locale to default.
*
* If desired setting can be honored, return a pointer to the
* locale string for the appropriate category.
*
* If desired setting can NOT be honored, return NULL.
*
* Exceptions:
* Compound locale strings of the form "LC_COLLATE=xxx;LC_CTYPE=xxx;..."
* are allowed for the LC_ALL category. This is to support the ability
* to restore locales with the returned string, as specified by ANSI.
* Setting the locale with a compound locale string will succeed unless
* *all* categories failed. The returned string will reflect the current
* locale. For example, if LC_CTYPE fails in the above string, setlocale
* will return "LC_COLLATE=xxx;LC_CTYPE=yyy;..." where yyy is the
* previous locale (or the C locale if restoring the previous locale
* also failed). Unrecognized LC_* categories are ignored.
*
*******************************************************************************/
_locale_t __cdecl _create_locale(
int _category,
const char *_locale
)
{
_locale_t retval = NULL;
/* Validate input */
if ( (_category < LC_MIN) || (_category > LC_MAX) || _locale == NULL)
return NULL;
if ((retval = _calloc_crt(sizeof(_locale_tstruct), 1)) == NULL)
{
errno = ENOMEM;
return NULL;
}
if ((retval->locinfo = _calloc_crt(sizeof(threadlocinfo), 1)) == NULL)
{
_free_crt(retval);
errno = ENOMEM;
return NULL;
}
if ((retval->mbcinfo = _calloc_crt(sizeof(threadmbcinfo), 1)) == NULL)
{
_free_crt(retval->locinfo);
_free_crt(retval);
errno = ENOMEM;
return NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -