319 lines
4.6 KiB
C
319 lines
4.6 KiB
C
/* $NetBSD: multibyte.c,v 1.9 2019/08/01 12:28:53 martin Exp $ */
|
|
|
|
/*
|
|
* Ignore all multibyte sequences, removes all the citrus code.
|
|
* Probably only used by vfprintf() when parsing the format string.
|
|
* And possibly from libcurses if compiled with HAVE_WCHAR.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <wchar.h>
|
|
#include <wctype.h>
|
|
#include <ctype.h>
|
|
|
|
size_t
|
|
mbrtowc(wchar_t *wc, const char *str, size_t max_sz, mbstate_t *ps)
|
|
{
|
|
if (str == NULL)
|
|
return 0;
|
|
|
|
if (wc != NULL)
|
|
*wc = (unsigned char)*str;
|
|
|
|
return *str == '\0' ? 0 : 1;
|
|
}
|
|
|
|
size_t
|
|
mbrtowc_l(wchar_t *wc, const char *str, size_t max_sz, mbstate_t *ps, locale_t loc)
|
|
{
|
|
return mbrtowc(wc, str, max_sz, ps);
|
|
}
|
|
|
|
size_t
|
|
wcrtomb(char *str, wchar_t wc, mbstate_t *ps)
|
|
{
|
|
*str = wc & 0xFF;
|
|
return 1;
|
|
}
|
|
|
|
|
|
size_t
|
|
wcrtomb_l(char *str, wchar_t wc, mbstate_t *ps, locale_t loc)
|
|
{
|
|
return wcrtomb(str, wc, ps);
|
|
}
|
|
|
|
int
|
|
wctob(wint_t x)
|
|
{
|
|
return x;
|
|
}
|
|
|
|
int
|
|
wctob_l(wint_t x, locale_t loc)
|
|
{
|
|
return x;
|
|
}
|
|
|
|
wint_t
|
|
btowc(int x)
|
|
{
|
|
return x;
|
|
}
|
|
|
|
wint_t
|
|
btowc_l(int x, locale_t loc)
|
|
{
|
|
return x;
|
|
}
|
|
|
|
size_t
|
|
mbrlen(const char * __restrict p, size_t l, mbstate_t * __restrict v)
|
|
{
|
|
size_t i;
|
|
for (i = 0; i < l; i++)
|
|
if (p[i] == '\0')
|
|
return i;
|
|
return l;
|
|
}
|
|
|
|
|
|
size_t
|
|
mbrlen_l(const char * __restrict p, size_t l, mbstate_t * __restrict v,
|
|
locale_t loc)
|
|
{
|
|
return mbrlen(p, l, v);
|
|
}
|
|
|
|
int
|
|
mbsinit(const mbstate_t *s)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
size_t
|
|
mbsrtowcs(wchar_t * __restrict pwcs, const char ** __restrict s, size_t n,
|
|
mbstate_t * __restrict ps)
|
|
{
|
|
const char *p;
|
|
wchar_t *d;
|
|
size_t count;
|
|
|
|
for (p = *s, d = pwcs, count = 0;
|
|
count <= n;
|
|
count++, d++, p++)
|
|
{
|
|
if (mbrtowc(d, p, 1, ps) == 0)
|
|
break;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
|
|
size_t
|
|
mbsrtowcs_l(wchar_t * __restrict pwcs, const char ** __restrict s, size_t n,
|
|
mbstate_t * __restrict ps, locale_t loc)
|
|
{
|
|
return mbsrtowcs(pwcs, s, n, ps);
|
|
}
|
|
|
|
size_t
|
|
wcsrtombs(char * __restrict s, const wchar_t ** __restrict pwcs, size_t n,
|
|
mbstate_t * __restrict ps)
|
|
{
|
|
char *d;
|
|
const wchar_t *p;
|
|
size_t count;
|
|
|
|
for (p = *pwcs, d = s, count = 0;
|
|
count <= n && *p != 0;
|
|
count++, d++, p++)
|
|
{
|
|
wcrtomb(d, *p, ps);
|
|
}
|
|
*d = 0;
|
|
return count;
|
|
}
|
|
|
|
size_t
|
|
wcsrtombs_l(char * __restrict s, const wchar_t ** __restrict pwcs, size_t n,
|
|
mbstate_t * __restrict ps, locale_t loc)
|
|
{
|
|
return wcsrtombs(s, pwcs, n, ps);
|
|
}
|
|
|
|
size_t
|
|
_mb_cur_max_l(locale_t loc)
|
|
{
|
|
return MB_CUR_MAX;
|
|
}
|
|
|
|
wint_t
|
|
fgetwc(FILE *stream)
|
|
{
|
|
return fgetc(stream);
|
|
}
|
|
|
|
wint_t
|
|
fputwc(wchar_t wc, FILE *stream)
|
|
{
|
|
return fputc(wc & 0xFF, stream);
|
|
}
|
|
|
|
wint_t __fputwc_unlock(wchar_t wc, FILE *stream);
|
|
wint_t
|
|
__fputwc_unlock(wchar_t wc, FILE *stream)
|
|
{
|
|
return __sputc(wc & 0xFF, stream);
|
|
}
|
|
|
|
#define MAPSINGLE(CT) \
|
|
int \
|
|
isw##CT(wint_t wc) \
|
|
{ \
|
|
return is##CT(wc & 0xFF); \
|
|
}
|
|
|
|
MAPSINGLE(alnum)
|
|
MAPSINGLE(alpha)
|
|
MAPSINGLE(blank)
|
|
MAPSINGLE(cntrl)
|
|
MAPSINGLE(digit)
|
|
MAPSINGLE(graph)
|
|
MAPSINGLE(lower)
|
|
MAPSINGLE(print)
|
|
MAPSINGLE(punct)
|
|
MAPSINGLE(space)
|
|
MAPSINGLE(upper)
|
|
MAPSINGLE(xdigit)
|
|
|
|
int
|
|
iswspace_l(wint_t wc, locale_t loc)
|
|
{
|
|
return iswspace(wc);
|
|
}
|
|
|
|
struct wct_entry_hack {
|
|
const char *name;
|
|
int (*predicate)(wint_t);
|
|
};
|
|
|
|
#define WCTENTRY(T) { .name= #T , .predicate= isw##T },
|
|
static const struct wct_entry_hack my_wcts[] = {
|
|
{ .name = NULL },
|
|
WCTENTRY(alnum)
|
|
WCTENTRY(alpha)
|
|
WCTENTRY(blank)
|
|
WCTENTRY(cntrl)
|
|
WCTENTRY(digit)
|
|
WCTENTRY(graph)
|
|
WCTENTRY(lower)
|
|
WCTENTRY(print)
|
|
WCTENTRY(punct)
|
|
WCTENTRY(space)
|
|
WCTENTRY(upper)
|
|
WCTENTRY(xdigit)
|
|
};
|
|
|
|
wctype_t
|
|
wctype(const char *charclass)
|
|
{
|
|
|
|
for (size_t i = 1; i < __arraycount(my_wcts); i++)
|
|
if (strcmp(charclass, my_wcts[i].name) == 0)
|
|
return (wctype_t)i;
|
|
|
|
return (wctype_t)0;
|
|
}
|
|
|
|
int
|
|
iswctype(wint_t wc, wctype_t charclass)
|
|
{
|
|
size_t ndx = (size_t)charclass;
|
|
|
|
if (ndx < 1 || ndx >= __arraycount(my_wcts))
|
|
return 0;
|
|
|
|
return my_wcts[ndx].predicate(wc);
|
|
}
|
|
|
|
size_t
|
|
wcslen(const wchar_t *s)
|
|
{
|
|
size_t l;
|
|
|
|
if (s == NULL)
|
|
return 0;
|
|
|
|
for (l = 0; *s; l++)
|
|
s++;
|
|
|
|
return l;
|
|
}
|
|
|
|
int
|
|
wcswidth(const wchar_t *pwcs, size_t n)
|
|
{
|
|
int cols;
|
|
|
|
if (pwcs == NULL)
|
|
return 0;
|
|
|
|
if (*pwcs == 0)
|
|
return 0;
|
|
|
|
for (cols = 0; *pwcs && n > 0; cols++)
|
|
if (!isprint(*pwcs & 0xFF))
|
|
return -1;
|
|
return cols;
|
|
}
|
|
|
|
int
|
|
wcwidth(wchar_t wc)
|
|
{
|
|
if (wc == 0)
|
|
return 0;
|
|
if (!isprint(wc & 0xFF))
|
|
return -1;
|
|
return 1;
|
|
}
|
|
|
|
wchar_t *
|
|
wmemchr(const wchar_t *s, wchar_t c, size_t n)
|
|
{
|
|
|
|
if (s == NULL)
|
|
return NULL;
|
|
while (*s != 0 && *s != c)
|
|
s++;
|
|
if (*s != 0)
|
|
return __UNCONST(s);
|
|
return NULL;
|
|
}
|
|
|
|
wchar_t *
|
|
wmemcpy(wchar_t * restrict s1, const wchar_t * restrict s2, size_t n)
|
|
{
|
|
wchar_t *p;
|
|
|
|
for (p = s1; n > 0; n--)
|
|
*p++ = *s2++;
|
|
|
|
return s1;
|
|
}
|
|
|
|
wint_t
|
|
towlower(wint_t wc)
|
|
{
|
|
return tolower(wc & 0xFF);
|
|
}
|
|
|
|
wint_t
|
|
towupper(wint_t wc)
|
|
{
|
|
return toupper(wc & 0xFF);
|
|
}
|
|
|
|
|