📄 setlocal.c
字号:
}
_copytlocinfo_nolock(retval->locinfo, &__initiallocinfo);
if (_setlocale_nolock(retval->locinfo, _category, _locale) == NULL)
{
__removelocaleref(retval->locinfo);
__freetlocinfo(retval->locinfo);
_free_crt(retval);
retval = NULL;
}
else
{
if (_setmbcp_nolock(retval->locinfo->lc_codepage, retval->mbcinfo) != 0)
{
_free_crt(retval->mbcinfo);
__removelocaleref(retval->locinfo);
__freetlocinfo(retval->locinfo);
_free_crt(retval);
retval = NULL;
}
else
{
retval->mbcinfo->refcount = 1;
retval->mbcinfo->refcount = 1;
}
}
return retval;
}
/* __create_locale will be removed in the next LKG */
_locale_t __cdecl __create_locale(
int _category,
const char *_locale
)
{
return _create_locale(_category, _locale);
}
/***
* _locale_t _get_current_locale() -
* Gets the current locale setting.
*
* Purpose:
* Gets the current locale setting for this thread. Returns locale
* in form of _locale_t, which then can be used with other locale
* aware string funcitons.
*
* Entry:
*
* Exit:
*
* Exceptions:
*
*******************************************************************************/
_locale_t __cdecl _get_current_locale(void)
{
_locale_t retval = NULL;
_ptiddata ptd = _getptd();
if ((retval = _calloc_crt(sizeof(_locale_tstruct), 1)) == NULL)
{
errno = ENOMEM;
return NULL;
}
__updatetlocinfo();
__updatetmbcinfo();
/*
* No one can free the data pointed to by ptlocinfo while we're copying
* it, since we're copying this thread's ptlocinfo, which won't be updated
* during the copy. So there are no worries about it being freed from
* under us. We still need a lock while adding a reference for the new
* copy, though, because of the race condition found in _wsetlocale.
*/
retval->locinfo = ptd->ptlocinfo;
retval->mbcinfo = ptd->ptmbcinfo;
_mlock(_SETLOCALE_LOCK);
__try {
__addlocaleref(retval->locinfo);
}
__finally {
_munlock(_SETLOCALE_LOCK);
}
_mlock(_MB_CP_LOCK);
__try
{
InterlockedIncrement(&(retval->mbcinfo->refcount));
}
__finally
{
_munlock(_MB_CP_LOCK);
}
return retval;
}
/* __get_current_locale will be removed in the next LKG */
_locale_t __cdecl __get_current_locale(void)
{
return _get_current_locale();
}
/***
*char * setlocale(int category, char *locale) - Set one or all locale categories
*
*Purpose:
* The setlocale() routine allows the user to set one or more of
* the locale categories to the specific locale selected by the
* user. [ANSI]
*
* NOTE: Under !_INTL, the C libraries only support the "C" locale.
* Attempts to change the locale will fail.
*
*Entry:
* int category = One of the locale categories defined in locale.h
* char *locale = String identifying a specific locale or NULL to
* query the current locale.
*
*Exit:
* If supplied locale pointer == NULL:
*
* Return pointer to current locale string and do NOT change
* the current locale.
*
* 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.
*
*******************************************************************************/
#if !defined (_WIN32)
char * __cdecl setlocale (
int _category,
const char *_locale
)
{
if ( (_locale == NULL) ||
(_locale[0] == '\0') ||
( (_locale[0]=='C') && (_locale[1]=='\0')) )
return(__clocalestr);
else
return(NULL);
}
#else /* !defined (_WIN32) */
char * __cdecl setlocale (
int _category,
const char *_locale
)
{
char * retval=NULL;
pthreadlocinfo ptloci = NULL;
_ptiddata ptd;
/* Validate category */
_VALIDATE_RETURN(LC_MIN <= _category && _category <= LC_MAX, EINVAL, NULL);
ptd = _getptd();
__updatetlocinfo();
// Note here that we increment the _ownlocale for this thread. We need this
// to make sure that the locale is not updated to some other locale by call to
// stricmp().
// Don't set any flag that aligns with N, P or G
ptd->_ownlocale |= 0x10;
__try {
if ((ptloci = _calloc_crt(sizeof(threadlocinfo), 1)) != NULL)
{
/*
* No one can free the data pointed to by ptlocinfo while we're
* copying it, since we're copying this thread's ptlocinfo, which
* won't be updated during the copy. So there are no worries
* about it being freed from under us. We still need a lock while
* making the copy, though, because of the race condition found in
* _wsetlocale.
*/
_mlock(_SETLOCALE_LOCK);
__try {
_copytlocinfo_nolock(ptloci, ptd->ptlocinfo);
}
__finally {
_munlock(_SETLOCALE_LOCK);
}
if (( ptloci != NULL) && (retval = _setlocale_nolock(ptloci, _category, _locale))) {
/*
* What we are trying here is that if no call has been made to
* setlocale to change locale from "C" locale to some other locale
* we keep __locale_changed = 0. Other funcitons depending on locale
* use this variable to optimize performance for C locale which is
* normally the case in 90% of the applications.
*/
if (_locale != NULL && strcmp(_locale, __clocalestr))
{
__locale_changed = 1;
}
_mlock(_SETLOCALE_LOCK);
__try {
(void)_updatetlocinfoEx_nolock(&ptd->ptlocinfo, ptloci);
__removelocaleref(ptloci);
// Note that after incrementing _ownlocale, if this thread doesn't
// have it's own locale, _ownlocale variable should be 1.
if (!(ptd->_ownlocale & _PER_THREAD_LOCALE_BIT) &&
!(__globallocalestatus & _GLOBAL_LOCALE_BIT)) {
(void)_updatetlocinfoEx_nolock(&__ptlocinfo, ptd->ptlocinfo);
sync_legacy_variables_lk();
}
} __finally {
_munlock(_SETLOCALE_LOCK);
}
} else {
__removelocaleref(ptloci);
__freetlocinfo(ptloci);
}
}
} __finally {
// Undo the previous action.
ptd->_ownlocale &= ~0x10;
}
return retval;
}
static char * __cdecl _setlocale_nolock(
pthreadlocinfo ploci,
int _category,
const char *_locale
)
{
char * retval;
/* Interpret locale */
if (_category != LC_ALL)
{
retval = (_locale) ? _setlocale_set_cat(ploci, _category,_locale) :
ploci->lc_category[_category].locale;
} else { /* LC_ALL */
char lctemp[MAX_LC_LEN];
int i;
int same = 1;
int fLocaleSet = 0; /* flag to indicate if anything successfully set */
if (_locale != NULL)
{
if ( (_locale[0]=='L') && (_locale[1]=='C') && (_locale[2]=='_') )
{
/* parse compound locale string */
size_t len;
const char * p = _locale; /* start of string to parse */
const char * s;
do {
s = strpbrk(p,"=;");
if ((s==(char *)NULL) || (!(len=(size_t)(s-p))) || (*s==';'))
return NULL; /* syntax error */
/* match with known LC_ strings, if possible, else ignore */
for (i=LC_ALL+1; i<=LC_MAX; i++)
{
if ((!strncmp(__lc_category[i].catname,p,len))
&& (len==strlen(__lc_category[i].catname)))
{
break; /* matched i */
}
} /* no match if (i>LC_MAX) -- just ignore */
if ((!(len = strcspn(++s,";"))) && (*s!=';'))
return NULL; /* syntax error */
if (i<=LC_MAX)
{
_ERRCHECK(strncpy_s(lctemp, _countof(lctemp), s, len));
lctemp[len]='\0'; /* null terminate string */
/* don't fail unless all categories fail */
if (_setlocale_set_cat(ploci, i,lctemp))
fLocaleSet++; /* record a success */
}
if (*(p = s+len)!='\0')
p++; /* skip ';', if present */
} while (*p);
retval = (fLocaleSet) ? _setlocale_get_all(ploci) : NULL;
} else { /* simple LC_ALL locale string */
/* confirm locale is supported, get expanded locale */
if (retval = _expandlocale((char *)_locale, lctemp, _countof(lctemp), NULL, NULL, _category))
{
for (i=LC_MIN; i<=LC_MAX; i++)
{
if (i!=LC_ALL)
{
if (strcmp(lctemp, ploci->lc_category[i].locale))
{
if (_setlocale_set_cat(ploci, i, lctemp))
{
fLocaleSet++; /* record a success */
}
else
{
same = 0; /* record a failure */
}
}
else
fLocaleSet++; /* trivial succcess */
}
}
if (same) /* needn't call setlocale_get_all() if all the same */
{
retval = _setlocale_get_all(ploci);
/* retval set above */
}
else
retval = (fLocaleSet) ? _setlocale_get_all(ploci) : NULL;
}
}
} else { /* LC_ALL & NULL */
retval = _setlocale_get_all (ploci);
}
}
/* common exit point */
return retval;
} /* setlocale */
static char * __cdecl _setlocale_set_cat (
pthreadlocinfo ploci,
int category,
const char * locale
)
{
char * oldlocale;
LCID oldhandle;
UINT oldcodepage;
LC_ID oldid;
LC_ID idtemp;
UINT cptemp;
char lctemp[MAX_LC_LEN];
char * pch = NULL;
size_t cch = 0;
short out[sizeof(_first_127char)];
int i;
_ptiddata _ptd = _getptd();
struct _is_ctype_compatible *_Lcid_c = _ptd->_setloc_data._Lcid_c; // __setloc_data._Lcid_c is array
int _LOC_CCACHE = sizeof(_ptd->_setloc_data._Lcid_c)/sizeof(struct _is_ctype_compatible);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -