1 /* A substitute for ISO C99 <wctype.h>, for platforms that lack it.
3 Copyright (C) 2006-2022 Free Software Foundation, Inc.
5 This file is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as
7 published by the Free Software Foundation; either version 2.1 of the
8 License, or (at your option) any later version.
10 This file is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
18 /* Written by Bruno Haible and Paul Eggert. */
21 * ISO C 99 <wctype.h> for platforms that lack it.
22 * <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/wctype.h.html>
24 * iswctype, towctrans, towlower, towupper, wctrans, wctype,
25 * wctrans_t, and wctype_t are not yet implemented.
29 @PRAGMA_SYSTEM_HEADER@
33 #if (defined __MINGW32__ && defined __CTYPE_H_SOURCED__)
35 /* Special invocation convention:
36 - With MinGW 3.22, when <ctype.h> includes <wctype.h>, only some part of
37 <wctype.h> is being processed, which doesn't include the idempotency
40 #@INCLUDE_NEXT@ @NEXT_WCTYPE_H@
43 /* Normal invocation convention. */
45 #ifndef _@GUARD_PREFIX@_WCTYPE_H
48 /* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */
52 /* Native Windows (mingw, MSVC) have declarations of towupper, towlower, and
53 isw* functions in <ctype.h>, <wchar.h> as well as in <wctype.h>. Include
54 <ctype.h>, <wchar.h> in advance to avoid rpl_ prefix being added to the
56 #if defined _WIN32 && ! defined __CYGWIN__
61 /* Include the original <wctype.h> if it exists.
62 BeOS 5 has the functions but no <wctype.h>. */
63 /* The include_next requires a split double-inclusion guard. */
65 # @INCLUDE_NEXT@ @NEXT_WCTYPE_H@
68 #ifndef _@GUARD_PREFIX@_WCTYPE_H
69 #define _@GUARD_PREFIX@_WCTYPE_H
71 #ifndef _GL_INLINE_HEADER_BEGIN
72 #error "Please include config.h first."
74 _GL_INLINE_HEADER_BEGIN
75 #ifndef _GL_WCTYPE_INLINE
76 # define _GL_WCTYPE_INLINE _GL_INLINE
79 /* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
81 /* The definition of _GL_WARN_ON_USE is copied here. */
83 /* Solaris 2.6 <wctype.h> includes <widec.h> which includes <euc.h> which
84 #defines a number of identifiers in the application namespace. Revert
96 /* Define wint_t and WEOF. (Also done in wchar.in.h.) */
97 #if !@HAVE_WINT_T@ && !defined wint_t
103 /* mingw and MSVC define wint_t as 'unsigned short' in <crtdefs.h> or
104 <stddef.h>. This is too small: ISO C 99 section 7.24.1.(2) says that
105 wint_t must be "unchanged by default argument promotions". Override it. */
106 # if @GNULIBHEADERS_OVERRIDE_WINT_T@
107 # if !GNULIB_defined_wint_t
108 # if @HAVE_CRTDEFS_H@
109 # include <crtdefs.h>
113 typedef unsigned int rpl_wint_t
;
115 # define wint_t rpl_wint_t
116 # define GNULIB_defined_wint_t 1
120 # define WEOF ((wint_t) -1)
125 #if !GNULIB_defined_wctype_functions
127 /* FreeBSD 4.4 to 4.11 has <wctype.h> but lacks the functions.
128 Linux libc5 has <wctype.h> and the functions but they are broken.
129 mingw and MSVC have <wctype.h> and the functions but they take a wchar_t
130 as argument, not an rpl_wint_t.
131 Assume all 11 functions (all isw* except iswblank) are implemented the
132 same way, or not at all. */
133 # if ! @HAVE_ISWCNTRL@ || @REPLACE_ISWCNTRL@
135 # if @GNULIBHEADERS_OVERRIDE_WINT_T@ /* implies @REPLACE_ISWCNTRL@ */
137 _GL_WCTYPE_INLINE
int
138 rpl_iswalnum (wint_t wc
)
140 return ((wchar_t) wc
== wc
? iswalnum ((wchar_t) wc
) : 0);
143 _GL_WCTYPE_INLINE
int
144 rpl_iswalpha (wint_t wc
)
146 return ((wchar_t) wc
== wc
? iswalpha ((wchar_t) wc
) : 0);
149 _GL_WCTYPE_INLINE
int
150 rpl_iswblank (wint_t wc
)
152 return ((wchar_t) wc
== wc
? iswblank ((wchar_t) wc
) : 0);
155 _GL_WCTYPE_INLINE
int
156 rpl_iswcntrl (wint_t wc
)
158 return ((wchar_t) wc
== wc
? iswcntrl ((wchar_t) wc
) : 0);
161 _GL_WCTYPE_INLINE
int
162 rpl_iswdigit (wint_t wc
)
164 return ((wchar_t) wc
== wc
? wc
>= '0' && wc
<= '9' : 0);
167 _GL_WCTYPE_INLINE
int
168 rpl_iswgraph (wint_t wc
)
170 return ((wchar_t) wc
== wc
? iswgraph ((wchar_t) wc
) : 0);
173 _GL_WCTYPE_INLINE
int
174 rpl_iswlower (wint_t wc
)
176 return ((wchar_t) wc
== wc
? iswlower ((wchar_t) wc
) : 0);
179 _GL_WCTYPE_INLINE
int
180 rpl_iswprint (wint_t wc
)
182 return ((wchar_t) wc
== wc
? iswprint ((wchar_t) wc
) : 0);
185 _GL_WCTYPE_INLINE
int
186 rpl_iswpunct (wint_t wc
)
188 return ((wchar_t) wc
== wc
? iswpunct ((wchar_t) wc
) : 0);
191 _GL_WCTYPE_INLINE
int
192 rpl_iswspace (wint_t wc
)
194 return ((wchar_t) wc
== wc
? iswspace ((wchar_t) wc
) : 0);
197 _GL_WCTYPE_INLINE
int
198 rpl_iswupper (wint_t wc
)
200 return ((wchar_t) wc
== wc
? iswupper ((wchar_t) wc
) : 0);
203 _GL_WCTYPE_INLINE
int
204 rpl_iswxdigit (wint_t wc
)
206 return ((wchar_t) wc
== wc
207 ? (wc
>= '0' && wc
<= '9')
208 || ((wc
& ~0x20) >= 'A' && (wc
& ~0x20) <= 'F')
212 _GL_WCTYPE_INLINE
wint_t
213 rpl_towlower (wint_t wc
)
215 return ((wchar_t) wc
== wc
? (wchar_t) towlower ((wchar_t) wc
) : wc
);
218 _GL_WCTYPE_INLINE
wint_t
219 rpl_towupper (wint_t wc
)
221 return ((wchar_t) wc
== wc
? (wchar_t) towupper ((wchar_t) wc
) : wc
);
224 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
239 # define iswalnum rpl_iswalnum
240 # define iswalpha rpl_iswalpha
241 # define iswblank rpl_iswblank
242 # define iswcntrl rpl_iswcntrl
243 # define iswdigit rpl_iswdigit
244 # define iswgraph rpl_iswgraph
245 # define iswlower rpl_iswlower
246 # define iswprint rpl_iswprint
247 # define iswpunct rpl_iswpunct
248 # define iswspace rpl_iswspace
249 # define iswupper rpl_iswupper
250 # define iswxdigit rpl_iswxdigit
251 # define towlower rpl_towlower
252 # define towupper rpl_towupper
257 /* IRIX 5.3 has macros but no functions, its isw* macros refer to an
258 undefined variable _ctmp_ and to <ctype.h> macros like _P, and they
259 refer to system functions like _iswctype that are not in the
260 standard C library. Rather than try to get ancient buggy
261 implementations like this to work, just disable them. */
277 /* Linux libc5 has <wctype.h> and the functions but they are broken. */
278 # if @REPLACE_ISWCNTRL@
279 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
280 # define iswalnum rpl_iswalnum
281 # define iswalpha rpl_iswalpha
282 # define iswblank rpl_iswblank
283 # define iswcntrl rpl_iswcntrl
284 # define iswdigit rpl_iswdigit
285 # define iswgraph rpl_iswgraph
286 # define iswlower rpl_iswlower
287 # define iswprint rpl_iswprint
288 # define iswpunct rpl_iswpunct
289 # define iswspace rpl_iswspace
290 # define iswupper rpl_iswupper
291 # define iswxdigit rpl_iswxdigit
294 # if @REPLACE_TOWLOWER@
295 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
296 # define towlower rpl_towlower
297 # define towupper rpl_towupper
301 _GL_WCTYPE_INLINE
int
302 # if @REPLACE_ISWCNTRL@
309 return ((wc
>= '0' && wc
<= '9')
310 || ((wc
& ~0x20) >= 'A' && (wc
& ~0x20) <= 'Z'));
313 _GL_WCTYPE_INLINE
int
314 # if @REPLACE_ISWCNTRL@
321 return (wc
& ~0x20) >= 'A' && (wc
& ~0x20) <= 'Z';
324 _GL_WCTYPE_INLINE
int
325 # if @REPLACE_ISWCNTRL@
332 return wc
== ' ' || wc
== '\t';
335 _GL_WCTYPE_INLINE
int
336 # if @REPLACE_ISWCNTRL@
343 return (wc
& ~0x1f) == 0 || wc
== 0x7f;
346 _GL_WCTYPE_INLINE
int
347 # if @REPLACE_ISWDIGIT@
354 return wc
>= '0' && wc
<= '9';
357 _GL_WCTYPE_INLINE
int
358 # if @REPLACE_ISWCNTRL@
365 return wc
>= '!' && wc
<= '~';
368 _GL_WCTYPE_INLINE
int
369 # if @REPLACE_ISWCNTRL@
376 return wc
>= 'a' && wc
<= 'z';
379 _GL_WCTYPE_INLINE
int
380 # if @REPLACE_ISWCNTRL@
387 return wc
>= ' ' && wc
<= '~';
390 _GL_WCTYPE_INLINE
int
391 # if @REPLACE_ISWCNTRL@
398 return (wc
>= '!' && wc
<= '~'
399 && !((wc
>= '0' && wc
<= '9')
400 || ((wc
& ~0x20) >= 'A' && (wc
& ~0x20) <= 'Z')));
403 _GL_WCTYPE_INLINE
int
404 # if @REPLACE_ISWCNTRL@
411 return (wc
== ' ' || wc
== '\t'
412 || wc
== '\n' || wc
== '\v' || wc
== '\f' || wc
== '\r');
415 _GL_WCTYPE_INLINE
int
416 # if @REPLACE_ISWCNTRL@
423 return wc
>= 'A' && wc
<= 'Z';
426 _GL_WCTYPE_INLINE
int
427 # if @REPLACE_ISWXDIGIT@
434 return ((wc
>= '0' && wc
<= '9')
435 || ((wc
& ~0x20) >= 'A' && (wc
& ~0x20) <= 'F'));
438 _GL_WCTYPE_INLINE
wint_t
439 # if @REPLACE_TOWLOWER@
446 return (wc
>= 'A' && wc
<= 'Z' ? wc
- 'A' + 'a' : wc
);
449 _GL_WCTYPE_INLINE
wint_t
450 # if @REPLACE_TOWLOWER@
457 return (wc
>= 'a' && wc
<= 'z' ? wc
- 'a' + 'A' : wc
);
463 /* Only some of the functions are missing or broken. */
465 # if @GNULIB_ISWBLANK@ && (! @HAVE_ISWBLANK@ || @REPLACE_ISWBLANK@)
466 /* Only the iswblank function is missing. */
467 # if @REPLACE_ISWBLANK@
468 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
469 # define iswblank rpl_iswblank
471 _GL_FUNCDECL_RPL (iswblank
, int, (wint_t wc
));
473 _GL_FUNCDECL_SYS (iswblank
, int, (wint_t wc
));
477 # if @GNULIB_ISWDIGIT@
478 # if @REPLACE_ISWDIGIT@
479 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
481 # define iswdigit rpl_iswdigit
483 _GL_FUNCDECL_RPL (iswdigit
, int, (wint_t wc
));
487 # if @GNULIB_ISWXDIGIT@
488 # if @REPLACE_ISWXDIGIT@
489 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
491 # define iswxdigit rpl_iswxdigit
493 _GL_FUNCDECL_RPL (iswxdigit
, int, (wint_t wc
));
499 # if defined __MINGW32__ && !@GNULIBHEADERS_OVERRIDE_WINT_T@
501 /* On native Windows, wchar_t is uint16_t, and wint_t is uint32_t.
502 The functions towlower and towupper are implemented in the MSVCRT library
503 to take a wchar_t argument and return a wchar_t result. mingw declares
504 these functions to take a wint_t argument and return a wint_t result.
506 1. When the user passes an argument outside the range 0x0000..0xFFFF, the
507 function will look only at the lower 16 bits. This is allowed according
509 2. The return value is returned in the lower 16 bits of the result register.
510 The upper 16 bits are random: whatever happened to be in that part of the
511 result register. We need to fix this by adding a zero-extend from
512 wchar_t to wint_t after the call. */
514 _GL_WCTYPE_INLINE
wint_t
515 rpl_towlower (wint_t wc
)
517 return (wint_t) (wchar_t) towlower (wc
);
519 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
520 # define towlower rpl_towlower
523 _GL_WCTYPE_INLINE
wint_t
524 rpl_towupper (wint_t wc
)
526 return (wint_t) (wchar_t) towupper (wc
);
528 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
529 # define towupper rpl_towupper
532 # endif /* __MINGW32__ && !@GNULIBHEADERS_OVERRIDE_WINT_T@ */
534 # define GNULIB_defined_wctype_functions 1
537 #if @REPLACE_ISWCNTRL@
538 _GL_CXXALIAS_RPL (iswalnum
, int, (wint_t wc
));
540 _GL_CXXALIAS_SYS (iswalnum
, int, (wint_t wc
));
542 #if @REPLACE_ISWCNTRL@
543 _GL_CXXALIAS_RPL (iswalpha
, int, (wint_t wc
));
545 _GL_CXXALIAS_SYS (iswalpha
, int, (wint_t wc
));
547 #if @REPLACE_ISWCNTRL@
548 _GL_CXXALIAS_RPL (iswcntrl
, int, (wint_t wc
));
550 _GL_CXXALIAS_SYS (iswcntrl
, int, (wint_t wc
));
552 #if @GNULIB_ISWDIGIT@
553 # if @REPLACE_ISWDIGIT@
554 _GL_CXXALIAS_RPL (iswdigit
, int, (wint_t wc
));
556 _GL_CXXALIAS_SYS (iswdigit
, int, (wint_t wc
));
559 #if @REPLACE_ISWCNTRL@
560 _GL_CXXALIAS_RPL (iswgraph
, int, (wint_t wc
));
562 _GL_CXXALIAS_SYS (iswgraph
, int, (wint_t wc
));
564 #if @REPLACE_ISWCNTRL@
565 _GL_CXXALIAS_RPL (iswlower
, int, (wint_t wc
));
567 _GL_CXXALIAS_SYS (iswlower
, int, (wint_t wc
));
569 #if @REPLACE_ISWCNTRL@
570 _GL_CXXALIAS_RPL (iswprint
, int, (wint_t wc
));
572 _GL_CXXALIAS_SYS (iswprint
, int, (wint_t wc
));
574 #if @REPLACE_ISWCNTRL@
575 _GL_CXXALIAS_RPL (iswpunct
, int, (wint_t wc
));
577 _GL_CXXALIAS_SYS (iswpunct
, int, (wint_t wc
));
579 #if @REPLACE_ISWCNTRL@
580 _GL_CXXALIAS_RPL (iswspace
, int, (wint_t wc
));
582 _GL_CXXALIAS_SYS (iswspace
, int, (wint_t wc
));
584 #if @REPLACE_ISWCNTRL@
585 _GL_CXXALIAS_RPL (iswupper
, int, (wint_t wc
));
587 _GL_CXXALIAS_SYS (iswupper
, int, (wint_t wc
));
589 #if @GNULIB_ISWXDIGIT@
590 # if @REPLACE_ISWXDIGIT@
591 _GL_CXXALIAS_RPL (iswxdigit
, int, (wint_t wc
));
593 _GL_CXXALIAS_SYS (iswxdigit
, int, (wint_t wc
));
597 _GL_CXXALIASWARN (iswalnum
);
598 _GL_CXXALIASWARN (iswalpha
);
599 _GL_CXXALIASWARN (iswcntrl
);
600 _GL_CXXALIASWARN (iswdigit
);
601 _GL_CXXALIASWARN (iswgraph
);
602 _GL_CXXALIASWARN (iswlower
);
603 _GL_CXXALIASWARN (iswprint
);
604 _GL_CXXALIASWARN (iswpunct
);
605 _GL_CXXALIASWARN (iswspace
);
606 _GL_CXXALIASWARN (iswupper
);
607 _GL_CXXALIASWARN (iswxdigit
);
610 #if @GNULIB_ISWBLANK@
611 # if @REPLACE_ISWCNTRL@ || @REPLACE_ISWBLANK@
612 _GL_CXXALIAS_RPL (iswblank
, int, (wint_t wc
));
614 _GL_CXXALIAS_SYS (iswblank
, int, (wint_t wc
));
617 _GL_CXXALIASWARN (iswblank
);
622 # if !GNULIB_defined_wctype_t
623 typedef void * wctype_t;
624 # define GNULIB_defined_wctype_t 1
628 /* Get a descriptor for a wide character property. */
630 # if !@HAVE_WCTYPE_T@
631 _GL_FUNCDECL_SYS (wctype
, wctype_t, (const char *name
));
633 _GL_CXXALIAS_SYS (wctype
, wctype_t, (const char *name
));
635 _GL_CXXALIASWARN (wctype
);
637 #elif defined GNULIB_POSIXCHECK
639 # if HAVE_RAW_DECL_WCTYPE
640 _GL_WARN_ON_USE (wctype
, "wctype is unportable - "
641 "use gnulib module wctype for portability");
645 /* Test whether a wide character has a given property.
646 The argument WC must be either a wchar_t value or WEOF.
647 The argument DESC must have been returned by the wctype() function. */
648 #if @GNULIB_ISWCTYPE@
649 # if @GNULIBHEADERS_OVERRIDE_WINT_T@
650 # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
652 # define iswctype rpl_iswctype
654 _GL_FUNCDECL_RPL (iswctype
, int, (wint_t wc
, wctype_t desc
));
655 _GL_CXXALIAS_RPL (iswctype
, int, (wint_t wc
, wctype_t desc
));
657 # if !@HAVE_WCTYPE_T@
658 _GL_FUNCDECL_SYS (iswctype
, int, (wint_t wc
, wctype_t desc
));
660 _GL_CXXALIAS_SYS (iswctype
, int, (wint_t wc
, wctype_t desc
));
663 _GL_CXXALIASWARN (iswctype
);
665 #elif defined GNULIB_POSIXCHECK
667 # if HAVE_RAW_DECL_ISWCTYPE
668 _GL_WARN_ON_USE (iswctype
, "iswctype is unportable - "
669 "use gnulib module iswctype for portability");
673 #if @REPLACE_TOWLOWER@ || defined __MINGW32__
674 _GL_CXXALIAS_RPL (towlower
, wint_t, (wint_t wc
));
675 _GL_CXXALIAS_RPL (towupper
, wint_t, (wint_t wc
));
677 _GL_CXXALIAS_SYS (towlower
, wint_t, (wint_t wc
));
678 _GL_CXXALIAS_SYS (towupper
, wint_t, (wint_t wc
));
681 _GL_CXXALIASWARN (towlower
);
682 _GL_CXXALIASWARN (towupper
);
685 #if !@HAVE_WCTRANS_T@
686 # if !GNULIB_defined_wctrans_t
687 typedef void * wctrans_t;
688 # define GNULIB_defined_wctrans_t 1
692 /* Get a descriptor for a wide character case conversion. */
694 # if !@HAVE_WCTRANS_T@
695 _GL_FUNCDECL_SYS (wctrans
, wctrans_t, (const char *name
));
697 _GL_CXXALIAS_SYS (wctrans
, wctrans_t, (const char *name
));
699 _GL_CXXALIASWARN (wctrans
);
701 #elif defined GNULIB_POSIXCHECK
703 # if HAVE_RAW_DECL_WCTRANS
704 _GL_WARN_ON_USE (wctrans
, "wctrans is unportable - "
705 "use gnulib module wctrans for portability");
709 /* Perform a given case conversion on a wide character.
710 The argument WC must be either a wchar_t value or WEOF.
711 The argument DESC must have been returned by the wctrans() function. */
712 #if @GNULIB_TOWCTRANS@
713 # if !@HAVE_WCTRANS_T@
714 _GL_FUNCDECL_SYS (towctrans
, wint_t, (wint_t wc
, wctrans_t desc
));
716 _GL_CXXALIAS_SYS (towctrans
, wint_t, (wint_t wc
, wctrans_t desc
));
718 _GL_CXXALIASWARN (towctrans
);
720 #elif defined GNULIB_POSIXCHECK
722 # if HAVE_RAW_DECL_TOWCTRANS
723 _GL_WARN_ON_USE (towctrans
, "towctrans is unportable - "
724 "use gnulib module towctrans for portability");
728 _GL_INLINE_HEADER_END
730 #endif /* _@GUARD_PREFIX@_WCTYPE_H */
731 #endif /* _@GUARD_PREFIX@_WCTYPE_H */