commit 919200085f7eaffafa33ec3a5e50c2adbd046ab7 Author: Laslo Hunhold <d...@frign.de> AuthorDate: Sat Aug 27 01:46:41 2022 +0200 Commit: Laslo Hunhold <d...@frign.de> CommitDate: Sat Aug 27 02:03:50 2022 +0200
Add manual-template-engine and manuals for the case-conversion functions Given the undeniable redundancy within the manuals it makes a lot of sense to have a simple template-engine for generating the manual files on the fly. After fiddling with m4 and finding out for the third time that it just hasn't aged well I realized that it makes most sense to simply use heredocs within small shell-scripts. Signed-off-by: Laslo Hunhold <d...@frign.de> diff --git a/Makefile b/Makefile index 30c72d2..9cdb406 100644 --- a/Makefile +++ b/Makefile @@ -56,22 +56,71 @@ TEST =\ test/utf8-encode\ test/word\ +MAN_TEMPLATE =\ + man/template/to_case.sh + MAN3 =\ - man/grapheme_decode_utf8.3\ - man/grapheme_encode_utf8.3\ - man/grapheme_is_character_break.3\ - man/grapheme_next_character_break.3\ - man/grapheme_next_line_break.3\ - man/grapheme_next_sentence_break.3\ - man/grapheme_next_word_break.3\ - man/grapheme_next_character_break_utf8.3\ - man/grapheme_next_line_break_utf8.3\ - man/grapheme_next_sentence_break_utf8.3\ - man/grapheme_next_word_break_utf8.3\ - -MAN7 = man/libgrapheme.7 - -all: data/LICENSE libgrapheme.a libgrapheme.so + man/grapheme_decode_utf8\ + man/grapheme_encode_utf8\ + man/grapheme_is_character_break\ + man/grapheme_next_character_break\ + man/grapheme_next_line_break\ + man/grapheme_next_sentence_break\ + man/grapheme_next_word_break\ + man/grapheme_next_character_break_utf8\ + man/grapheme_next_line_break_utf8\ + man/grapheme_next_sentence_break_utf8\ + man/grapheme_next_word_break_utf8\ + man/grapheme_to_uppercase\ + man/grapheme_to_lowercase\ + man/grapheme_to_titlecase\ + +MAN7 =\ + man/libgrapheme\ + +all: data/LICENSE $(MAN3:=.3) $(MAN7:=.7) libgrapheme.a libgrapheme.so + +data/DerivedCoreProperties.txt: + wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/DerivedCoreProperties.txt + +data/EastAsianWidth.txt: + wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/EastAsianWidth.txt + +data/emoji-data.txt: + wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/emoji/emoji-data.txt + +data/GraphemeBreakProperty.txt: + wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/auxiliary/GraphemeBreakProperty.txt + +data/GraphemeBreakTest.txt: + wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/auxiliary/GraphemeBreakTest.txt + +data/LICENSE: + wget -O $@ https://www.unicode.org/license.txt + +data/LineBreak.txt: + wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/LineBreak.txt + +data/LineBreakTest.txt: + wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/auxiliary/LineBreakTest.txt + +data/SentenceBreakProperty.txt: + wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/auxiliary/SentenceBreakProperty.txt + +data/SentenceBreakTest.txt: + wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/auxiliary/SentenceBreakTest.txt + +data/SpecialCasing.txt: + wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/SpecialCasing.txt + +data/UnicodeData.txt: + wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/UnicodeData.txt + +data/WordBreakProperty.txt: + wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/auxiliary/WordBreakProperty.txt + +data/WordBreakTest.txt: + wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/auxiliary/WordBreakTest.txt benchmark/case.o: benchmark/case.c config.mk gen/word-test.h grapheme.h benchmark/util.h benchmark/character.o: benchmark/character.c config.mk gen/character-test.h grapheme.h benchmark/util.h @@ -137,47 +186,22 @@ gen/sentence-test.h: data/SentenceBreakTest.txt gen/sentence-test gen/word.h: data/WordBreakProperty.txt gen/word gen/word-test.h: data/WordBreakTest.txt gen/word-test -data/DerivedCoreProperties.txt: - wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/DerivedCoreProperties.txt - -data/EastAsianWidth.txt: - wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/EastAsianWidth.txt - -data/emoji-data.txt: - wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/emoji/emoji-data.txt - -data/GraphemeBreakProperty.txt: - wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/auxiliary/GraphemeBreakProperty.txt - -data/GraphemeBreakTest.txt: - wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/auxiliary/GraphemeBreakTest.txt - -data/LICENSE: - wget -O $@ https://www.unicode.org/license.txt - -data/LineBreak.txt: - wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/LineBreak.txt - -data/LineBreakTest.txt: - wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/auxiliary/LineBreakTest.txt - -data/SentenceBreakProperty.txt: - wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/auxiliary/SentenceBreakProperty.txt - -data/SentenceBreakTest.txt: - wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/auxiliary/SentenceBreakTest.txt - -data/SpecialCasing.txt: - wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/SpecialCasing.txt - -data/UnicodeData.txt: - wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/UnicodeData.txt - -data/WordBreakProperty.txt: - wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/auxiliary/WordBreakProperty.txt - -data/WordBreakTest.txt: - wget -O $@ https://www.unicode.org/Public/14.0.0/ucd/auxiliary/WordBreakTest.txt +man/grapheme_decode_utf8.3: man/grapheme_decode_utf8.sh config.mk +man/grapheme_encode_utf8.3: man/grapheme_encode_utf8.sh config.mk +man/grapheme_is_character_break.3: man/grapheme_is_character_break.sh config.mk +man/grapheme_next_character_break.3: man/grapheme_next_character_break.sh config.mk +man/grapheme_next_line_break.3: man/grapheme_next_line_break.sh config.mk +man/grapheme_next_sentence_break.3: man/grapheme_next_sentence_break.sh config.mk +man/grapheme_next_word_break.3: man/grapheme_next_word_break.sh config.mk +man/grapheme_next_character_break_utf8.3: man/grapheme_next_character_break_utf8.sh config.mk +man/grapheme_next_line_break_utf8.3: man/grapheme_next_line_break_utf8.sh config.mk +man/grapheme_next_sentence_break_utf8.3: man/grapheme_next_sentence_break_utf8.sh config.mk +man/grapheme_next_word_break_utf8.3: man/grapheme_next_word_break_utf8.sh config.mk +man/grapheme_to_uppercase.3: man/grapheme_to_uppercase.sh man/template/to_case.sh config.mk +man/grapheme_to_lowercase.3: man/grapheme_to_lowercase.sh man/template/to_case.sh config.mk +man/grapheme_to_titlecase.3: man/grapheme_to_titlecase.sh man/template/to_case.sh config.mk + +man/libgrapheme.7: man/libgrapheme.sh config.mk $(GEN:=.o): $(BUILD_CC) -c -o $@ $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) $(@:.o=.c) @@ -207,6 +231,12 @@ libgrapheme.a: $(SRC:=.o) libgrapheme.so: $(SRC:=.o) $(CC) -o $@ $(SOFLAGS) $(LDFLAGS) $(SRC:=.o) +$(MAN3:=.3): + SH=$(SH) $(SH) $(@:.3=.sh) > $@ + +$(MAN7:=.7): + SH=$(SH) $(SH) $(@:.7=.sh) > $@ + benchmark: $(BENCHMARK) for m in $(BENCHMARK); do ./$$m; done @@ -218,23 +248,23 @@ install: all mkdir -p "$(DESTDIR)$(INCPREFIX)" mkdir -p "$(DESTDIR)$(MANPREFIX)/man3" mkdir -p "$(DESTDIR)$(MANPREFIX)/man7" - cp -f $(MAN3) "$(DESTDIR)$(MANPREFIX)/man3" - cp -f $(MAN7) "$(DESTDIR)$(MANPREFIX)/man7" + cp -f $(MAN3:=.3) "$(DESTDIR)$(MANPREFIX)/man3" + cp -f $(MAN7:=.7) "$(DESTDIR)$(MANPREFIX)/man7" cp -f libgrapheme.a "$(DESTDIR)$(LIBPREFIX)" cp -f libgrapheme.so "$(DESTDIR)$(LIBPREFIX)" cp -f grapheme.h "$(DESTDIR)$(INCPREFIX)" $(LDCONFIG) uninstall: - for m in $(MAN3); do rm -f "$(DESTDIR)$(MANPREFIX)/man3/`basename $$m`"; done - for m in $(MAN7); do rm -f "$(DESTDIR)$(MANPREFIX)/man7/`basename $$m`"; done + for m in $(MAN3:=.3); do rm -f "$(DESTDIR)$(MANPREFIX)/man3/`basename $$m`"; done + for m in $(MAN7:=.7); do rm -f "$(DESTDIR)$(MANPREFIX)/man7/`basename $$m`"; done rm -f "$(DESTDIR)$(LIBPREFIX)/libgrapheme.a" rm -f "$(DESTDIR)$(LIBPREFIX)/libgrapheme.so" rm -f "$(DESTDIR)$(INCPREFIX)/grapheme.h" $(LDCONFIG) clean: - rm -f $(BENCHMARK:=.o) benchmark/util.o $(BENCHMARK) $(GEN:=.h) $(GEN:=.o) gen/util.o $(GEN) $(SRC:=.o) src/util.o $(TEST:=.o) test/util.o $(TEST) libgrapheme.a libgrapheme.so + rm -f $(BENCHMARK:=.o) benchmark/util.o $(BENCHMARK) $(GEN:=.h) $(GEN:=.o) gen/util.o $(GEN) $(SRC:=.o) src/util.o $(TEST:=.o) test/util.o $(TEST) libgrapheme.a libgrapheme.so $(MAN3:=.3) $(MAN7:=.7) clean-data: rm -f $(DATA) @@ -242,12 +272,13 @@ clean-data: dist: rm -rf "libgrapheme-$(VERSION)" mkdir "libgrapheme-$(VERSION)" - for m in benchmark data gen man src test; do mkdir "libgrapheme-$(VERSION)/$$m"; done + for m in benchmark data gen man man/template src test; do mkdir "libgrapheme-$(VERSION)/$$m"; done cp config.mk grapheme.h LICENSE Makefile README "libgrapheme-$(VERSION)" cp $(BENCHMARK:=.c) benchmark/util.c benchmark/util.h "libgrapheme-$(VERSION)/benchmark" cp $(DATA) "libgrapheme-$(VERSION)/data" cp $(GEN:=.c) gen/util.c gen/types.h gen/util.h "libgrapheme-$(VERSION)/gen" - cp $(MAN3) $(MAN7) "libgrapheme-$(VERSION)/man" + cp $(MAN3:=.sh) $(MAN7:=.sh) "libgrapheme-$(VERSION)/man" + cp $(MAN_TEMPLATE) "libgrapheme-$(VERSION)/man/template" cp $(SRC:=.c) src/util.h "libgrapheme-$(VERSION)/src" cp $(TEST:=.c) test/util.c test/util.h "libgrapheme-$(VERSION)/test" tar -cf - "libgrapheme-$(VERSION)" | gzip -c > "libgrapheme-$(VERSION).tar.gz" diff --git a/config.mk b/config.mk index 9e66400..4b30699 100644 --- a/config.mk +++ b/config.mk @@ -27,3 +27,4 @@ BUILD_CC = $(CC) AR = ar RANLIB = ranlib LDCONFIG = ldconfig # unset to not call ldconfig(1) after install/uninstall +SH = sh diff --git a/man/grapheme_decode_utf8.3 b/man/grapheme_decode_utf8.sh similarity index 99% rename from man/grapheme_decode_utf8.3 rename to man/grapheme_decode_utf8.sh index 6adcab5..88685c9 100644 --- a/man/grapheme_decode_utf8.3 +++ b/man/grapheme_decode_utf8.sh @@ -1,3 +1,4 @@ +cat << EOF .Dd 2022-08-26 .Dt GRAPHEME_DECODE_UTF8 3 .Os suckless.org @@ -98,3 +99,4 @@ print_cps_nul_terminated(const char *str) .Xr libgrapheme 7 .Sh AUTHORS .An Laslo Hunhold Aq Mt d...@frign.de +EOF diff --git a/man/grapheme_encode_utf8.3 b/man/grapheme_encode_utf8.sh similarity index 99% rename from man/grapheme_encode_utf8.3 rename to man/grapheme_encode_utf8.sh index ab78383..0c9b0be 100644 --- a/man/grapheme_encode_utf8.3 +++ b/man/grapheme_encode_utf8.sh @@ -1,3 +1,4 @@ +cat << EOF .Dd 2022-08-26 .Dt GRAPHEME_ENCODE_UTF8 3 .Os suckless.org @@ -99,3 +100,4 @@ cps_to_utf8_alloc(const uint_least32_t *cp, size_t cplen) .Xr libgrapheme 7 .Sh AUTHORS .An Laslo Hunhold Aq Mt d...@frign.de +EOF diff --git a/man/grapheme_is_character_break.3 b/man/grapheme_is_character_break.sh similarity index 99% rename from man/grapheme_is_character_break.3 rename to man/grapheme_is_character_break.sh index c847737..9adc83e 100644 --- a/man/grapheme_is_character_break.3 +++ b/man/grapheme_is_character_break.sh @@ -1,3 +1,4 @@ +cat << EOF .Dd 2022-08-26 .Dt GRAPHEME_IS_CHARACTER_BREAK 3 .Os suckless.org @@ -79,3 +80,4 @@ main(void) is compliant with the Unicode 14.0.0 specification. .Sh AUTHORS .An Laslo Hunhold Aq Mt d...@frign.de +EOF diff --git a/man/grapheme_next_character_break.3 b/man/grapheme_next_character_break.sh similarity index 98% rename from man/grapheme_next_character_break.3 rename to man/grapheme_next_character_break.sh index cb17639..c3135e7 100644 --- a/man/grapheme_next_character_break.3 +++ b/man/grapheme_next_character_break.sh @@ -1,3 +1,4 @@ +cat << EOF .Dd 2022-08-26 .Dt GRAPHEME_NEXT_CHARACTER_BREAK 3 .Os suckless.org @@ -53,3 +54,4 @@ is is compliant with the Unicode 14.0.0 specification. .Sh AUTHORS .An Laslo Hunhold Aq Mt d...@frign.de +EOF diff --git a/man/grapheme_next_character_break_utf8.3 b/man/grapheme_next_character_break_utf8.sh similarity index 99% rename from man/grapheme_next_character_break_utf8.3 rename to man/grapheme_next_character_break_utf8.sh index fd8d9f7..0bcf9ce 100644 --- a/man/grapheme_next_character_break_utf8.3 +++ b/man/grapheme_next_character_break_utf8.sh @@ -1,3 +1,4 @@ +cat << EOF .Dd 2022-08-26 .Dt GRAPHEME_NEXT_CHARACTER_BREAK_UTF8 3 .Os suckless.org @@ -93,3 +94,4 @@ main(void) is compliant with the Unicode 14.0.0 specification. .Sh AUTHORS .An Laslo Hunhold Aq Mt d...@frign.de +EOF diff --git a/man/grapheme_next_line_break.3 b/man/grapheme_next_line_break.sh similarity index 98% rename from man/grapheme_next_line_break.3 rename to man/grapheme_next_line_break.sh index 05d361d..7ef5fe8 100644 --- a/man/grapheme_next_line_break.3 +++ b/man/grapheme_next_line_break.sh @@ -1,3 +1,4 @@ +cat << EOF .Dd 2022-08-26 .Dt GRAPHEME_NEXT_LINE_BREAK 3 .Os suckless.org @@ -49,3 +50,4 @@ is is compliant with the Unicode 14.0.0 specification. .Sh AUTHORS .An Laslo Hunhold Aq Mt d...@frign.de +EOF diff --git a/man/grapheme_next_line_break_utf8.3 b/man/grapheme_next_line_break_utf8.sh similarity index 99% rename from man/grapheme_next_line_break_utf8.3 rename to man/grapheme_next_line_break_utf8.sh index 692d13d..c4a1d42 100644 --- a/man/grapheme_next_line_break_utf8.3 +++ b/man/grapheme_next_line_break_utf8.sh @@ -1,3 +1,4 @@ +cat << EOF .Dd 2022-08-26 .Dt GRAPHEME_NEXT_LINE_BREAK_UTF8 3 .Os suckless.org @@ -87,3 +88,4 @@ main(void) is compliant with the Unicode 14.0.0 specification. .Sh AUTHORS .An Laslo Hunhold Aq Mt d...@frign.de +EOF diff --git a/man/grapheme_next_sentence_break.3 b/man/grapheme_next_sentence_break.sh similarity index 98% rename from man/grapheme_next_sentence_break.3 rename to man/grapheme_next_sentence_break.sh index 723cf80..0366db6 100644 --- a/man/grapheme_next_sentence_break.3 +++ b/man/grapheme_next_sentence_break.sh @@ -1,3 +1,4 @@ +cat << EOF .Dd 2022-08-26 .Dt GRAPHEME_NEXT_SENTENCE_BREAK 3 .Os suckless.org @@ -52,3 +53,4 @@ is is compliant with the Unicode 14.0.0 specification. .Sh AUTHORS .An Laslo Hunhold Aq Mt d...@frign.de +EOF diff --git a/man/grapheme_next_sentence_break_utf8.3 b/man/grapheme_next_sentence_break_utf8.sh similarity index 99% rename from man/grapheme_next_sentence_break_utf8.3 rename to man/grapheme_next_sentence_break_utf8.sh index 858b9c0..b9fc5de 100644 --- a/man/grapheme_next_sentence_break_utf8.3 +++ b/man/grapheme_next_sentence_break_utf8.sh @@ -1,3 +1,4 @@ +cat << EOF .Dd 2022-08-26 .Dt GRAPHEME_NEXT_SENTENCE_BREAK_UTF8 3 .Os suckless.org @@ -90,3 +91,4 @@ main(void) is compliant with the Unicode 14.0.0 specification. .Sh AUTHORS .An Laslo Hunhold Aq Mt d...@frign.de +EOF diff --git a/man/grapheme_next_word_break.3 b/man/grapheme_next_word_break.sh similarity index 98% rename from man/grapheme_next_word_break.3 rename to man/grapheme_next_word_break.sh index c82c4fb..a72092a 100644 --- a/man/grapheme_next_word_break.3 +++ b/man/grapheme_next_word_break.sh @@ -1,3 +1,4 @@ +cat << EOF .Dd 2022-08-26 .Dt GRAPHEME_NEXT_WORD_BREAK 3 .Os suckless.org @@ -52,3 +53,4 @@ is is compliant with the Unicode 14.0.0 specification. .Sh AUTHORS .An Laslo Hunhold Aq Mt d...@frign.de +EOF diff --git a/man/grapheme_next_word_break_utf8.3 b/man/grapheme_next_word_break_utf8.sh similarity index 99% rename from man/grapheme_next_word_break_utf8.3 rename to man/grapheme_next_word_break_utf8.sh index 7bc3287..772fe71 100644 --- a/man/grapheme_next_word_break_utf8.3 +++ b/man/grapheme_next_word_break_utf8.sh @@ -1,3 +1,4 @@ +cat << EOF .Dd 2022-08-26 .Dt GRAPHEME_NEXT_WORD_BREAK_UTF8 3 .Os suckless.org @@ -90,3 +91,4 @@ main(void) is compliant with the Unicode 14.0.0 specification. .Sh AUTHORS .An Laslo Hunhold Aq Mt d...@frign.de +EOF diff --git a/man/grapheme_to_lowercase.sh b/man/grapheme_to_lowercase.sh new file mode 100644 index 0000000..7b90734 --- /dev/null +++ b/man/grapheme_to_lowercase.sh @@ -0,0 +1,2 @@ +CASE="lowercase"\ + $SH man/template/to_case.sh diff --git a/man/grapheme_to_titlecase.sh b/man/grapheme_to_titlecase.sh new file mode 100644 index 0000000..38096dd --- /dev/null +++ b/man/grapheme_to_titlecase.sh @@ -0,0 +1,2 @@ +CASE="titlecase"\ + $SH man/template/to_case.sh diff --git a/man/grapheme_to_uppercase.sh b/man/grapheme_to_uppercase.sh new file mode 100644 index 0000000..d451ea5 --- /dev/null +++ b/man/grapheme_to_uppercase.sh @@ -0,0 +1,2 @@ +CASE="uppercase"\ + $SH man/template/to_case.sh diff --git a/man/libgrapheme.7 b/man/libgrapheme.sh similarity index 99% rename from man/libgrapheme.7 rename to man/libgrapheme.sh index acbe4f7..040a659 100644 --- a/man/libgrapheme.7 +++ b/man/libgrapheme.sh @@ -1,3 +1,6 @@ +#!/bin/sh + +cat << EOF .Dd 2022-08-26 .Dt LIBGRAPHEME 7 .Os suckless.org @@ -39,12 +42,12 @@ example illustrating the possible usage. .Xr grapheme_encode_utf8 3 , .Xr grapheme_is_character_break 3 , .Xr grapheme_next_character_break 3 , -.Xr grapheme_next_line_break 3 , -.Xr grapheme_next_sentence_break 3 , -.Xr grapheme_next_word_break 3 , .Xr grapheme_next_character_break_utf8 3 , +.Xr grapheme_next_line_break 3 , .Xr grapheme_next_line_break_utf8 3 , +.Xr grapheme_next_sentence_break 3 , .Xr grapheme_next_sentence_break_utf8 3 , +.Xr grapheme_next_word_break 3 , .Xr grapheme_next_word_break_utf8 3 .Sh STANDARDS .Nm @@ -145,3 +148,4 @@ The motivation behind is to make unicode handling suck less and abide by the UNIX philosophy. .Sh AUTHORS .An Laslo Hunhold Aq Mt d...@frign.de +EOF diff --git a/man/template/to_case.sh b/man/template/to_case.sh new file mode 100644 index 0000000..eb12764 --- /dev/null +++ b/man/template/to_case.sh @@ -0,0 +1,58 @@ +cat << EOF +.Dd 2022-08-26 +.Dt GRAPHEME_TO_$(echo $CASE | tr [:lower:] [:upper:]) 3 +.Os suckless.org +.Sh NAME +.Nm grapheme_to_$CASE +.Nd convert codepoint array to $CASE +.Sh SYNOPSIS +.In grapheme.h +.Ft size_t +.Fn grapheme_to_$CASE "const uint_least32_t *src" "size_t srclen" "uint_least32_t *dest" "size_t destlen" +.Sh DESCRIPTION +The +.Fn grapheme_to_$CASE +function converts the codepoint array +.Va str +to $CASE and writes the result to +.Va dest +up to +.Va destlen , +unless +.Va dest +is set to +.Dv NULL . +.Pp +If +.Va len +is set to +.Dv SIZE_MAX +(stdint.h is already included by grapheme.h) the string +.Va src +is interpreted to be NUL-terminated and processing stops when a +NUL-byte is encountered. +.Pp +For UTF-8-encoded input data +.Xr grapheme_to_$CASE_utf8 3 +can be used instead. +.Sh RETURN VALUES +The +.Fn grapheme_to_$CASE +function returns the number of codepoints in the array resulting +from converting +.Va src +to $CASE, even if +.Va len +is not large enough or +.Va dest +is +.Dv NULL . +.Sh SEE ALSO +.Xr grapheme_to_$CASE_utf8 3 , +.Xr libgrapheme 7 +.Sh STANDARDS +.Fn grapheme_to_$CASE +is compliant with the Unicode 14.0.0 specification. +.Sh AUTHORS +.An Laslo Hunhold Aq Mt d...@frign.de +EOF