📄 setlocal.c
字号:
/***
*setlocal.c - Contains the setlocale function
*
* Copyright (c) 1988-1998, Microsoft Corporation. All rights reserved.
*
*Purpose:
* Contains the setlocale() function.
*
*******************************************************************************/
#include <locale.h>
#if !defined (_WIN32)
static char _clocalestr[] = "C";
#else /* !defined (_WIN32) */
#include <cruntime.h>
#include <mtdll.h>
#include <malloc.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h> /* for strtol */
#include <setlocal.h>
#include <dbgint.h>
/* C locale */
static char _clocalestr[] = "C";
__declspec(selectany) struct {
const char * catname;
char * locale;
int (* init)(void);
} __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 }
};
#ifdef _MT
/*
* Flag indicating whether or not setlocale() is active. Its value is the
* number of setlocale() calls currently active.
*/
_CRTIMP int __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.
*/
_CRTIMP int __unguarded_readlc_active;
#endif /* _MT */
/* helper function prototypes */
char * _expandlocale(char *, char *, LC_ID *, UINT *, int);
void _strcats(char *, int, ...);
void __lc_lctostr(char *, const LC_STRINGS *);
int __lc_strtolc(LC_STRINGS *, const char *);
static char * __cdecl _setlocale_set_cat(int, const char *);
static char * __cdecl _setlocale_get_all(void);
#endif /* !defined (_WIN32) */
/***
*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.
*
*******************************************************************************/
char * __cdecl setlocale (
int _category,
const char *_locale
)
#if !defined (_WIN32)
{
if ( (_locale == NULL) ||
(_locale[0] == '\0') ||
( (_locale[0]=='C') && (_locale[1]=='\0')) )
return(_clocalestr);
else
return(NULL);
}
#else /* !defined (_WIN32) */
{
char * retval;
#ifdef _MT
int local_lock_flag;
#endif /* _MT */
/* Validate category */
if ((_category < LC_MIN) || (_category > LC_MAX))
return NULL;
#ifdef _MT
/*
* Assert setlocale lock
*/
_mlock( _SETLOCALE_LOCK );
local_lock_flag = 1;
/*
* Increment flag that indicates a setlocale is active.
*/
__setlc_active++;
/*
* Wait until all unguarded locale read operations have completed.
*/
while ( __unguarded_readlc_active )
Sleep( 1 );
#endif /* _MT */
/* Interpret locale */
if (_category != LC_ALL)
{
retval = (_locale) ? _setlocale_set_cat(_category,_locale) :
__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=s-p)) || (*s==';'))
{
#ifdef _MT
if ( local_lock_flag ) {
_munlock( _SETLOCALE_LOCK );
__setlc_active--;
}
#endif /* _MT */
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!=';'))
{
#ifdef _MT
if ( local_lock_flag ) {
_munlock( _SETLOCALE_LOCK );
__setlc_active--;
}
#endif /* _MT */
return NULL; /* syntax error */
}
if (i<=LC_MAX)
{
strncpy(lctemp, s, len);
lctemp[len]='\0'; /* null terminate string */
/* don't fail unless all categories fail */
if (_setlocale_set_cat(i,lctemp))
fLocaleSet++; /* record a success */
}
if (*(p = s+len)!='\0')
p++; /* skip ';', if present */
} while (*p);
retval = (fLocaleSet) ? _setlocale_get_all() : NULL;
} else { /* simple LC_ALL locale string */
/* confirm locale is supported, get expanded locale */
if (retval = _expandlocale((char *)_locale, lctemp, NULL, NULL, _category))
{
for (i=LC_MIN; i<=LC_MAX; i++)
{
if (i!=LC_ALL)
{
if (strcmp(lctemp, __lc_category[i].locale))
{
if (_setlocale_set_cat(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();
/* retval set above */
_free_crt(__lc_category[LC_ALL].locale);
__lc_category[LC_ALL].locale = NULL;
}
else
retval = (fLocaleSet) ? _setlocale_get_all() : NULL;
}
}
} else { /* LC_ALL & NULL */
retval = _setlocale_get_all ();
}
}
/* common exit point */
#ifdef _MT
if ( local_lock_flag ) {
_munlock( _SETLOCALE_LOCK );
__setlc_active--;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -