📄 setlocal.c
字号:
struct _is_ctype_compatible buf1, buf2;
if (!_expandlocale((char *)locale, lctemp, _countof(lctemp), &idtemp, &cptemp, category))
{
return NULL; /* unrecognized locale */
}
if (!strcmp(lctemp, ploci->lc_category[category].locale))
{
return ploci->lc_category[category].locale;
}
cch = sizeof(int)+strlen(lctemp)+1;
if (!(pch = (char *)_malloc_crt(cch)))
{
return NULL; /* error if malloc fails */
}
oldlocale = ploci->lc_category[category].locale; /* save for possible restore*/
oldhandle = ploci->lc_handle[category];
memcpy((void *)&oldid, (void *)&ploci->lc_id[category], sizeof(oldid));
oldcodepage = ploci->lc_codepage;
/* update locale string */
_ERRCHECK(strcpy_s(pch + sizeof(int), cch - sizeof(int), lctemp));
ploci->lc_category[category].locale = pch + sizeof(int);
ploci->lc_handle[category] = MAKELCID(idtemp.wLanguage, SORT_DEFAULT);
memcpy((void *)&ploci->lc_id[category], (void *)&idtemp, sizeof(idtemp));
/* To speedup locale based comparisions, we identify if the current
* local has first 127 character set same as CLOCALE. If yes then
* ploci->lc_clike = TRUE.
*/
if (category==LC_CTYPE)
{
ploci->lc_codepage = cptemp;
buf1 = _Lcid_c[_LOC_CCACHE -1];
/* brings the recently used codepage to the top. or else shifts
* every thing down by one so that new _Lcid_c can be placed at
* the top.
*/
for ( i = 0; i < _LOC_CCACHE; i++)
{
if (ploci->lc_codepage == _Lcid_c[i].id)
{
/* We don't really want to swap cache around in case what we are looking
* for is the first element of the cache
*/
if (i!=0)
{
_Lcid_c[0] = _Lcid_c[i];
_Lcid_c[i] = buf1;
}
break;
}
else
{
buf2 = _Lcid_c[i];
_Lcid_c[i] = buf1;
buf1 = buf2;
}
}
if ( i == _LOC_CCACHE)
{
if ( __crtGetStringTypeA(NULL, CT_CTYPE1,
_first_127char,
sizeof(_first_127char),
out,
ploci->lc_codepage,
ploci->lc_handle[LC_CTYPE],
TRUE ))
{
int j;
for ( j = 0; j < sizeof(_first_127char); j++)
out[j] = out[j]&
(_UPPER|_LOWER|_DIGIT|_SPACE|_PUNCT|_CONTROL|_BLANK|_HEX|_ALPHA);
if ( !memcmp(out, _ctype_loc_style, (sizeof(_first_127char)/sizeof(char))*sizeof(short)))
{
_Lcid_c[0].is_clike = TRUE;
}
else
{
_Lcid_c[0].is_clike = FALSE;
}
}
else
_Lcid_c[0].is_clike = FALSE;
_Lcid_c[0].id = ploci->lc_codepage;
}
ploci->lc_clike = _Lcid_c[0].is_clike;
}
if ( category == LC_COLLATE )
ploci->lc_collate_cp = cptemp;
if (__lc_category[category].init(ploci))
{
/* restore previous state! */
ploci->lc_category[category].locale = oldlocale;
_free_crt(pch);
ploci->lc_handle[category] = oldhandle;
ploci->lc_codepage = oldcodepage;
return NULL; /* error if non-zero return */
}
/* locale set up successfully */
/* Cleanup */
if ((oldlocale != __clocalestr) &&
(InterlockedDecrement(ploci->lc_category[category].refcount) == 0)
)
{
_ASSERT(0);
_free_crt(ploci->lc_category[category].refcount);
_free_crt(ploci->lc_category[category].wrefcount);
ploci->lc_category[category].wlocale = NULL;
}
if (pch) {
*(int *)pch = 1;
}
ploci->lc_category[category].refcount = (int *)pch;
return ploci->lc_category[category].locale;
} /* _setlocale_set_cat */
static char * __cdecl _setlocale_get_all ( pthreadlocinfo ploci)
{
int i;
int same = 1;
char *pch = NULL;
size_t cch = 0;
int *refcount = NULL;
size_t refcountSize = 0;
/* allocate memory if necessary */
refcountSize = sizeof(int)+(MAX_LC_LEN+1) * (LC_MAX-LC_MIN+1) + CATNAMES_LEN;
if ( (refcount = _malloc_crt(refcountSize))
== NULL)
return NULL;
pch = (char *)(refcount + 1);
cch = refcountSize - sizeof(int);
*pch = '\0';
*refcount = 1;
for (i=LC_MIN+1; ; i++)
{
_strcats(pch, cch, 3, __lc_category[i].catname,"=",ploci->lc_category[i].locale);
if (i<LC_MAX)
{
_ERRCHECK(strcat_s(pch, cch, ";"));
if (strcmp(ploci->lc_category[i].locale, ploci->lc_category[i+1].locale))
same=0;
}
else
{
if (!same) {
if (ploci->lc_category[LC_ALL].refcount != NULL &&
InterlockedDecrement(ploci->lc_category[LC_ALL].refcount) == 0) {
_ASSERT(0);
_free_crt(ploci->lc_category[LC_ALL].refcount);
}
if (ploci->lc_category[LC_ALL].wrefcount != NULL &&
InterlockedDecrement(ploci->lc_category[LC_ALL].wrefcount) == 0) {
_ASSERT(0);
_free_crt(ploci->lc_category[LC_ALL].wrefcount);
}
ploci->lc_category[LC_ALL].wrefcount = NULL;
ploci->lc_category[LC_ALL].wlocale = NULL;
ploci->lc_category[LC_ALL].refcount = refcount;
return ploci->lc_category[LC_ALL].locale = pch;
} else {
_free_crt(refcount);
if (ploci->lc_category[LC_ALL].refcount != NULL &&
InterlockedDecrement(ploci->lc_category[LC_ALL].refcount) == 0) {
_ASSERT(0);
_free_crt(ploci->lc_category[LC_ALL].refcount);
}
if (ploci->lc_category[LC_ALL].wrefcount != NULL &&
InterlockedDecrement(ploci->lc_category[LC_ALL].wrefcount) == 0) {
_ASSERT(0);
_free_crt(ploci->lc_category[LC_ALL].wrefcount);
}
ploci->lc_category[LC_ALL].wrefcount = NULL;
ploci->lc_category[LC_ALL].wlocale = NULL;
ploci->lc_category[LC_ALL].refcount = NULL;
ploci->lc_category[LC_ALL].locale = NULL;
return ploci->lc_category[LC_CTYPE].locale;
}
}
}
} /* _setlocale_get_all */
char * _expandlocale (
char *expr,
char * output,
size_t sizeInChars,
LC_ID * id,
UINT * cp,
int category
)
{
_psetloc_struct _psetloc_data = &_getptd()->_setloc_data;
UINT *pcachecp = &_psetloc_data->_cachecp;
LC_ID *pcacheid = &_psetloc_data->_cacheid;
char *cachein = _psetloc_data->_cachein;
size_t cacheinSize = _countof(_psetloc_data->_cachein);
char *cacheout = _psetloc_data->_cacheout;
size_t cacheoutSize = _countof(_psetloc_data->_cacheout);
size_t charactersInExpression = 0;
if (!expr)
return NULL; /* error if no input */
if (output == NULL || sizeInChars == 0)
return NULL; /* error if no output */
if (((*expr=='C') && (!expr[1]))
) /* for "C" locale, just return */
{
_ERRCHECK(strcpy_s(output, sizeInChars, "C"));
if (id)
{
id->wLanguage = 0;
id->wCountry = 0;
id->wCodePage = 0;
}
if (cp)
{
*cp = CP_ACP; /* return to ANSI code page */
}
return output; /* "C" */
}
/* first, make sure we didn't just do this one */
charactersInExpression = strlen(expr);
if (charactersInExpression >= MAX_LC_LEN || /* we would never have cached this */
(strcmp(cacheout,expr) && strcmp(cachein,expr)))
{
/* do some real work */
LC_STRINGS names;
const char *source=NULL;
size_t charactersInSource = 0;
if (__lc_strtolc(&names, expr))
return NULL; /* syntax error */
if (!__get_qualified_locale(&names, pcacheid, &names))
return NULL; /* locale not recognized/supported */
/* begin: cache atomic section */
*pcachecp = pcacheid->wCodePage;
__lc_lctostr(cacheout, cacheoutSize, &names);
if (*expr && charactersInExpression < MAX_LC_LEN)
{
source = expr;
charactersInSource = charactersInExpression;
}
else
{
/* Don't cache "" empty string or over-long string */
source = "";
}
/* Ensure that whatever we are about to copy in will be null terminated */
_ERRCHECK(strncpy_s(cachein, cacheinSize, source, charactersInSource + 1));
/* end: cache atomic section */
}
if (id)
memcpy((void *)id, (void *)pcacheid, sizeof(*pcacheid)); /* possibly return LC_ID */
if (cp)
memcpy((void *)cp, (void *)pcachecp, sizeof(*pcachecp)); /* possibly return cp */
_ERRCHECK(strcpy_s(output, sizeInChars, cacheout));
return cacheout; /* return fully expanded locale string */
}
/* helpers */
int __cdecl __init_dummy(pthreadlocinfo ploci) /* default routine for locale initializer */
{
return 0;
}
void _strcats ( char *outstr, size_t sizeInBytes, int n, ...)
{
int i;
va_list substr;
va_start (substr, n);
for (i =0; i<n; i++)
{
_ERRCHECK(strcat_s(outstr, sizeInBytes, va_arg(substr, char *)));
}
va_end(substr);
}
int __lc_strtolc ( LC_STRINGS *names, const char *locale)
{
int i;
size_t len;
char ch;
memset((void *)names, '\0', sizeof(LC_STRINGS)); /* clear out result */
if (*locale=='\0')
return 0; /* trivial case */
/* only code page is given */
if (locale[0] == '.' && locale[1] != '\0')
{
_ERRCHECK(strncpy_s(names->szCodePage, _countof(names->szCodePage), &locale[1], MAX_CP_LEN-1));
/* Make sure to null terminate the string in case locale is > MAX_CP_LEN */
names->szCodePage[ MAX_CP_LEN -1] = 0;
return 0;
}
for (i=0; ; i++)
{
if (!(len=strcspn(locale,"_.,")))
return -1; /* syntax error */
ch = locale[len];
if ((i==0) && (len<MAX_LANG_LEN) && (ch!='.'))
_ERRCHECK(strncpy_s(names->szLanguage, _countof(names->szLanguage), locale, len));
else if ((i==1) && (len<MAX_CTRY_LEN) && (ch!='_'))
_ERRCHECK(strncpy_s(names->szCountry, _countof(names->szCountry), locale, len));
else if ((i==2) && (len<MAX_CP_LEN) && (ch=='\0' || ch==','))
_ERRCHECK(strncpy_s(names->szCodePage, _countof(names->szCodePage), locale, len));
else
return -1; /* error parsing locale string */
if (ch==',')
{
/* modifier not used in current implementation, but it
must be parsed to for POSIX/XOpen conformance */
/* strncpy(names->szModifier, locale, MAX_MODIFIER_LEN-1); */
break;
}
if (!ch)
break;
locale+=(len+1);
}
return 0;
}
void __lc_lctostr ( char *locale, size_t sizeInBytes, const LC_STRINGS *names)
{
_ERRCHECK(strcpy_s(locale, sizeInBytes, (char *)names->szLanguage));
if (*(names->szCountry))
_strcats(locale, sizeInBytes, 2, "_", names->szCountry);
if (*(names->szCodePage))
_strcats(locale, sizeInBytes, 2, ".", names->szCodePage);
}
#endif /* !defined (_WIN32) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -