/*** *initctyp.c - contains __init_ctype * * Copyright (c) 1991-1998, Microsoft Corporation. All rights reserved. * *Purpose: * Contains the locale-category initialization function: __init_ctype(). * * Each initialization function sets up locale-specific information * for their category, for use by functions which are affected by * their locale category. * * *** For internal use by setlocale() only *** * *******************************************************************************/ #include #include #include #include #include #include #include #include #include #define _CTABSIZE 257 /* size of ctype tables */ /*** *int __init_ctype() - initialization for LC_CTYPE locale category. * *Purpose: * In non-C locales, preread ctype tables for chars and wide-chars. * Old tables are freed when new tables are fully established, else * the old tables remain intact (as if original state unaltered). * The leadbyte table is implemented as the high bit in ctype1. * * In the C locale, ctype tables are freed, and pointers point to * the static ctype table. * * Tables contain 257 entries: -1 to 256. * Table pointers point to entry 0 (to allow index -1). * *Entry: * None. * *Exit: * 0 success * 1 fail * *Exceptions: * *******************************************************************************/ int __cdecl __init_ctype ( void ) { /* non-C locale table for char's */ static unsigned short *ctype1 = NULL; /* keep around until next time */ unsigned short *newctype1; /* temp new table */ /* non-C locale table for wchar_t's */ static unsigned short *wctype1 = NULL; /* keep around until next time */ unsigned short *newwctype1; /* temp new table */ unsigned char *cbuffer = NULL; /* char working buffer */ wchar_t *wbuffer = NULL; /* wchar_t working buffer */ int i; /* general purpose counter */ unsigned char *cp; /* char pointer */ wchar_t *wcp; /* wide char pointer */ CPINFO lpCPInfo; /* struct for use with GetCPInfo */ /* allocate and set up buffers before destroying old ones */ /* codepage will be restored by setlocale if error */ if (__lc_handle[LC_CTYPE] != _CLOCALEHANDLE) { if (__lc_codepage == 0) { /* code page was not specified */ if ( __getlocaleinfo( LC_INT_TYPE, MAKELCID(__lc_id[LC_CTYPE].wLanguage, SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE, (char **)&__lc_codepage ) ) goto error_cleanup; } /* allocate new buffers for tables */ newctype1 = (unsigned short *) _malloc_crt(_CTABSIZE * sizeof(unsigned short)); newwctype1 = (unsigned short *) _malloc_crt(_CTABSIZE * sizeof(unsigned short)); cbuffer = (unsigned char *) _malloc_crt (_CTABSIZE * sizeof(char)); wbuffer = (wchar_t *) _malloc_crt (_CTABSIZE * sizeof(wchar_t)); if (!newctype1 || !newwctype1 || !cbuffer || !wbuffer) goto error_cleanup; /* construct string composed of first 256 chars in sequence */ for (cp=cbuffer, i=0; i<_CTABSIZE-1; i++) *cp++ = (unsigned char)i; if (GetCPInfo( __lc_codepage, &lpCPInfo) == FALSE) goto error_cleanup; if (lpCPInfo.MaxCharSize > MB_LEN_MAX) goto error_cleanup; __mb_cur_max = (unsigned short) lpCPInfo.MaxCharSize; /* zero out leadbytes so GetStringType doesn't interpret as multi-byte chars */ if (__mb_cur_max > 1) { for (cp = (unsigned char *)lpCPInfo.LeadByte; cp[0] && cp[1]; cp += 2) { for (i = cp[0]; i <= cp[1]; i++) cbuffer[i] = 0; } } /* convert to newctype1 table - ignore invalid char errors */ if ( __crtGetStringTypeA( CT_CTYPE1, cbuffer, _CTABSIZE-1, newctype1+1, 0, 0, FALSE ) == FALSE ) goto error_cleanup; *newctype1 = 0; /* entry for EOF */ /* construct wide char string composed of first 256 chars in sequence */ for (wcp=wbuffer, i=0; i<_CTABSIZE-1; i++) *wcp++ = (wchar_t)i; /* convert to newwctype1 table */ if ( __crtGetStringTypeW( CT_CTYPE1, wbuffer, _CTABSIZE-1, newwctype1+1, 0, 0 ) == FALSE ) goto error_cleanup; *newwctype1 = 0; /* entry for EOF */ /* ignore DefaultChar */ /* mark lead-byte entries in newctype1 table */ if (__mb_cur_max > 1) { for (cp = (unsigned char *)lpCPInfo.LeadByte; cp[0] && cp[1]; cp += 2) { for (i = cp[0]; i <= cp[1]; i++) newctype1[i+1] = _LEADBYTE; } } /* set pointers to point to entry 0 of tables */ _pctype = newctype1 + 1; _pwctype = newwctype1 + 1; /* free old tables */ if (ctype1) _free_crt (ctype1); ctype1 = newctype1; if (wctype1) _free_crt (wctype1); wctype1 = newwctype1; /* cleanup and return success */ _free_crt (cbuffer); _free_crt (wbuffer); return 0; error_cleanup: _free_crt (newctype1); _free_crt (newwctype1); _free_crt (cbuffer); _free_crt (wbuffer); return 1; } else { /* set pointers to static C-locale table */ _pctype = _ctype + 1; _pwctype = _ctype + 1; /* free dynamic locale-specific tables */ _free_crt (ctype1); _free_crt (wctype1); ctype1 = NULL; wctype1 = NULL; return 0; } }