aboutsummaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'contrib')
-rw-r--r--contrib/arm-optimized-routines/README2
-rw-r--r--contrib/arm-optimized-routines/math/cosf.c2
-rw-r--r--contrib/arm-optimized-routines/math/sincosf.c2
-rw-r--r--contrib/arm-optimized-routines/math/sincosf.h2
-rw-r--r--contrib/arm-optimized-routines/math/sinf.c2
-rw-r--r--contrib/arm-optimized-routines/string/aarch64/memcmp.S237
-rw-r--r--contrib/arm-optimized-routines/string/aarch64/memcpy-sve.S180
-rw-r--r--contrib/arm-optimized-routines/string/aarch64/stpcpy-mte.S10
-rw-r--r--contrib/arm-optimized-routines/string/aarch64/strcmp-mte.S189
-rw-r--r--contrib/arm-optimized-routines/string/aarch64/strcmp.S234
-rw-r--r--contrib/arm-optimized-routines/string/aarch64/strcpy-mte.S161
-rw-r--r--contrib/arm-optimized-routines/string/aarch64/strcpy.S394
-rw-r--r--contrib/arm-optimized-routines/string/aarch64/strncmp-mte.S307
-rw-r--r--contrib/arm-optimized-routines/string/aarch64/strncmp.S234
-rw-r--r--contrib/arm-optimized-routines/string/bench/memcpy.c165
-rw-r--r--contrib/arm-optimized-routines/string/bench/memset.c243
-rw-r--r--contrib/arm-optimized-routines/string/bench/strlen.c14
-rw-r--r--contrib/arm-optimized-routines/string/include/stringlib.h6
-rw-r--r--contrib/arm-optimized-routines/string/test/memcpy.c3
-rw-r--r--contrib/arm-optimized-routines/string/test/memmove.c3
-rw-r--r--contrib/arm-optimized-routines/string/test/stpcpy.c3
-rw-r--r--contrib/arm-optimized-routines/string/test/strcmp.c3
-rw-r--r--contrib/arm-optimized-routines/string/test/strcpy.c3
-rw-r--r--contrib/arm-optimized-routines/string/test/strncmp.c3
-rw-r--r--contrib/bionic-x86_64-string/avx2-memset-kbl.S160
-rw-r--r--contrib/bionic-x86_64-string/cache.h36
-rw-r--r--contrib/bionic-x86_64-string/sse2-memmove-slm.S518
-rw-r--r--contrib/bionic-x86_64-string/sse2-memset-slm.S149
-rw-r--r--contrib/bionic-x86_64-string/sse2-stpcpy-slm.S33
-rw-r--r--contrib/bionic-x86_64-string/sse2-stpncpy-slm.S34
-rw-r--r--contrib/bionic-x86_64-string/sse2-strcat-slm.S87
-rw-r--r--contrib/bionic-x86_64-string/sse2-strcpy-slm.S1921
-rw-r--r--contrib/bionic-x86_64-string/sse2-strlen-slm.S294
-rw-r--r--contrib/bionic-x86_64-string/sse2-strncat-slm.S33
-rw-r--r--contrib/bionic-x86_64-string/sse2-strncpy-slm.S33
-rw-r--r--contrib/bionic-x86_64-string/sse4-memcmp-slm.S1799
-rw-r--r--contrib/bionic-x86_64-string/ssse3-strcmp-slm.S1925
-rw-r--r--contrib/bionic-x86_64-string/ssse3-strncmp-slm.S33
-rw-r--r--contrib/blacklist/bin/blacklistctl.c3
-rw-r--r--contrib/blacklist/bin/blacklistd.852
-rw-r--r--contrib/blacklist/bin/blacklistd.c48
-rw-r--r--contrib/blacklist/bin/blacklistd.conf.56
-rw-r--r--contrib/blacklist/bin/conf.c30
-rw-r--r--contrib/blacklist/bin/run.c2
-rw-r--r--contrib/blacklist/bin/support.c2
-rw-r--r--contrib/blacklist/diff/proftpd.diff2
-rw-r--r--contrib/blacklist/lib/bl.c3
-rw-r--r--contrib/blacklist/lib/blacklist.c2
-rw-r--r--contrib/blacklist/lib/libblacklist.318
-rw-r--r--contrib/blacklist/libexec/blacklistd-helper5
-rw-r--r--contrib/bsddialog/.gitignore25
-rw-r--r--contrib/bsddialog/CHANGELOG133
-rw-r--r--contrib/bsddialog/GNUMakefile6
-rw-r--r--contrib/bsddialog/Makefile6
-rw-r--r--contrib/bsddialog/README.md47
-rw-r--r--contrib/bsddialog/bsddialog.1366
-rw-r--r--contrib/bsddialog/bsddialog.c1424
-rw-r--r--contrib/bsddialog/examples_library/calendar.c55
-rwxr-xr-xcontrib/bsddialog/examples_library/compile4
-rw-r--r--contrib/bsddialog/examples_library/datebox.c4
-rw-r--r--contrib/bsddialog/examples_library/form.c14
-rw-r--r--contrib/bsddialog/examples_library/formw.c61
-rw-r--r--contrib/bsddialog/examples_library/timebox.c4
-rw-r--r--contrib/bsddialog/examples_utility/calendar.sh34
-rwxr-xr-xcontrib/bsddialog/examples_utility/form.sh10
-rwxr-xr-xcontrib/bsddialog/examples_utility/mixedform.sh6
-rwxr-xr-xcontrib/bsddialog/examples_utility/passwordform.sh10
-rwxr-xr-xcontrib/bsddialog/examples_utility/timebox.sh3
-rw-r--r--contrib/bsddialog/lib/GNUMakefile12
-rw-r--r--contrib/bsddialog/lib/Makefile8
-rw-r--r--contrib/bsddialog/lib/barbox.c80
-rw-r--r--contrib/bsddialog/lib/bsddialog.3201
-rw-r--r--contrib/bsddialog/lib/bsddialog.h28
-rw-r--r--contrib/bsddialog/lib/bsddialog_theme.h17
-rw-r--r--contrib/bsddialog/lib/calendarbox.c520
-rw-r--r--contrib/bsddialog/lib/formbox.c1150
-rw-r--r--contrib/bsddialog/lib/infobox.c6
-rw-r--r--contrib/bsddialog/lib/lib_util.c558
-rw-r--r--contrib/bsddialog/lib/lib_util.h19
-rw-r--r--contrib/bsddialog/lib/libbsddialog.c23
-rw-r--r--contrib/bsddialog/lib/menubox.c201
-rw-r--r--contrib/bsddialog/lib/messagebox.c97
-rw-r--r--contrib/bsddialog/lib/textbox.c117
-rw-r--r--contrib/bsddialog/lib/theme.c188
-rw-r--r--contrib/bsddialog/lib/timebox.c198
-rw-r--r--contrib/bsddialog/util_theme.c353
-rw-r--r--contrib/bsddialog/util_theme.h (renamed from contrib/telnet/telnetd/telnetd.h)33
-rw-r--r--contrib/bsnmp/snmp_mibII/mibII_ip.c14
-rw-r--r--contrib/capsicum-test/syscalls.h13
-rw-r--r--contrib/diff/src/diff3.c1
-rw-r--r--contrib/dma/mail.c11
-rw-r--r--contrib/expat/COPYING2
-rw-r--r--contrib/expat/Changes119
-rw-r--r--contrib/expat/Makefile.in1
-rw-r--r--contrib/expat/README.md22
-rwxr-xr-xcontrib/expat/buildconf.sh4
-rw-r--r--contrib/expat/configure.ac14
-rw-r--r--contrib/expat/doc/Makefile.in1
-rw-r--r--contrib/expat/doc/reference.html10
-rw-r--r--contrib/expat/doc/xmlwf.12
-rw-r--r--contrib/expat/doc/xmlwf.xml2
-rw-r--r--contrib/expat/examples/Makefile.in1
-rw-r--r--contrib/expat/examples/elements.c47
-rw-r--r--contrib/expat/examples/outline.c77
-rw-r--r--contrib/expat/expat_config.h.in5
-rwxr-xr-xcontrib/expat/fix-xmltest-log.sh4
-rw-r--r--contrib/expat/lib/Makefile.am5
-rw-r--r--contrib/expat/lib/Makefile.in6
-rw-r--r--contrib/expat/lib/expat.h4
-rw-r--r--contrib/expat/lib/internal.h6
-rw-r--r--contrib/expat/lib/siphash.h2
-rw-r--r--contrib/expat/lib/xmlparse.c64
-rw-r--r--contrib/expat/lib/xmltok.c7
-rw-r--r--contrib/expat/lib/xmltok_impl.c6
-rw-r--r--contrib/expat/lib/xmltok_impl.h2
-rw-r--r--contrib/expat/tests/Makefile.in1
-rw-r--r--contrib/expat/tests/benchmark/Makefile.in1
-rw-r--r--contrib/expat/tests/runtests.c253
-rw-r--r--contrib/expat/xmlwf/Makefile.in1
-rw-r--r--contrib/expat/xmlwf/win32filemap.c5
-rw-r--r--contrib/expat/xmlwf/xmlwf.c3
-rw-r--r--contrib/file/ChangeLog29
-rw-r--r--contrib/file/Makefile.in57
-rw-r--r--contrib/file/acinclude.m43
-rw-r--r--contrib/file/aclocal.m479
-rwxr-xr-xcontrib/file/compile6
-rwxr-xr-xcontrib/file/config.guess1424
-rw-r--r--contrib/file/config.h.in102
-rwxr-xr-xcontrib/file/config.sub669
-rwxr-xr-xcontrib/file/configure6905
-rw-r--r--contrib/file/configure.ac2
-rwxr-xr-xcontrib/file/depcomp2
-rw-r--r--contrib/file/doc/Makefile.in10
-rw-r--r--contrib/file/doc/file.man4
-rw-r--r--contrib/file/doc/magic.man8
-rw-r--r--contrib/file/magic/Magdir/animation6
-rw-r--r--contrib/file/magic/Magdir/archive33
-rw-r--r--contrib/file/magic/Magdir/audio176
-rw-r--r--contrib/file/magic/Magdir/burp7
-rw-r--r--contrib/file/magic/Magdir/cafebabe8
-rw-r--r--contrib/file/magic/Magdir/compress3
-rw-r--r--contrib/file/magic/Magdir/database6
-rw-r--r--contrib/file/magic/Magdir/der14
-rw-r--r--contrib/file/magic/Magdir/filesystems28
-rw-r--r--contrib/file/magic/Magdir/fonts3
-rw-r--r--contrib/file/magic/Magdir/gentoo80
-rw-r--r--contrib/file/magic/Magdir/images133
-rw-r--r--contrib/file/magic/Magdir/javascript101
-rw-r--r--contrib/file/magic/Magdir/jpeg119
-rw-r--r--contrib/file/magic/Magdir/linux33
-rw-r--r--contrib/file/magic/Magdir/luks117
-rw-r--r--contrib/file/magic/Magdir/mail.news50
-rw-r--r--contrib/file/magic/Magdir/msdos223
-rw-r--r--contrib/file/magic/Magdir/msooxml5
-rw-r--r--contrib/file/magic/Magdir/ole2compounddocs14
-rw-r--r--contrib/file/magic/Magdir/pascal27
-rw-r--r--contrib/file/magic/Magdir/python118
-rw-r--r--contrib/file/magic/Magdir/riff23
-rw-r--r--contrib/file/magic/Magdir/ringdove45
-rw-r--r--contrib/file/magic/Magdir/sgml4
-rw-r--r--contrib/file/magic/Magdir/sniffer7
-rw-r--r--contrib/file/magic/Magdir/sql8
-rw-r--r--contrib/file/magic/Magdir/subtitle38
-rw-r--r--contrib/file/magic/Magdir/virtual8
-rw-r--r--contrib/file/magic/Magdir/webassembly4
-rw-r--r--contrib/file/magic/Magdir/windows176
-rw-r--r--contrib/file/magic/Magdir/wordprocessors174
-rw-r--r--contrib/file/magic/Magdir/xo659
-rw-r--r--contrib/file/magic/Makefile.am6
-rw-r--r--contrib/file/magic/Makefile.in16
-rwxr-xr-xcontrib/file/missing2
-rw-r--r--contrib/file/python/Makefile.in12
-rw-r--r--contrib/file/python/magic.py36
-rw-r--r--contrib/file/python/tests.py8
-rw-r--r--contrib/file/src/Makefile.in17
-rw-r--r--contrib/file/src/apprentice.c16
-rw-r--r--contrib/file/src/compress.c5
-rw-r--r--contrib/file/src/der.c20
-rw-r--r--contrib/file/src/encoding.c8
-rw-r--r--contrib/file/src/file.c155
-rw-r--r--contrib/file/src/file.h17
-rw-r--r--contrib/file/src/file_opts.h4
-rw-r--r--contrib/file/src/fmtcheck.c3
-rw-r--r--contrib/file/src/funcs.c5
-rw-r--r--contrib/file/src/is_json.c50
-rw-r--r--contrib/file/src/is_tar.c15
-rw-r--r--contrib/file/src/memtest.c4
-rw-r--r--contrib/file/src/print.c28
-rw-r--r--contrib/file/src/readelf.c16
-rw-r--r--contrib/file/src/seccomp.c4
-rw-r--r--contrib/file/src/softmagic.c61
-rw-r--r--contrib/file/src/strlcat.c3
-rw-r--r--contrib/file/src/strlcpy.c3
-rw-r--r--contrib/file/src/vasprintf.c4
-rw-r--r--contrib/file/tests/Makefile.am14
-rw-r--r--contrib/file/tests/Makefile.in26
-rw-r--r--contrib/file/tests/dsd64-dff.result1
-rw-r--r--contrib/file/tests/dsd64-dff.testfilebin0 -> 17922 bytes
-rw-r--r--contrib/file/tests/dsd64-dsf.result1
-rw-r--r--contrib/file/tests/dsd64-dsf.testfilebin0 -> 20707 bytes
-rw-r--r--contrib/file/tests/gpkg-1-zst.result1
-rw-r--r--contrib/file/tests/gpkg-1-zst.testfilebin0 -> 1024 bytes
-rw-r--r--contrib/file/tests/json6.result1
-rw-r--r--contrib/file/tests/json6.testfile1
-rw-r--r--contrib/file/tests/json7.result1
-rw-r--r--contrib/file/tests/json7.testfile1
-rw-r--r--contrib/file/tests/json8.result1
-rw-r--r--contrib/file/tests/json8.testfile1
-rw-r--r--contrib/file/tests/jsonlines1.result1
-rw-r--r--contrib/file/tests/jsonlines1.testfile2
-rw-r--r--contrib/file/tests/test.c2
-rw-r--r--contrib/jemalloc/src/pages.c16
-rw-r--r--contrib/less/LICENSE2
-rw-r--r--contrib/less/NEWS67
-rw-r--r--contrib/less/README6
-rw-r--r--contrib/less/brac.c6
-rw-r--r--contrib/less/ch.c19
-rw-r--r--contrib/less/charset.c18
-rw-r--r--contrib/less/charset.h2
-rw-r--r--contrib/less/cmd.h3
-rw-r--r--contrib/less/cmdbuf.c91
-rw-r--r--contrib/less/command.c76
-rw-r--r--contrib/less/compose.uni20
-rw-r--r--contrib/less/cvt.c2
-rw-r--r--contrib/less/decode.c30
-rw-r--r--contrib/less/edit.c4
-rw-r--r--contrib/less/filename.c19
-rw-r--r--contrib/less/fmt.uni3
-rw-r--r--contrib/less/forwback.c126
-rw-r--r--contrib/less/funcs.h18
-rw-r--r--contrib/less/help.c20
-rw-r--r--contrib/less/ifile.c2
-rw-r--r--contrib/less/input.c22
-rw-r--r--contrib/less/jump.c2
-rw-r--r--contrib/less/less.h4
-rw-r--r--contrib/less/less.hlp18
-rw-r--r--contrib/less/less.nro99
-rw-r--r--contrib/less/lessecho.c45
-rw-r--r--contrib/less/lessecho.nro2
-rw-r--r--contrib/less/lesskey.c11
-rw-r--r--contrib/less/lesskey.h2
-rw-r--r--contrib/less/lesskey.nro155
-rw-r--r--contrib/less/lesskey_parse.c238
-rw-r--r--contrib/less/lglob.h2
-rw-r--r--contrib/less/line.c285
-rw-r--r--contrib/less/linenum.c23
-rw-r--r--contrib/less/lsystem.c9
-rw-r--r--contrib/less/main.c25
-rw-r--r--contrib/less/mark.c5
-rw-r--r--contrib/less/optfunc.c131
-rw-r--r--contrib/less/option.c4
-rw-r--r--contrib/less/option.h2
-rw-r--r--contrib/less/opttbl.c65
-rw-r--r--contrib/less/os.c18
-rw-r--r--contrib/less/output.c11
-rw-r--r--contrib/less/pattern.c13
-rw-r--r--contrib/less/pattern.h34
-rw-r--r--contrib/less/pckeys.h2
-rw-r--r--contrib/less/position.c3
-rw-r--r--contrib/less/position.h2
-rw-r--r--contrib/less/prompt.c29
-rw-r--r--contrib/less/screen.c62
-rw-r--r--contrib/less/scrsize.c2
-rw-r--r--contrib/less/search.c59
-rw-r--r--contrib/less/signal.c2
-rw-r--r--contrib/less/tags.c8
-rw-r--r--contrib/less/ttyin.c63
-rw-r--r--contrib/less/ubin.uni2
-rw-r--r--contrib/less/version.c27
-rw-r--r--contrib/less/wide.uni25
-rw-r--r--contrib/less/xbuf.c23
-rw-r--r--contrib/less/xbuf.h3
-rw-r--r--contrib/llvm-project/clang/lib/Basic/Targets/X86.h8
-rw-r--r--contrib/llvm-project/libcxx/include/type_traits2
-rw-r--r--contrib/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp4
-rw-r--r--contrib/ofed/libibverbs/examples/rc_pingpong.c2
-rw-r--r--contrib/ofed/libibverbs/examples/srq_pingpong.c2
-rw-r--r--contrib/ofed/libibverbs/examples/uc_pingpong.c2
-rw-r--r--contrib/ofed/libibverbs/examples/ud_pingpong.c2
-rw-r--r--contrib/ofed/libibverbs/examples/xsrq_pingpong.c2
-rw-r--r--contrib/openbsm/libbsm/bsm_io.c2
-rw-r--r--contrib/opie/BUG-REPORT85
-rw-r--r--contrib/opie/COPYRIGHT.NRL68
-rw-r--r--contrib/opie/INSTALL178
-rw-r--r--contrib/opie/License.TIN45
-rw-r--r--contrib/opie/Makefile.in327
-rw-r--r--contrib/opie/README508
-rw-r--r--contrib/opie/acconfig.h226
-rw-r--r--contrib/opie/config.h.in450
-rw-r--r--contrib/opie/config.testeflag12
-rwxr-xr-xcontrib/opie/configure5247
-rw-r--r--contrib/opie/configure.in562
-rw-r--r--contrib/opie/configure.munger.in16
-rw-r--r--contrib/opie/ftpcmd.y1290
-rw-r--r--contrib/opie/glob.c668
-rw-r--r--contrib/opie/install-sh238
-rw-r--r--contrib/opie/libmissing/Makefile.in34
-rw-r--r--contrib/opie/libmissing/bogus.c1
-rw-r--r--contrib/opie/libmissing/endutent.c19
-rw-r--r--contrib/opie/libmissing/getutline.c63
-rw-r--r--contrib/opie/libmissing/pututline.c64
-rw-r--r--contrib/opie/libmissing/setutent.c18
-rw-r--r--contrib/opie/libopie/Makefile.in35
-rw-r--r--contrib/opie/libopie/accessfile.c171
-rw-r--r--contrib/opie/libopie/atob8.c76
-rw-r--r--contrib/opie/libopie/btoa8.c34
-rw-r--r--contrib/opie/libopie/btoe.c2267
-rw-r--r--contrib/opie/libopie/btoh.c36
-rw-r--r--contrib/opie/libopie/challenge.c79
-rw-r--r--contrib/opie/libopie/generator.c398
-rw-r--r--contrib/opie/libopie/getsequence.c27
-rw-r--r--contrib/opie/libopie/getutmpentry.c85
-rw-r--r--contrib/opie/libopie/hash.c78
-rw-r--r--contrib/opie/libopie/hashlen.c69
-rw-r--r--contrib/opie/libopie/insecure.c172
-rw-r--r--contrib/opie/libopie/keycrunch.c66
-rw-r--r--contrib/opie/libopie/lock.c255
-rw-r--r--contrib/opie/libopie/login.c124
-rw-r--r--contrib/opie/libopie/logwtmp.c197
-rw-r--r--contrib/opie/libopie/lookup.c31
-rw-r--r--contrib/opie/libopie/md4c.c267
-rw-r--r--contrib/opie/libopie/md5c.c304
-rw-r--r--contrib/opie/libopie/newseed.c96
-rw-r--r--contrib/opie/libopie/open.c77
-rw-r--r--contrib/opie/libopie/parsechallenge.c82
-rw-r--r--contrib/opie/libopie/passcheck.c50
-rw-r--r--contrib/opie/libopie/passwd.c76
-rw-r--r--contrib/opie/libopie/randomchallenge.c50
-rw-r--r--contrib/opie/libopie/readpass.c315
-rw-r--r--contrib/opie/libopie/readrec.c167
-rw-r--r--contrib/opie/libopie/unlock.c103
-rw-r--r--contrib/opie/libopie/verify.c222
-rw-r--r--contrib/opie/libopie/version.c29
-rw-r--r--contrib/opie/libopie/writerec.c89
-rw-r--r--contrib/opie/opie.4340
-rw-r--r--contrib/opie/opie.h179
-rw-r--r--contrib/opie/opie_cfg.h184
-rw-r--r--contrib/opie/opieaccess.589
-rw-r--r--contrib/opie/opieauto.c386
-rw-r--r--contrib/opie/opieftpd.8294
-rw-r--r--contrib/opie/opieftpd.c1715
-rw-r--r--contrib/opie/opiegen.190
-rw-r--r--contrib/opie/opiegen.c88
-rw-r--r--contrib/opie/opieinfo.1100
-rw-r--r--contrib/opie/opieinfo.c105
-rw-r--r--contrib/opie/opiekey.1173
-rw-r--r--contrib/opie/opiekey.c347
-rw-r--r--contrib/opie/opiekeys.569
-rw-r--r--contrib/opie/opielogin.1131
-rw-r--r--contrib/opie/opielogin.c1458
-rw-r--r--contrib/opie/opiepasswd.1178
-rw-r--r--contrib/opie/opiepasswd.c442
-rw-r--r--contrib/opie/opieserv.182
-rw-r--r--contrib/opie/opieserv.c83
-rw-r--r--contrib/opie/opiesu.1101
-rw-r--r--contrib/opie/opiesu.c512
-rw-r--r--contrib/opie/opietest.c310
-rw-r--r--contrib/opie/permsfile.c167
-rw-r--r--contrib/opie/popen.c216
-rw-r--r--contrib/sendmail/FREEBSD-upgrade2
-rw-r--r--contrib/sendmail/src/sendmail.h5
-rwxr-xr-xcontrib/sqlite3/configure20
-rw-r--r--contrib/sqlite3/configure.ac2
-rw-r--r--contrib/sqlite3/shell.c5097
-rw-r--r--contrib/sqlite3/sqlite3.c5227
-rw-r--r--contrib/sqlite3/sqlite3.h119
-rw-r--r--contrib/sqlite3/sqlite3ext.h8
-rw-r--r--contrib/sqlite3/sqlite3rc.h2
-rw-r--r--contrib/sqlite3/tea/Makefile.in189
-rwxr-xr-xcontrib/sqlite3/tea/configure1991
-rw-r--r--contrib/sqlite3/tea/configure.ac94
-rw-r--r--contrib/sqlite3/tea/pkgIndex.tcl.in15
-rw-r--r--contrib/sqlite3/tea/tclconfig/tcl.m41153
-rw-r--r--contrib/sqlite3/tea/win/makefile.vc13
-rw-r--r--contrib/telnet/telnet/telnet.18
-rw-r--r--contrib/telnet/telnetd/authenc.c86
-rw-r--r--contrib/telnet/telnetd/defs.h254
-rw-r--r--contrib/telnet/telnetd/ext.h218
-rw-r--r--contrib/telnet/telnetd/global.c48
-rw-r--r--contrib/telnet/telnetd/pathnames.h52
-rw-r--r--contrib/telnet/telnetd/slc.c480
-rw-r--r--contrib/telnet/telnetd/state.c1631
-rw-r--r--contrib/telnet/telnetd/sys_term.c1252
-rw-r--r--contrib/telnet/telnetd/telnetd.8613
-rw-r--r--contrib/telnet/telnetd/telnetd.c1256
-rw-r--r--contrib/telnet/telnetd/termstat.c628
-rw-r--r--contrib/telnet/telnetd/utility.c1077
-rw-r--r--contrib/tzcode/stdtime/ctime.36
-rw-r--r--contrib/tzdata/Makefile250
-rw-r--r--contrib/tzdata/NEWS372
-rw-r--r--contrib/tzdata/africa249
-rw-r--r--contrib/tzdata/antarctica32
-rw-r--r--contrib/tzdata/asia457
-rw-r--r--contrib/tzdata/australasia141
-rw-r--r--contrib/tzdata/backward294
-rw-r--r--contrib/tzdata/backzone694
-rw-r--r--contrib/tzdata/calendars4
-rw-r--r--contrib/tzdata/checklinks.awk24
-rw-r--r--contrib/tzdata/etcetera25
-rw-r--r--contrib/tzdata/europe684
-rw-r--r--contrib/tzdata/leap-seconds.list8
-rw-r--r--contrib/tzdata/leapseconds8
-rw-r--r--[-rwxr-xr-x]contrib/tzdata/leapseconds.awk0
-rw-r--r--contrib/tzdata/northamerica429
-rw-r--r--contrib/tzdata/pacificnew29
-rw-r--r--contrib/tzdata/southamerica89
-rw-r--r--contrib/tzdata/systemv39
-rw-r--r--contrib/tzdata/theory.html42
-rw-r--r--contrib/tzdata/version2
-rwxr-xr-xcontrib/tzdata/yearistype.sh39
-rw-r--r--contrib/tzdata/ziguard.awk321
-rw-r--r--contrib/tzdata/zishrink.awk62
-rw-r--r--contrib/tzdata/zone.tab35
-rw-r--r--contrib/tzdata/zone1970.tab106
-rwxr-xr-xcontrib/tzdata/zoneinfo2tdf.pl53
-rw-r--r--contrib/unbound/Makefile.in8
-rw-r--r--contrib/unbound/acx_nlnetlabs.m46
-rw-r--r--contrib/unbound/compat/arc4random.c8
-rwxr-xr-xcontrib/unbound/config.guess10
-rw-r--r--contrib/unbound/config.h.in15
-rwxr-xr-xcontrib/unbound/config.sub29
-rwxr-xr-xcontrib/unbound/configure101
-rw-r--r--contrib/unbound/configure.ac14
-rw-r--r--contrib/unbound/daemon/acl_list.c447
-rw-r--r--contrib/unbound/daemon/acl_list.h39
-rw-r--r--contrib/unbound/daemon/daemon.c61
-rw-r--r--contrib/unbound/daemon/daemon.h2
-rw-r--r--contrib/unbound/daemon/remote.c6
-rw-r--r--contrib/unbound/daemon/stats.c27
-rw-r--r--contrib/unbound/daemon/worker.c152
-rw-r--r--contrib/unbound/daemon/worker.h4
-rw-r--r--contrib/unbound/dnstap/dtstream.c4
-rw-r--r--contrib/unbound/dnstap/unbound-dnstap-socket.c4
-rw-r--r--contrib/unbound/doc/Changelog110
-rw-r--r--contrib/unbound/doc/README2
-rw-r--r--contrib/unbound/doc/example.conf.in68
-rw-r--r--contrib/unbound/doc/libunbound.3.in4
-rw-r--r--contrib/unbound/doc/unbound-anchor.8.in2
-rw-r--r--contrib/unbound/doc/unbound-checkconf.8.in2
-rw-r--r--contrib/unbound/doc/unbound-control.8.in2
-rw-r--r--contrib/unbound/doc/unbound-host.1.in2
-rw-r--r--contrib/unbound/doc/unbound.8.in4
-rw-r--r--contrib/unbound/doc/unbound.conf.5.in63
-rw-r--r--contrib/unbound/edns-subnet/addrtree.c9
-rw-r--r--contrib/unbound/edns-subnet/addrtree.h7
-rw-r--r--contrib/unbound/edns-subnet/subnetmod.c43
-rw-r--r--contrib/unbound/iterator/iter_delegpt.c3
-rw-r--r--contrib/unbound/iterator/iter_delegpt.h2
-rw-r--r--contrib/unbound/iterator/iter_hints.c2
-rw-r--r--contrib/unbound/iterator/iter_resptype.c6
-rw-r--r--contrib/unbound/iterator/iter_utils.c3
-rw-r--r--contrib/unbound/iterator/iter_utils.h9
-rw-r--r--contrib/unbound/iterator/iterator.c127
-rw-r--r--contrib/unbound/iterator/iterator.h2
-rw-r--r--contrib/unbound/libunbound/libunbound.c4
-rw-r--r--contrib/unbound/respip/respip.c10
-rw-r--r--contrib/unbound/respip/respip.h6
-rw-r--r--contrib/unbound/services/authzone.c6
-rw-r--r--contrib/unbound/services/cache/dns.c3
-rw-r--r--contrib/unbound/services/cache/infra.c37
-rw-r--r--contrib/unbound/services/cache/infra.h7
-rw-r--r--contrib/unbound/services/listen_dnsport.c134
-rw-r--r--contrib/unbound/services/listen_dnsport.h14
-rw-r--r--contrib/unbound/services/localzone.c12
-rw-r--r--contrib/unbound/services/mesh.c20
-rw-r--r--contrib/unbound/services/mesh.h11
-rw-r--r--contrib/unbound/services/outside_network.c162
-rw-r--r--contrib/unbound/services/outside_network.h24
-rw-r--r--contrib/unbound/services/rpz.c28
-rw-r--r--contrib/unbound/services/view.c5
-rw-r--r--contrib/unbound/smallapp/unbound-checkconf.c18
-rw-r--r--contrib/unbound/smallapp/unbound-control.c4
-rw-r--r--contrib/unbound/testdata/iter_ghost_sub.rpl309
-rw-r--r--contrib/unbound/testdata/iter_ghost_timewindow.rpl391
-rw-r--r--contrib/unbound/util/config_file.c54
-rw-r--r--contrib/unbound/util/config_file.h20
-rw-r--r--contrib/unbound/util/configlexer.lex6
-rw-r--r--contrib/unbound/util/configparser.y129
-rw-r--r--contrib/unbound/util/fptr_wlist.c1
-rw-r--r--contrib/unbound/util/net_help.c6
-rw-r--r--contrib/unbound/util/net_help.h8
-rw-r--r--contrib/unbound/util/netevent.c836
-rw-r--r--contrib/unbound/util/netevent.h42
-rw-r--r--contrib/unbound/util/proxy_protocol.c139
-rw-r--r--contrib/unbound/util/proxy_protocol.h131
-rw-r--r--contrib/unbound/util/storage/dnstree.c13
-rw-r--r--contrib/unbound/util/storage/dnstree.h10
-rw-r--r--contrib/unbound/util/tube.c42
-rw-r--r--contrib/unbound/util/tube.h8
-rw-r--r--contrib/wireguard-tools/.gitignore21
-rw-r--r--contrib/wireguard-tools/config.c650
-rw-r--r--contrib/wireguard-tools/config.h27
-rw-r--r--contrib/wireguard-tools/containers.h107
-rw-r--r--contrib/wireguard-tools/ctype.h29
-rw-r--r--contrib/wireguard-tools/curve25519-fiat32.h860
-rw-r--r--contrib/wireguard-tools/curve25519-hacl64.h784
-rw-r--r--contrib/wireguard-tools/curve25519.c98
-rw-r--r--contrib/wireguard-tools/curve25519.h24
-rw-r--r--contrib/wireguard-tools/encoding.c125
-rw-r--r--contrib/wireguard-tools/encoding.h24
-rw-r--r--contrib/wireguard-tools/genkey.c99
-rw-r--r--contrib/wireguard-tools/ipc-freebsd.h360
-rw-r--r--contrib/wireguard-tools/ipc-uapi-unix.h119
-rw-r--r--contrib/wireguard-tools/ipc-uapi.h297
-rw-r--r--contrib/wireguard-tools/ipc.c98
-rw-r--r--contrib/wireguard-tools/ipc.h17
-rw-r--r--contrib/wireguard-tools/man/wg.8258
-rw-r--r--contrib/wireguard-tools/pubkey.c50
-rw-r--r--contrib/wireguard-tools/set.c41
-rw-r--r--contrib/wireguard-tools/setconf.c156
-rw-r--r--contrib/wireguard-tools/show.c454
-rw-r--r--contrib/wireguard-tools/showconf.c103
-rw-r--r--contrib/wireguard-tools/subcommands.h17
-rw-r--r--contrib/wireguard-tools/terminal.c76
-rw-r--r--contrib/wireguard-tools/terminal.h51
-rw-r--r--contrib/wireguard-tools/version.h3
-rw-r--r--contrib/wireguard-tools/wg.c66
-rw-r--r--contrib/xz/AUTHORS2
-rw-r--r--contrib/xz/ChangeLog2120
-rw-r--r--contrib/xz/FREEBSD-Xlist2
-rw-r--r--contrib/xz/README2
-rw-r--r--contrib/xz/THANKS19
-rw-r--r--contrib/xz/src/common/mythread.h7
-rw-r--r--contrib/xz/src/common/tuklib_cpucores.c9
-rw-r--r--contrib/xz/src/common/tuklib_physmem.c2
-rw-r--r--contrib/xz/src/liblzma/api/lzma.h3
-rw-r--r--contrib/xz/src/liblzma/api/lzma/base.h13
-rw-r--r--contrib/xz/src/liblzma/api/lzma/block.h3
-rw-r--r--contrib/xz/src/liblzma/api/lzma/container.h20
-rw-r--r--contrib/xz/src/liblzma/api/lzma/filter.h4
-rw-r--r--contrib/xz/src/liblzma/api/lzma/version.h2
-rw-r--r--contrib/xz/src/liblzma/api/lzma/vli.h2
-rw-r--r--contrib/xz/src/liblzma/check/crc32_x86.S13
-rw-r--r--contrib/xz/src/liblzma/check/crc64_x86.S11
-rw-r--r--contrib/xz/src/liblzma/common/alone_decoder.c2
-rw-r--r--contrib/xz/src/liblzma/common/auto_decoder.c4
-rw-r--r--contrib/xz/src/liblzma/common/block_buffer_encoder.c18
-rw-r--r--contrib/xz/src/liblzma/common/block_decoder.c79
-rw-r--r--contrib/xz/src/liblzma/common/common.c14
-rw-r--r--contrib/xz/src/liblzma/common/common.h28
-rw-r--r--contrib/xz/src/liblzma/common/filter_common.c18
-rw-r--r--contrib/xz/src/liblzma/common/hardware_cputhreads.c12
-rw-r--r--contrib/xz/src/liblzma/common/index.c16
-rw-r--r--contrib/xz/src/liblzma/common/index_hash.c11
-rw-r--r--contrib/xz/src/liblzma/common/memcmplen.h3
-rw-r--r--contrib/xz/src/liblzma/common/stream_decoder.c28
-rw-r--r--contrib/xz/src/liblzma/common/stream_encoder_mt.c49
-rw-r--r--contrib/xz/src/liblzma/liblzma_generic.map (renamed from contrib/xz/src/liblzma/liblzma.map)6
-rw-r--r--contrib/xz/src/liblzma/liblzma_linux.map123
-rw-r--r--contrib/xz/src/liblzma/lz/lz_decoder.c10
-rw-r--r--contrib/xz/src/liblzma/lz/lz_decoder.h8
-rw-r--r--contrib/xz/src/liblzma/lz/lz_encoder.c32
-rw-r--r--contrib/xz/src/liblzma/lzma/lzma2_decoder.c2
-rw-r--r--contrib/xz/src/liblzma/lzma/lzma2_encoder.c3
-rw-r--r--contrib/xz/src/liblzma/lzma/lzma_decoder.c104
-rw-r--r--contrib/xz/src/liblzma/lzma/lzma_encoder.c3
-rw-r--r--[-rwxr-xr-x]contrib/xz/src/liblzma/validate_map.sh113
-rw-r--r--contrib/xz/src/xz/coder.c43
-rw-r--r--contrib/xz/src/xz/file_io.c26
-rw-r--r--contrib/xz/src/xz/hardware.c6
-rw-r--r--contrib/xz/src/xz/message.c12
-rw-r--r--contrib/xz/src/xz/xz.1150
562 files changed, 44372 insertions, 48129 deletions
diff --git a/contrib/arm-optimized-routines/README b/contrib/arm-optimized-routines/README
index ae465e93fea7..9e1a34fdc65d 100644
--- a/contrib/arm-optimized-routines/README
+++ b/contrib/arm-optimized-routines/README
@@ -9,7 +9,7 @@ contributor-agreement.pdf. This is needed so upstreaming code
to projects that require copyright assignment is possible.
Regular quarterly releases are tagged as vYY.MM, the latest
-release is v20.11.
+release is v21.02.
Source code layout:
diff --git a/contrib/arm-optimized-routines/math/cosf.c b/contrib/arm-optimized-routines/math/cosf.c
index f29f19474e23..67a3798b573e 100644
--- a/contrib/arm-optimized-routines/math/cosf.c
+++ b/contrib/arm-optimized-routines/math/cosf.c
@@ -22,7 +22,7 @@ cosf (float y)
int n;
const sincos_t *p = &__sincosf_table[0];
- if (abstop12 (y) < abstop12 (pio4))
+ if (abstop12 (y) < abstop12 (pio4f))
{
double x2 = x * x;
diff --git a/contrib/arm-optimized-routines/math/sincosf.c b/contrib/arm-optimized-routines/math/sincosf.c
index 9746f1c22e6c..6fb299d10309 100644
--- a/contrib/arm-optimized-routines/math/sincosf.c
+++ b/contrib/arm-optimized-routines/math/sincosf.c
@@ -22,7 +22,7 @@ sincosf (float y, float *sinp, float *cosp)
int n;
const sincos_t *p = &__sincosf_table[0];
- if (abstop12 (y) < abstop12 (pio4))
+ if (abstop12 (y) < abstop12 (pio4f))
{
double x2 = x * x;
diff --git a/contrib/arm-optimized-routines/math/sincosf.h b/contrib/arm-optimized-routines/math/sincosf.h
index 1e80fc9ba8e1..59124699f552 100644
--- a/contrib/arm-optimized-routines/math/sincosf.h
+++ b/contrib/arm-optimized-routines/math/sincosf.h
@@ -12,7 +12,7 @@
/* 2PI * 2^-64. */
static const double pi63 = 0x1.921FB54442D18p-62;
/* PI / 4. */
-static const double pio4 = 0x1.921FB54442D18p-1;
+static const float pio4f = 0x1.921FB6p-1f;
/* The constants and polynomials for sine and cosine. */
typedef struct
diff --git a/contrib/arm-optimized-routines/math/sinf.c b/contrib/arm-optimized-routines/math/sinf.c
index ddbc1daf74a9..4d2cbd6fae72 100644
--- a/contrib/arm-optimized-routines/math/sinf.c
+++ b/contrib/arm-optimized-routines/math/sinf.c
@@ -21,7 +21,7 @@ sinf (float y)
int n;
const sincos_t *p = &__sincosf_table[0];
- if (abstop12 (y) < abstop12 (pio4))
+ if (abstop12 (y) < abstop12 (pio4f))
{
s = x * x;
diff --git a/contrib/arm-optimized-routines/string/aarch64/memcmp.S b/contrib/arm-optimized-routines/string/aarch64/memcmp.S
index 3b1026642eee..7ca1135edec7 100644
--- a/contrib/arm-optimized-routines/string/aarch64/memcmp.S
+++ b/contrib/arm-optimized-routines/string/aarch64/memcmp.S
@@ -1,103 +1,84 @@
/* memcmp - compare memory
*
- * Copyright (c) 2013-2020, Arm Limited.
+ * Copyright (c) 2013-2021, Arm Limited.
* SPDX-License-Identifier: MIT
*/
/* Assumptions:
*
- * ARMv8-a, AArch64, unaligned accesses.
+ * ARMv8-a, AArch64, Advanced SIMD, unaligned accesses.
*/
#include "../asmdefs.h"
-/* Parameters and result. */
-#define src1 x0
-#define src2 x1
-#define limit x2
-#define result w0
-
-/* Internal variables. */
-#define data1 x3
-#define data1w w3
-#define data1h x4
-#define data2 x5
-#define data2w w5
-#define data2h x6
-#define tmp1 x7
-#define tmp2 x8
+#define src1 x0
+#define src2 x1
+#define limit x2
+#define result w0
+
+#define data1 x3
+#define data1w w3
+#define data2 x4
+#define data2w w4
+#define data3 x5
+#define data3w w5
+#define data4 x6
+#define data4w w6
+#define tmp x6
+#define src1end x7
+#define src2end x8
+
ENTRY (__memcmp_aarch64)
PTR_ARG (0)
PTR_ARG (1)
SIZE_ARG (2)
- subs limit, limit, 8
- b.lo L(less8)
-
- ldr data1, [src1], 8
- ldr data2, [src2], 8
- cmp data1, data2
- b.ne L(return)
-
- subs limit, limit, 8
- b.gt L(more16)
-
- ldr data1, [src1, limit]
- ldr data2, [src2, limit]
- b L(return)
-
-L(more16):
- ldr data1, [src1], 8
- ldr data2, [src2], 8
- cmp data1, data2
- bne L(return)
- /* Jump directly to comparing the last 16 bytes for 32 byte (or less)
- strings. */
- subs limit, limit, 16
+ cmp limit, 16
+ b.lo L(less16)
+ ldp data1, data3, [src1]
+ ldp data2, data4, [src2]
+ ccmp data1, data2, 0, ne
+ ccmp data3, data4, 0, eq
+ b.ne L(return2)
+
+ add src1end, src1, limit
+ add src2end, src2, limit
+ cmp limit, 32
b.ls L(last_bytes)
+ cmp limit, 160
+ b.hs L(loop_align)
+ sub limit, limit, 32
- /* We overlap loads between 0-32 bytes at either side of SRC1 when we
- try to align, so limit it only to strings larger than 128 bytes. */
- cmp limit, 96
- b.ls L(loop16)
-
- /* Align src1 and adjust src2 with bytes not yet done. */
- and tmp1, src1, 15
- add limit, limit, tmp1
- sub src1, src1, tmp1
- sub src2, src2, tmp1
-
- /* Loop performing 16 bytes per iteration using aligned src1.
- Limit is pre-decremented by 16 and must be larger than zero.
- Exit if <= 16 bytes left to do or if the data is not equal. */
.p2align 4
-L(loop16):
- ldp data1, data1h, [src1], 16
- ldp data2, data2h, [src2], 16
- subs limit, limit, 16
- ccmp data1, data2, 0, hi
- ccmp data1h, data2h, 0, eq
- b.eq L(loop16)
-
+L(loop32):
+ ldp data1, data3, [src1, 16]
+ ldp data2, data4, [src2, 16]
cmp data1, data2
- bne L(return)
- mov data1, data1h
- mov data2, data2h
+ ccmp data3, data4, 0, eq
+ b.ne L(return2)
+ cmp limit, 16
+ b.ls L(last_bytes)
+
+ ldp data1, data3, [src1, 32]
+ ldp data2, data4, [src2, 32]
cmp data1, data2
- bne L(return)
+ ccmp data3, data4, 0, eq
+ b.ne L(return2)
+ add src1, src1, 32
+ add src2, src2, 32
+L(last64):
+ subs limit, limit, 32
+ b.hi L(loop32)
/* Compare last 1-16 bytes using unaligned access. */
L(last_bytes):
- add src1, src1, limit
- add src2, src2, limit
- ldp data1, data1h, [src1]
- ldp data2, data2h, [src2]
- cmp data1, data2
- bne L(return)
- mov data1, data1h
- mov data2, data2h
+ ldp data1, data3, [src1end, -16]
+ ldp data2, data4, [src2end, -16]
+L(return2):
cmp data1, data2
+ csel data1, data1, data3, ne
+ csel data2, data2, data4, ne
/* Compare data bytes and set return value to 0, -1 or 1. */
L(return):
@@ -105,33 +86,105 @@ L(return):
rev data1, data1
rev data2, data2
#endif
- cmp data1, data2
-L(ret_eq):
+ cmp data1, data2
cset result, ne
cneg result, result, lo
ret
.p2align 4
- /* Compare up to 8 bytes. Limit is [-8..-1]. */
+L(less16):
+ add src1end, src1, limit
+ add src2end, src2, limit
+ tbz limit, 3, L(less8)
+ ldr data1, [src1]
+ ldr data2, [src2]
+ ldr data3, [src1end, -8]
+ ldr data4, [src2end, -8]
+ b L(return2)
+
+ .p2align 4
L(less8):
- adds limit, limit, 4
- b.lo L(less4)
- ldr data1w, [src1], 4
- ldr data2w, [src2], 4
+ tbz limit, 2, L(less4)
+ ldr data1w, [src1]
+ ldr data2w, [src2]
+ ldr data3w, [src1end, -4]
+ ldr data4w, [src2end, -4]
+ b L(return2)
+
+L(less4):
+ tbz limit, 1, L(less2)
+ ldrh data1w, [src1]
+ ldrh data2w, [src2]
cmp data1w, data2w
b.ne L(return)
- sub limit, limit, 4
-L(less4):
- adds limit, limit, 4
- beq L(ret_eq)
-L(byte_loop):
- ldrb data1w, [src1], 1
- ldrb data2w, [src2], 1
- subs limit, limit, 1
- ccmp data1w, data2w, 0, ne /* NZCV = 0b0000. */
- b.eq L(byte_loop)
+L(less2):
+ mov result, 0
+ tbz limit, 0, L(return_zero)
+ ldrb data1w, [src1end, -1]
+ ldrb data2w, [src2end, -1]
sub result, data1w, data2w
+L(return_zero):
ret
-END (__memcmp_aarch64)
+L(loop_align):
+ ldp data1, data3, [src1, 16]
+ ldp data2, data4, [src2, 16]
+ cmp data1, data2
+ ccmp data3, data4, 0, eq
+ b.ne L(return2)
+ /* Align src2 and adjust src1, src2 and limit. */
+ and tmp, src2, 15
+ sub tmp, tmp, 16
+ sub src2, src2, tmp
+ add limit, limit, tmp
+ sub src1, src1, tmp
+ sub limit, limit, 64 + 16
+
+ .p2align 4
+L(loop64):
+ ldr q0, [src1, 16]
+ ldr q1, [src2, 16]
+ subs limit, limit, 64
+ ldr q2, [src1, 32]
+ ldr q3, [src2, 32]
+ eor v0.16b, v0.16b, v1.16b
+ eor v1.16b, v2.16b, v3.16b
+ ldr q2, [src1, 48]
+ ldr q3, [src2, 48]
+ umaxp v0.16b, v0.16b, v1.16b
+ ldr q4, [src1, 64]!
+ ldr q5, [src2, 64]!
+ eor v1.16b, v2.16b, v3.16b
+ eor v2.16b, v4.16b, v5.16b
+ umaxp v1.16b, v1.16b, v2.16b
+ umaxp v0.16b, v0.16b, v1.16b
+ umaxp v0.16b, v0.16b, v0.16b
+ fmov tmp, d0
+ ccmp tmp, 0, 0, hi
+ b.eq L(loop64)
+
+ /* If equal, process last 1-64 bytes using scalar loop. */
+ add limit, limit, 64 + 16
+ cbz tmp, L(last64)
+
+ /* Determine the 8-byte aligned offset of the first difference. */
+#ifdef __AARCH64EB__
+ rev16 tmp, tmp
+#endif
+ rev tmp, tmp
+ clz tmp, tmp
+ bic tmp, tmp, 7
+ sub tmp, tmp, 48
+ ldr data1, [src1, tmp]
+ ldr data2, [src2, tmp]
+#ifndef __AARCH64EB__
+ rev data1, data1
+ rev data2, data2
+#endif
+ mov result, 1
+ cmp data1, data2
+ cneg result, result, lo
+ ret
+
+END (__memcmp_aarch64)
diff --git a/contrib/arm-optimized-routines/string/aarch64/memcpy-sve.S b/contrib/arm-optimized-routines/string/aarch64/memcpy-sve.S
new file mode 100644
index 000000000000..f85e8009f3c5
--- /dev/null
+++ b/contrib/arm-optimized-routines/string/aarch64/memcpy-sve.S
@@ -0,0 +1,180 @@
+/*
+ * memcpy - copy memory area
+ *
+ * Copyright (c) 2019-2022, Arm Limited.
+ * SPDX-License-Identifier: MIT
+ */
+
+/* Assumptions:
+ *
+ * ARMv8-a, AArch64, Advanced SIMD, SVE, unaligned accesses.
+ *
+ */
+
+#if __ARM_FEATURE_SVE
+
+#include "../asmdefs.h"
+
+#define dstin x0
+#define src x1
+#define count x2
+#define dst x3
+#define srcend x4
+#define dstend x5
+#define tmp1 x6
+#define vlen x6
+
+#define A_q q0
+#define B_q q1
+#define C_q q2
+#define D_q q3
+#define E_q q4
+#define F_q q5
+#define G_q q6
+#define H_q q7
+
+/* This implementation handles overlaps and supports both memcpy and memmove
+ from a single entry point. It uses unaligned accesses and branchless
+ sequences to keep the code small, simple and improve performance.
+ SVE vectors are used to speedup small copies.
+
+ Copies are split into 3 main cases: small copies of up to 32 bytes, medium
+ copies of up to 128 bytes, and large copies. The overhead of the overlap
+ check is negligible since it is only required for large copies.
+
+ Large copies use a software pipelined loop processing 64 bytes per iteration.
+ The source pointer is 16-byte aligned to minimize unaligned accesses.
+ The loop tail is handled by always copying 64 bytes from the end.
+*/
+
+ENTRY_ALIAS (__memmove_aarch64_sve)
+ENTRY (__memcpy_aarch64_sve)
+ PTR_ARG (0)
+ PTR_ARG (1)
+ SIZE_ARG (2)
+
+ cmp count, 128
+ b.hi L(copy_long)
+ cmp count, 32
+ b.hi L(copy32_128)
+
+ whilelo p0.b, xzr, count
+ cntb vlen
+ tbnz vlen, 4, L(vlen128)
+ ld1b z0.b, p0/z, [src]
+ st1b z0.b, p0, [dstin]
+ ret
+
+ /* Medium copies: 33..128 bytes. */
+L(copy32_128):
+ add srcend, src, count
+ add dstend, dstin, count
+ ldp A_q, B_q, [src]
+ ldp C_q, D_q, [srcend, -32]
+ cmp count, 64
+ b.hi L(copy128)
+ stp A_q, B_q, [dstin]
+ stp C_q, D_q, [dstend, -32]
+ ret
+
+ /* Copy 65..128 bytes. */
+L(copy128):
+ ldp E_q, F_q, [src, 32]
+ cmp count, 96
+ b.ls L(copy96)
+ ldp G_q, H_q, [srcend, -64]
+ stp G_q, H_q, [dstend, -64]
+L(copy96):
+ stp A_q, B_q, [dstin]
+ stp E_q, F_q, [dstin, 32]
+ stp C_q, D_q, [dstend, -32]
+ ret
+
+ /* Copy more than 128 bytes. */
+L(copy_long):
+ add srcend, src, count
+ add dstend, dstin, count
+
+ /* Use backwards copy if there is an overlap. */
+ sub tmp1, dstin, src
+ cmp tmp1, count
+ b.lo L(copy_long_backwards)
+
+ /* Copy 16 bytes and then align src to 16-byte alignment. */
+ ldr D_q, [src]
+ and tmp1, src, 15
+ bic src, src, 15
+ sub dst, dstin, tmp1
+ add count, count, tmp1 /* Count is now 16 too large. */
+ ldp A_q, B_q, [src, 16]
+ str D_q, [dstin]
+ ldp C_q, D_q, [src, 48]
+ subs count, count, 128 + 16 /* Test and readjust count. */
+ b.ls L(copy64_from_end)
+L(loop64):
+ stp A_q, B_q, [dst, 16]
+ ldp A_q, B_q, [src, 80]
+ stp C_q, D_q, [dst, 48]
+ ldp C_q, D_q, [src, 112]
+ add src, src, 64
+ add dst, dst, 64
+ subs count, count, 64
+ b.hi L(loop64)
+
+ /* Write the last iteration and copy 64 bytes from the end. */
+L(copy64_from_end):
+ ldp E_q, F_q, [srcend, -64]
+ stp A_q, B_q, [dst, 16]
+ ldp A_q, B_q, [srcend, -32]
+ stp C_q, D_q, [dst, 48]
+ stp E_q, F_q, [dstend, -64]
+ stp A_q, B_q, [dstend, -32]
+ ret
+
+L(vlen128):
+ whilelo p1.b, vlen, count
+ ld1b z0.b, p0/z, [src, 0, mul vl]
+ ld1b z1.b, p1/z, [src, 1, mul vl]
+ st1b z0.b, p0, [dstin, 0, mul vl]
+ st1b z1.b, p1, [dstin, 1, mul vl]
+ ret
+
+ /* Large backwards copy for overlapping copies.
+ Copy 16 bytes and then align srcend to 16-byte alignment. */
+L(copy_long_backwards):
+ cbz tmp1, L(return)
+ ldr D_q, [srcend, -16]
+ and tmp1, srcend, 15
+ bic srcend, srcend, 15
+ sub count, count, tmp1
+ ldp A_q, B_q, [srcend, -32]
+ str D_q, [dstend, -16]
+ ldp C_q, D_q, [srcend, -64]
+ sub dstend, dstend, tmp1
+ subs count, count, 128
+ b.ls L(copy64_from_start)
+
+L(loop64_backwards):
+ str B_q, [dstend, -16]
+ str A_q, [dstend, -32]
+ ldp A_q, B_q, [srcend, -96]
+ str D_q, [dstend, -48]
+ str C_q, [dstend, -64]!
+ ldp C_q, D_q, [srcend, -128]
+ sub srcend, srcend, 64
+ subs count, count, 64
+ b.hi L(loop64_backwards)
+
+ /* Write the last iteration and copy 64 bytes from the start. */
+L(copy64_from_start):
+ ldp E_q, F_q, [src, 32]
+ stp A_q, B_q, [dstend, -32]
+ ldp A_q, B_q, [src]
+ stp C_q, D_q, [dstend, -64]
+ stp E_q, F_q, [dstin, 32]
+ stp A_q, B_q, [dstin]
+L(return):
+ ret
+
+END (__memcpy_aarch64_sve)
+#endif
diff --git a/contrib/arm-optimized-routines/string/aarch64/stpcpy-mte.S b/contrib/arm-optimized-routines/string/aarch64/stpcpy-mte.S
deleted file mode 100644
index f1c711906515..000000000000
--- a/contrib/arm-optimized-routines/string/aarch64/stpcpy-mte.S
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * stpcpy - copy a string returning pointer to end.
- *
- * Copyright (c) 2020, Arm Limited.
- * SPDX-License-Identifier: MIT
- */
-
-#define BUILD_STPCPY 1
-
-#include "strcpy-mte.S"
diff --git a/contrib/arm-optimized-routines/string/aarch64/strcmp-mte.S b/contrib/arm-optimized-routines/string/aarch64/strcmp-mte.S
deleted file mode 100644
index 12d1a6b51dd3..000000000000
--- a/contrib/arm-optimized-routines/string/aarch64/strcmp-mte.S
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * strcmp - compare two strings
- *
- * Copyright (c) 2012-2020, Arm Limited.
- * SPDX-License-Identifier: MIT
- */
-
-
-/* Assumptions:
- *
- * ARMv8-a, AArch64.
- * MTE compatible.
- */
-
-#include "../asmdefs.h"
-
-#define REP8_01 0x0101010101010101
-#define REP8_7f 0x7f7f7f7f7f7f7f7f
-
-#define src1 x0
-#define src2 x1
-#define result x0
-
-#define data1 x2
-#define data1w w2
-#define data2 x3
-#define data2w w3
-#define has_nul x4
-#define diff x5
-#define off1 x5
-#define syndrome x6
-#define tmp x6
-#define data3 x7
-#define zeroones x8
-#define shift x9
-#define off2 x10
-
-/* On big-endian early bytes are at MSB and on little-endian LSB.
- LS_FW means shifting towards early bytes. */
-#ifdef __AARCH64EB__
-# define LS_FW lsl
-#else
-# define LS_FW lsr
-#endif
-
-/* NUL detection works on the principle that (X - 1) & (~X) & 0x80
- (=> (X - 1) & ~(X | 0x7f)) is non-zero iff a byte is zero, and
- can be done in parallel across the entire word.
- Since carry propagation makes 0x1 bytes before a NUL byte appear
- NUL too in big-endian, byte-reverse the data before the NUL check. */
-
-
-ENTRY (__strcmp_aarch64_mte)
- PTR_ARG (0)
- PTR_ARG (1)
- sub off2, src2, src1
- mov zeroones, REP8_01
- and tmp, src1, 7
- tst off2, 7
- b.ne L(misaligned8)
- cbnz tmp, L(mutual_align)
-
- .p2align 4
-
-L(loop_aligned):
- ldr data2, [src1, off2]
- ldr data1, [src1], 8
-L(start_realigned):
-#ifdef __AARCH64EB__
- rev tmp, data1
- sub has_nul, tmp, zeroones
- orr tmp, tmp, REP8_7f
-#else
- sub has_nul, data1, zeroones
- orr tmp, data1, REP8_7f
-#endif
- bics has_nul, has_nul, tmp /* Non-zero if NUL terminator. */
- ccmp data1, data2, 0, eq
- b.eq L(loop_aligned)
-#ifdef __AARCH64EB__
- rev has_nul, has_nul
-#endif
- eor diff, data1, data2
- orr syndrome, diff, has_nul
-L(end):
-#ifndef __AARCH64EB__
- rev syndrome, syndrome
- rev data1, data1
- rev data2, data2
-#endif
- clz shift, syndrome
- /* The most-significant-non-zero bit of the syndrome marks either the
- first bit that is different, or the top bit of the first zero byte.
- Shifting left now will bring the critical information into the
- top bits. */
- lsl data1, data1, shift
- lsl data2, data2, shift
- /* But we need to zero-extend (char is unsigned) the value and then
- perform a signed 32-bit subtraction. */
- lsr data1, data1, 56
- sub result, data1, data2, lsr 56
- ret
-
- .p2align 4
-
-L(mutual_align):
- /* Sources are mutually aligned, but are not currently at an
- alignment boundary. Round down the addresses and then mask off
- the bytes that precede the start point. */
- bic src1, src1, 7
- ldr data2, [src1, off2]
- ldr data1, [src1], 8
- neg shift, src2, lsl 3 /* Bits to alignment -64. */
- mov tmp, -1
- LS_FW tmp, tmp, shift
- orr data1, data1, tmp
- orr data2, data2, tmp
- b L(start_realigned)
-
-L(misaligned8):
- /* Align SRC1 to 8 bytes and then compare 8 bytes at a time, always
- checking to make sure that we don't access beyond the end of SRC2. */
- cbz tmp, L(src1_aligned)
-L(do_misaligned):
- ldrb data1w, [src1], 1
- ldrb data2w, [src2], 1
- cmp data1w, 0
- ccmp data1w, data2w, 0, ne /* NZCV = 0b0000. */
- b.ne L(done)
- tst src1, 7
- b.ne L(do_misaligned)
-
-L(src1_aligned):
- neg shift, src2, lsl 3
- bic src2, src2, 7
- ldr data3, [src2], 8
-#ifdef __AARCH64EB__
- rev data3, data3
-#endif
- lsr tmp, zeroones, shift
- orr data3, data3, tmp
- sub has_nul, data3, zeroones
- orr tmp, data3, REP8_7f
- bics has_nul, has_nul, tmp
- b.ne L(tail)
-
- sub off1, src2, src1
-
- .p2align 4
-
-L(loop_unaligned):
- ldr data3, [src1, off1]
- ldr data2, [src1, off2]
-#ifdef __AARCH64EB__
- rev data3, data3
-#endif
- sub has_nul, data3, zeroones
- orr tmp, data3, REP8_7f
- ldr data1, [src1], 8
- bics has_nul, has_nul, tmp
- ccmp data1, data2, 0, eq
- b.eq L(loop_unaligned)
-
- lsl tmp, has_nul, shift
-#ifdef __AARCH64EB__
- rev tmp, tmp
-#endif
- eor diff, data1, data2
- orr syndrome, diff, tmp
- cbnz syndrome, L(end)
-L(tail):
- ldr data1, [src1]
- neg shift, shift
- lsr data2, data3, shift
- lsr has_nul, has_nul, shift
-#ifdef __AARCH64EB__
- rev data2, data2
- rev has_nul, has_nul
-#endif
- eor diff, data1, data2
- orr syndrome, diff, has_nul
- b L(end)
-
-L(done):
- sub result, data1, data2
- ret
-
-END (__strcmp_aarch64_mte)
-
diff --git a/contrib/arm-optimized-routines/string/aarch64/strcmp.S b/contrib/arm-optimized-routines/string/aarch64/strcmp.S
index 7714ebf5577d..6e77845ae6ff 100644
--- a/contrib/arm-optimized-routines/string/aarch64/strcmp.S
+++ b/contrib/arm-optimized-routines/string/aarch64/strcmp.S
@@ -1,168 +1,184 @@
/*
* strcmp - compare two strings
*
- * Copyright (c) 2012-2020, Arm Limited.
+ * Copyright (c) 2012-2022, Arm Limited.
* SPDX-License-Identifier: MIT
*/
+
/* Assumptions:
*
- * ARMv8-a, AArch64
+ * ARMv8-a, AArch64.
+ * MTE compatible.
*/
#include "../asmdefs.h"
#define REP8_01 0x0101010101010101
#define REP8_7f 0x7f7f7f7f7f7f7f7f
-#define REP8_80 0x8080808080808080
-/* Parameters and result. */
#define src1 x0
#define src2 x1
#define result x0
-/* Internal variables. */
#define data1 x2
#define data1w w2
#define data2 x3
#define data2w w3
#define has_nul x4
#define diff x5
+#define off1 x5
#define syndrome x6
-#define tmp1 x7
-#define tmp2 x8
-#define tmp3 x9
-#define zeroones x10
-#define pos x11
+#define tmp x6
+#define data3 x7
+#define zeroones x8
+#define shift x9
+#define off2 x10
+
+/* On big-endian early bytes are at MSB and on little-endian LSB.
+ LS_FW means shifting towards early bytes. */
+#ifdef __AARCH64EB__
+# define LS_FW lsl
+#else
+# define LS_FW lsr
+#endif
+
+/* NUL detection works on the principle that (X - 1) & (~X) & 0x80
+ (=> (X - 1) & ~(X | 0x7f)) is non-zero iff a byte is zero, and
+ can be done in parallel across the entire word.
+ Since carry propagation makes 0x1 bytes before a NUL byte appear
+ NUL too in big-endian, byte-reverse the data before the NUL check. */
+
- /* Start of performance-critical section -- one 64B cache line. */
ENTRY (__strcmp_aarch64)
PTR_ARG (0)
PTR_ARG (1)
- eor tmp1, src1, src2
- mov zeroones, #REP8_01
- tst tmp1, #7
+ sub off2, src2, src1
+ mov zeroones, REP8_01
+ and tmp, src1, 7
+ tst off2, 7
b.ne L(misaligned8)
- ands tmp1, src1, #7
- b.ne L(mutual_align)
- /* NUL detection works on the principle that (X - 1) & (~X) & 0x80
- (=> (X - 1) & ~(X | 0x7f)) is non-zero iff a byte is zero, and
- can be done in parallel across the entire word. */
+ cbnz tmp, L(mutual_align)
+
+ .p2align 4
+
L(loop_aligned):
- ldr data1, [src1], #8
- ldr data2, [src2], #8
+ ldr data2, [src1, off2]
+ ldr data1, [src1], 8
L(start_realigned):
- sub tmp1, data1, zeroones
- orr tmp2, data1, #REP8_7f
- eor diff, data1, data2 /* Non-zero if differences found. */
- bic has_nul, tmp1, tmp2 /* Non-zero if NUL terminator. */
+#ifdef __AARCH64EB__
+ rev tmp, data1
+ sub has_nul, tmp, zeroones
+ orr tmp, tmp, REP8_7f
+#else
+ sub has_nul, data1, zeroones
+ orr tmp, data1, REP8_7f
+#endif
+ bics has_nul, has_nul, tmp /* Non-zero if NUL terminator. */
+ ccmp data1, data2, 0, eq
+ b.eq L(loop_aligned)
+#ifdef __AARCH64EB__
+ rev has_nul, has_nul
+#endif
+ eor diff, data1, data2
orr syndrome, diff, has_nul
- cbz syndrome, L(loop_aligned)
- /* End of performance-critical section -- one 64B cache line. */
-
L(end):
-#ifndef __AARCH64EB__
+#ifndef __AARCH64EB__
rev syndrome, syndrome
rev data1, data1
- /* The MS-non-zero bit of the syndrome marks either the first bit
- that is different, or the top bit of the first zero byte.
- Shifting left now will bring the critical information into the
- top bits. */
- clz pos, syndrome
rev data2, data2
- lsl data1, data1, pos
- lsl data2, data2, pos
- /* But we need to zero-extend (char is unsigned) the value and then
- perform a signed 32-bit subtraction. */
- lsr data1, data1, #56
- sub result, data1, data2, lsr #56
- ret
-#else
- /* For big-endian we cannot use the trick with the syndrome value
- as carry-propagation can corrupt the upper bits if the trailing
- bytes in the string contain 0x01. */
- /* However, if there is no NUL byte in the dword, we can generate
- the result directly. We can't just subtract the bytes as the
- MSB might be significant. */
- cbnz has_nul, 1f
- cmp data1, data2
- cset result, ne
- cneg result, result, lo
- ret
-1:
- /* Re-compute the NUL-byte detection, using a byte-reversed value. */
- rev tmp3, data1
- sub tmp1, tmp3, zeroones
- orr tmp2, tmp3, #REP8_7f
- bic has_nul, tmp1, tmp2
- rev has_nul, has_nul
- orr syndrome, diff, has_nul
- clz pos, syndrome
- /* The MS-non-zero bit of the syndrome marks either the first bit
- that is different, or the top bit of the first zero byte.
+#endif
+ clz shift, syndrome
+ /* The most-significant-non-zero bit of the syndrome marks either the
+ first bit that is different, or the top bit of the first zero byte.
Shifting left now will bring the critical information into the
top bits. */
- lsl data1, data1, pos
- lsl data2, data2, pos
+ lsl data1, data1, shift
+ lsl data2, data2, shift
/* But we need to zero-extend (char is unsigned) the value and then
perform a signed 32-bit subtraction. */
- lsr data1, data1, #56
- sub result, data1, data2, lsr #56
+ lsr data1, data1, 56
+ sub result, data1, data2, lsr 56
ret
-#endif
+
+ .p2align 4
L(mutual_align):
/* Sources are mutually aligned, but are not currently at an
alignment boundary. Round down the addresses and then mask off
- the bytes that preceed the start point. */
- bic src1, src1, #7
- bic src2, src2, #7
- lsl tmp1, tmp1, #3 /* Bytes beyond alignment -> bits. */
- ldr data1, [src1], #8
- neg tmp1, tmp1 /* Bits to alignment -64. */
- ldr data2, [src2], #8
- mov tmp2, #~0
-#ifdef __AARCH64EB__
- /* Big-endian. Early bytes are at MSB. */
- lsl tmp2, tmp2, tmp1 /* Shift (tmp1 & 63). */
-#else
- /* Little-endian. Early bytes are at LSB. */
- lsr tmp2, tmp2, tmp1 /* Shift (tmp1 & 63). */
-#endif
- orr data1, data1, tmp2
- orr data2, data2, tmp2
+ the bytes that precede the start point. */
+ bic src1, src1, 7
+ ldr data2, [src1, off2]
+ ldr data1, [src1], 8
+ neg shift, src2, lsl 3 /* Bits to alignment -64. */
+ mov tmp, -1
+ LS_FW tmp, tmp, shift
+ orr data1, data1, tmp
+ orr data2, data2, tmp
b L(start_realigned)
L(misaligned8):
/* Align SRC1 to 8 bytes and then compare 8 bytes at a time, always
- checking to make sure that we don't access beyond page boundary in
- SRC2. */
- tst src1, #7
- b.eq L(loop_misaligned)
+ checking to make sure that we don't access beyond the end of SRC2. */
+ cbz tmp, L(src1_aligned)
L(do_misaligned):
- ldrb data1w, [src1], #1
- ldrb data2w, [src2], #1
- cmp data1w, #1
- ccmp data1w, data2w, #0, cs /* NZCV = 0b0000. */
+ ldrb data1w, [src1], 1
+ ldrb data2w, [src2], 1
+ cmp data1w, 0
+ ccmp data1w, data2w, 0, ne /* NZCV = 0b0000. */
b.ne L(done)
- tst src1, #7
+ tst src1, 7
b.ne L(do_misaligned)
-L(loop_misaligned):
- /* Test if we are within the last dword of the end of a 4K page. If
- yes then jump back to the misaligned loop to copy a byte at a time. */
- and tmp1, src2, #0xff8
- eor tmp1, tmp1, #0xff8
- cbz tmp1, L(do_misaligned)
- ldr data1, [src1], #8
- ldr data2, [src2], #8
-
- sub tmp1, data1, zeroones
- orr tmp2, data1, #REP8_7f
- eor diff, data1, data2 /* Non-zero if differences found. */
- bic has_nul, tmp1, tmp2 /* Non-zero if NUL terminator. */
+L(src1_aligned):
+ neg shift, src2, lsl 3
+ bic src2, src2, 7
+ ldr data3, [src2], 8
+#ifdef __AARCH64EB__
+ rev data3, data3
+#endif
+ lsr tmp, zeroones, shift
+ orr data3, data3, tmp
+ sub has_nul, data3, zeroones
+ orr tmp, data3, REP8_7f
+ bics has_nul, has_nul, tmp
+ b.ne L(tail)
+
+ sub off1, src2, src1
+
+ .p2align 4
+
+L(loop_unaligned):
+ ldr data3, [src1, off1]
+ ldr data2, [src1, off2]
+#ifdef __AARCH64EB__
+ rev data3, data3
+#endif
+ sub has_nul, data3, zeroones
+ orr tmp, data3, REP8_7f
+ ldr data1, [src1], 8
+ bics has_nul, has_nul, tmp
+ ccmp data1, data2, 0, eq
+ b.eq L(loop_unaligned)
+
+ lsl tmp, has_nul, shift
+#ifdef __AARCH64EB__
+ rev tmp, tmp
+#endif
+ eor diff, data1, data2
+ orr syndrome, diff, tmp
+ cbnz syndrome, L(end)
+L(tail):
+ ldr data1, [src1]
+ neg shift, shift
+ lsr data2, data3, shift
+ lsr has_nul, has_nul, shift
+#ifdef __AARCH64EB__
+ rev data2, data2
+ rev has_nul, has_nul
+#endif
+ eor diff, data1, data2
orr syndrome, diff, has_nul
- cbz syndrome, L(loop_misaligned)
b L(end)
L(done):
diff --git a/contrib/arm-optimized-routines/string/aarch64/strcpy-mte.S b/contrib/arm-optimized-routines/string/aarch64/strcpy-mte.S
deleted file mode 100644
index 88c222d61e53..000000000000
--- a/contrib/arm-optimized-routines/string/aarch64/strcpy-mte.S
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * strcpy/stpcpy - copy a string returning pointer to start/end.
- *
- * Copyright (c) 2020, Arm Limited.
- * SPDX-License-Identifier: MIT
- */
-
-/* Assumptions:
- *
- * ARMv8-a, AArch64, Advanced SIMD.
- * MTE compatible.
- */
-
-#include "../asmdefs.h"
-
-#define dstin x0
-#define srcin x1
-#define result x0
-
-#define src x2
-#define dst x3
-#define len x4
-#define synd x4
-#define tmp x5
-#define wtmp w5
-#define shift x5
-#define data1 x6
-#define dataw1 w6
-#define data2 x7
-#define dataw2 w7
-
-#define dataq q0
-#define vdata v0
-#define vhas_nul v1
-#define vrepmask v2
-#define vend v3
-#define dend d3
-#define dataq2 q1
-
-#ifdef BUILD_STPCPY
-# define STRCPY __stpcpy_aarch64_mte
-# define IFSTPCPY(X,...) X,__VA_ARGS__
-#else
-# define STRCPY __strcpy_aarch64_mte
-# define IFSTPCPY(X,...)
-#endif
-
-/* Core algorithm:
-
- For each 16-byte chunk we calculate a 64-bit syndrome value with four bits
- per byte. For even bytes, bits 0-3 are set if the relevant byte matched the
- requested character or the byte is NUL. Bits 4-7 must be zero. Bits 4-7 are
- set likewise for odd bytes so that adjacent bytes can be merged. Since the
- bits in the syndrome reflect the order in which things occur in the original
- string, counting trailing zeros identifies exactly which byte matched. */
-
-ENTRY (STRCPY)
- PTR_ARG (0)
- PTR_ARG (1)
- bic src, srcin, 15
- mov wtmp, 0xf00f
- ld1 {vdata.16b}, [src]
- dup vrepmask.8h, wtmp
- cmeq vhas_nul.16b, vdata.16b, 0
- lsl shift, srcin, 2
- and vhas_nul.16b, vhas_nul.16b, vrepmask.16b
- addp vend.16b, vhas_nul.16b, vhas_nul.16b
- fmov synd, dend
- lsr synd, synd, shift
- cbnz synd, L(tail)
-
- ldr dataq, [src, 16]!
- cmeq vhas_nul.16b, vdata.16b, 0
- and vhas_nul.16b, vhas_nul.16b, vrepmask.16b
- addp vend.16b, vhas_nul.16b, vhas_nul.16b
- fmov synd, dend
- cbz synd, L(start_loop)
-
-#ifndef __AARCH64EB__
- rbit synd, synd
-#endif
- sub tmp, src, srcin
- clz len, synd
- add len, tmp, len, lsr 2
- tbz len, 4, L(less16)
- sub tmp, len, 15
- ldr dataq, [srcin]
- ldr dataq2, [srcin, tmp]
- str dataq, [dstin]
- str dataq2, [dstin, tmp]
- IFSTPCPY (add result, dstin, len)
- ret
-
- .p2align 4,,8
-L(tail):
- rbit synd, synd
- clz len, synd
- lsr len, len, 2
-
- .p2align 4
-L(less16):
- tbz len, 3, L(less8)
- sub tmp, len, 7
- ldr data1, [srcin]
- ldr data2, [srcin, tmp]
- str data1, [dstin]
- str data2, [dstin, tmp]
- IFSTPCPY (add result, dstin, len)
- ret
-
- .p2align 4
-L(less8):
- subs tmp, len, 3
- b.lo L(less4)
- ldr dataw1, [srcin]
- ldr dataw2, [srcin, tmp]
- str dataw1, [dstin]
- str dataw2, [dstin, tmp]
- IFSTPCPY (add result, dstin, len)
- ret
-
-L(less4):
- cbz len, L(zerobyte)
- ldrh dataw1, [srcin]
- strh dataw1, [dstin]
-L(zerobyte):
- strb wzr, [dstin, len]
- IFSTPCPY (add result, dstin, len)
- ret
-
- .p2align 4
-L(start_loop):
- sub len, src, srcin
- ldr dataq2, [srcin]
- add dst, dstin, len
- str dataq2, [dstin]
-
- .p2align 5
-L(loop):
- str dataq, [dst], 16
- ldr dataq, [src, 16]!
- cmeq vhas_nul.16b, vdata.16b, 0
- umaxp vend.16b, vhas_nul.16b, vhas_nul.16b
- fmov synd, dend
- cbz synd, L(loop)
-
- and vhas_nul.16b, vhas_nul.16b, vrepmask.16b
- addp vend.16b, vhas_nul.16b, vhas_nul.16b /* 128->64 */
- fmov synd, dend
-#ifndef __AARCH64EB__
- rbit synd, synd
-#endif
- clz len, synd
- lsr len, len, 2
- sub tmp, len, 15
- ldr dataq, [src, tmp]
- str dataq, [dst, tmp]
- IFSTPCPY (add result, dst, len)
- ret
-
-END (STRCPY)
diff --git a/contrib/arm-optimized-routines/string/aarch64/strcpy.S b/contrib/arm-optimized-routines/string/aarch64/strcpy.S
index 6e9ed424b693..b99e49403be8 100644
--- a/contrib/arm-optimized-routines/string/aarch64/strcpy.S
+++ b/contrib/arm-optimized-routines/string/aarch64/strcpy.S
@@ -1,311 +1,161 @@
/*
* strcpy/stpcpy - copy a string returning pointer to start/end.
*
- * Copyright (c) 2013-2020, Arm Limited.
+ * Copyright (c) 2020-2022, Arm Limited.
* SPDX-License-Identifier: MIT
*/
/* Assumptions:
*
- * ARMv8-a, AArch64, unaligned accesses, min page size 4k.
+ * ARMv8-a, AArch64, Advanced SIMD.
+ * MTE compatible.
*/
#include "../asmdefs.h"
-/* To build as stpcpy, define BUILD_STPCPY before compiling this file.
-
- To test the page crossing code path more thoroughly, compile with
- -DSTRCPY_TEST_PAGE_CROSS - this will force all copies through the slower
- entry path. This option is not intended for production use. */
-
-/* Arguments and results. */
#define dstin x0
#define srcin x1
+#define result x0
-/* Locals and temporaries. */
#define src x2
#define dst x3
-#define data1 x4
-#define data1w w4
-#define data2 x5
-#define data2w w5
-#define has_nul1 x6
-#define has_nul2 x7
-#define tmp1 x8
-#define tmp2 x9
-#define tmp3 x10
-#define tmp4 x11
-#define zeroones x12
-#define data1a x13
-#define data2a x14
-#define pos x15
-#define len x16
-#define to_align x17
+#define len x4
+#define synd x4
+#define tmp x5
+#define wtmp w5
+#define shift x5
+#define data1 x6
+#define dataw1 w6
+#define data2 x7
+#define dataw2 w7
+
+#define dataq q0
+#define vdata v0
+#define vhas_nul v1
+#define vrepmask v2
+#define vend v3
+#define dend d3
+#define dataq2 q1
#ifdef BUILD_STPCPY
-#define STRCPY __stpcpy_aarch64
+# define STRCPY __stpcpy_aarch64
+# define IFSTPCPY(X,...) X,__VA_ARGS__
#else
-#define STRCPY __strcpy_aarch64
+# define STRCPY __strcpy_aarch64
+# define IFSTPCPY(X,...)
#endif
- /* NUL detection works on the principle that (X - 1) & (~X) & 0x80
- (=> (X - 1) & ~(X | 0x7f)) is non-zero iff a byte is zero, and
- can be done in parallel across the entire word. */
-
-#define REP8_01 0x0101010101010101
-#define REP8_7f 0x7f7f7f7f7f7f7f7f
-#define REP8_80 0x8080808080808080
+/* Core algorithm:
- /* AArch64 systems have a minimum page size of 4k. We can do a quick
- page size check for crossing this boundary on entry and if we
- do not, then we can short-circuit much of the entry code. We
- expect early page-crossing strings to be rare (probability of
- 16/MIN_PAGE_SIZE ~= 0.4%), so the branch should be quite
- predictable, even with random strings.
-
- We don't bother checking for larger page sizes, the cost of setting
- up the correct page size is just not worth the extra gain from
- a small reduction in the cases taking the slow path. Note that
- we only care about whether the first fetch, which may be
- misaligned, crosses a page boundary - after that we move to aligned
- fetches for the remainder of the string. */
-
-#ifdef STRCPY_TEST_PAGE_CROSS
- /* Make everything that isn't Qword aligned look like a page cross. */
-#define MIN_PAGE_P2 4
-#else
-#define MIN_PAGE_P2 12
-#endif
-
-#define MIN_PAGE_SIZE (1 << MIN_PAGE_P2)
+ For each 16-byte chunk we calculate a 64-bit syndrome value with four bits
+ per byte. For even bytes, bits 0-3 are set if the relevant byte matched the
+ requested character or the byte is NUL. Bits 4-7 must be zero. Bits 4-7 are
+ set likewise for odd bytes so that adjacent bytes can be merged. Since the
+ bits in the syndrome reflect the order in which things occur in the original
+ string, counting trailing zeros identifies exactly which byte matched. */
ENTRY (STRCPY)
PTR_ARG (0)
PTR_ARG (1)
- /* For moderately short strings, the fastest way to do the copy is to
- calculate the length of the string in the same way as strlen, then
- essentially do a memcpy of the result. This avoids the need for
- multiple byte copies and further means that by the time we
- reach the bulk copy loop we know we can always use DWord
- accesses. We expect __strcpy_aarch64 to rarely be called repeatedly
- with the same source string, so branch prediction is likely to
- always be difficult - we mitigate against this by preferring
- conditional select operations over branches whenever this is
- feasible. */
- and tmp2, srcin, #(MIN_PAGE_SIZE - 1)
- mov zeroones, #REP8_01
- and to_align, srcin, #15
- cmp tmp2, #(MIN_PAGE_SIZE - 16)
- neg tmp1, to_align
- /* The first fetch will straddle a (possible) page boundary iff
- srcin + 15 causes bit[MIN_PAGE_P2] to change value. A 16-byte
- aligned string will never fail the page align check, so will
- always take the fast path. */
- b.gt L(page_cross)
-
-L(page_cross_ok):
- ldp data1, data2, [srcin]
-#ifdef __AARCH64EB__
- /* Because we expect the end to be found within 16 characters
- (profiling shows this is the most common case), it's worth
- swapping the bytes now to save having to recalculate the
- termination syndrome later. We preserve data1 and data2
- so that we can re-use the values later on. */
- rev tmp2, data1
- sub tmp1, tmp2, zeroones
- orr tmp2, tmp2, #REP8_7f
- bics has_nul1, tmp1, tmp2
- b.ne L(fp_le8)
- rev tmp4, data2
- sub tmp3, tmp4, zeroones
- orr tmp4, tmp4, #REP8_7f
-#else
- sub tmp1, data1, zeroones
- orr tmp2, data1, #REP8_7f
- bics has_nul1, tmp1, tmp2
- b.ne L(fp_le8)
- sub tmp3, data2, zeroones
- orr tmp4, data2, #REP8_7f
+ bic src, srcin, 15
+ mov wtmp, 0xf00f
+ ld1 {vdata.16b}, [src]
+ dup vrepmask.8h, wtmp
+ cmeq vhas_nul.16b, vdata.16b, 0
+ lsl shift, srcin, 2
+ and vhas_nul.16b, vhas_nul.16b, vrepmask.16b
+ addp vend.16b, vhas_nul.16b, vhas_nul.16b
+ fmov synd, dend
+ lsr synd, synd, shift
+ cbnz synd, L(tail)
+
+ ldr dataq, [src, 16]!
+ cmeq vhas_nul.16b, vdata.16b, 0
+ and vhas_nul.16b, vhas_nul.16b, vrepmask.16b
+ addp vend.16b, vhas_nul.16b, vhas_nul.16b
+ fmov synd, dend
+ cbz synd, L(start_loop)
+
+#ifndef __AARCH64EB__
+ rbit synd, synd
#endif
- bics has_nul2, tmp3, tmp4
- b.eq L(bulk_entry)
+ sub tmp, src, srcin
+ clz len, synd
+ add len, tmp, len, lsr 2
+ tbz len, 4, L(less16)
+ sub tmp, len, 15
+ ldr dataq, [srcin]
+ ldr dataq2, [srcin, tmp]
+ str dataq, [dstin]
+ str dataq2, [dstin, tmp]
+ IFSTPCPY (add result, dstin, len)
+ ret
- /* The string is short (<=16 bytes). We don't know exactly how
- short though, yet. Work out the exact length so that we can
- quickly select the optimal copy strategy. */
-L(fp_gt8):
- rev has_nul2, has_nul2
- clz pos, has_nul2
- mov tmp2, #56
- add dst, dstin, pos, lsr #3 /* Bits to bytes. */
- sub pos, tmp2, pos
-#ifdef __AARCH64EB__
- lsr data2, data2, pos
-#else
- lsl data2, data2, pos
-#endif
- str data2, [dst, #1]
+ .p2align 4,,8
+L(tail):
+ rbit synd, synd
+ clz len, synd
+ lsr len, len, 2
+
+ .p2align 4
+L(less16):
+ tbz len, 3, L(less8)
+ sub tmp, len, 7
+ ldr data1, [srcin]
+ ldr data2, [srcin, tmp]
str data1, [dstin]
-#ifdef BUILD_STPCPY
- add dstin, dst, #8
-#endif
+ str data2, [dstin, tmp]
+ IFSTPCPY (add result, dstin, len)
ret
-L(fp_le8):
- rev has_nul1, has_nul1
- clz pos, has_nul1
- add dst, dstin, pos, lsr #3 /* Bits to bytes. */
- subs tmp2, pos, #24 /* Pos in bits. */
- b.lt L(fp_lt4)
-#ifdef __AARCH64EB__
- mov tmp2, #56
- sub pos, tmp2, pos
- lsr data2, data1, pos
- lsr data1, data1, #32
-#else
- lsr data2, data1, tmp2
-#endif
- /* 4->7 bytes to copy. */
- str data2w, [dst, #-3]
- str data1w, [dstin]
-#ifdef BUILD_STPCPY
- mov dstin, dst
-#endif
+ .p2align 4
+L(less8):
+ subs tmp, len, 3
+ b.lo L(less4)
+ ldr dataw1, [srcin]
+ ldr dataw2, [srcin, tmp]
+ str dataw1, [dstin]
+ str dataw2, [dstin, tmp]
+ IFSTPCPY (add result, dstin, len)
ret
-L(fp_lt4):
- cbz pos, L(fp_lt2)
- /* 2->3 bytes to copy. */
-#ifdef __AARCH64EB__
- lsr data1, data1, #48
-#endif
- strh data1w, [dstin]
- /* Fall-through, one byte (max) to go. */
-L(fp_lt2):
- /* Null-terminated string. Last character must be zero! */
- strb wzr, [dst]
-#ifdef BUILD_STPCPY
- mov dstin, dst
-#endif
- ret
-
- .p2align 6
- /* Aligning here ensures that the entry code and main loop all lies
- within one 64-byte cache line. */
-L(bulk_entry):
- sub to_align, to_align, #16
- stp data1, data2, [dstin]
- sub src, srcin, to_align
- sub dst, dstin, to_align
- b L(entry_no_page_cross)
- /* The inner loop deals with two Dwords at a time. This has a
- slightly higher start-up cost, but we should win quite quickly,
- especially on cores with a high number of issue slots per
- cycle, as we get much better parallelism out of the operations. */
-L(main_loop):
- stp data1, data2, [dst], #16
-L(entry_no_page_cross):
- ldp data1, data2, [src], #16
- sub tmp1, data1, zeroones
- orr tmp2, data1, #REP8_7f
- sub tmp3, data2, zeroones
- orr tmp4, data2, #REP8_7f
- bic has_nul1, tmp1, tmp2
- bics has_nul2, tmp3, tmp4
- ccmp has_nul1, #0, #0, eq /* NZCV = 0000 */
- b.eq L(main_loop)
-
- /* Since we know we are copying at least 16 bytes, the fastest way
- to deal with the tail is to determine the location of the
- trailing NUL, then (re)copy the 16 bytes leading up to that. */
- cmp has_nul1, #0
-#ifdef __AARCH64EB__
- /* For big-endian, carry propagation (if the final byte in the
- string is 0x01) means we cannot use has_nul directly. The
- easiest way to get the correct byte is to byte-swap the data
- and calculate the syndrome a second time. */
- csel data1, data1, data2, ne
- rev data1, data1
- sub tmp1, data1, zeroones
- orr tmp2, data1, #REP8_7f
- bic has_nul1, tmp1, tmp2
-#else
- csel has_nul1, has_nul1, has_nul2, ne
-#endif
- rev has_nul1, has_nul1
- clz pos, has_nul1
- add tmp1, pos, #72
- add pos, pos, #8
- csel pos, pos, tmp1, ne
- add src, src, pos, lsr #3
- add dst, dst, pos, lsr #3
- ldp data1, data2, [src, #-32]
- stp data1, data2, [dst, #-16]
-#ifdef BUILD_STPCPY
- sub dstin, dst, #1
-#endif
+L(less4):
+ cbz len, L(zerobyte)
+ ldrh dataw1, [srcin]
+ strh dataw1, [dstin]
+L(zerobyte):
+ strb wzr, [dstin, len]
+ IFSTPCPY (add result, dstin, len)
ret
-L(page_cross):
- bic src, srcin, #15
- /* Start by loading two words at [srcin & ~15], then forcing the
- bytes that precede srcin to 0xff. This means they never look
- like termination bytes. */
- ldp data1, data2, [src]
- lsl tmp1, tmp1, #3 /* Bytes beyond alignment -> bits. */
- tst to_align, #7
- csetm tmp2, ne
-#ifdef __AARCH64EB__
- lsl tmp2, tmp2, tmp1 /* Shift (tmp1 & 63). */
-#else
- lsr tmp2, tmp2, tmp1 /* Shift (tmp1 & 63). */
+ .p2align 4
+L(start_loop):
+ sub len, src, srcin
+ ldr dataq2, [srcin]
+ add dst, dstin, len
+ str dataq2, [dstin]
+
+ .p2align 5
+L(loop):
+ str dataq, [dst], 16
+ ldr dataq, [src, 16]!
+ cmeq vhas_nul.16b, vdata.16b, 0
+ umaxp vend.16b, vhas_nul.16b, vhas_nul.16b
+ fmov synd, dend
+ cbz synd, L(loop)
+
+ and vhas_nul.16b, vhas_nul.16b, vrepmask.16b
+ addp vend.16b, vhas_nul.16b, vhas_nul.16b /* 128->64 */
+ fmov synd, dend
+#ifndef __AARCH64EB__
+ rbit synd, synd
#endif
- orr data1, data1, tmp2
- orr data2a, data2, tmp2
- cmp to_align, #8
- csinv data1, data1, xzr, lt
- csel data2, data2, data2a, lt
- sub tmp1, data1, zeroones
- orr tmp2, data1, #REP8_7f
- sub tmp3, data2, zeroones
- orr tmp4, data2, #REP8_7f
- bic has_nul1, tmp1, tmp2
- bics has_nul2, tmp3, tmp4
- ccmp has_nul1, #0, #0, eq /* NZCV = 0000 */
- b.eq L(page_cross_ok)
- /* We now need to make data1 and data2 look like they've been
- loaded directly from srcin. Do a rotate on the 128-bit value. */
- lsl tmp1, to_align, #3 /* Bytes->bits. */
- neg tmp2, to_align, lsl #3
-#ifdef __AARCH64EB__
- lsl data1a, data1, tmp1
- lsr tmp4, data2, tmp2
- lsl data2, data2, tmp1
- orr tmp4, tmp4, data1a
- cmp to_align, #8
- csel data1, tmp4, data2, lt
- rev tmp2, data1
- rev tmp4, data2
- sub tmp1, tmp2, zeroones
- orr tmp2, tmp2, #REP8_7f
- sub tmp3, tmp4, zeroones
- orr tmp4, tmp4, #REP8_7f
-#else
- lsr data1a, data1, tmp1
- lsl tmp4, data2, tmp2
- lsr data2, data2, tmp1
- orr tmp4, tmp4, data1a
- cmp to_align, #8
- csel data1, tmp4, data2, lt
- sub tmp1, data1, zeroones
- orr tmp2, data1, #REP8_7f
- sub tmp3, data2, zeroones
- orr tmp4, data2, #REP8_7f
-#endif
- bic has_nul1, tmp1, tmp2
- cbnz has_nul1, L(fp_le8)
- bic has_nul2, tmp3, tmp4
- b L(fp_gt8)
+ clz len, synd
+ lsr len, len, 2
+ sub tmp, len, 15
+ ldr dataq, [src, tmp]
+ str dataq, [dst, tmp]
+ IFSTPCPY (add result, dst, len)
+ ret
END (STRCPY)
-
diff --git a/contrib/arm-optimized-routines/string/aarch64/strncmp-mte.S b/contrib/arm-optimized-routines/string/aarch64/strncmp-mte.S
deleted file mode 100644
index c9d6fc8a158b..000000000000
--- a/contrib/arm-optimized-routines/string/aarch64/strncmp-mte.S
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * strncmp - compare two strings
- *
- * Copyright (c) 2013-2021, Arm Limited.
- * SPDX-License-Identifier: MIT
- */
-
-/* Assumptions:
- *
- * ARMv8-a, AArch64
- */
-
-#include "../asmdefs.h"
-
-#define REP8_01 0x0101010101010101
-#define REP8_7f 0x7f7f7f7f7f7f7f7f
-
-/* Parameters and result. */
-#define src1 x0
-#define src2 x1
-#define limit x2
-#define result x0
-
-/* Internal variables. */
-#define data1 x3
-#define data1w w3
-#define data2 x4
-#define data2w w4
-#define has_nul x5
-#define diff x6
-#define syndrome x7
-#define tmp1 x8
-#define tmp2 x9
-#define tmp3 x10
-#define zeroones x11
-#define pos x12
-#define mask x13
-#define endloop x14
-#define count mask
-#define offset pos
-#define neg_offset x15
-
-/* Define endian dependent shift operations.
- On big-endian early bytes are at MSB and on little-endian LSB.
- LS_FW means shifting towards early bytes.
- LS_BK means shifting towards later bytes.
- */
-#ifdef __AARCH64EB__
-#define LS_FW lsl
-#define LS_BK lsr
-#else
-#define LS_FW lsr
-#define LS_BK lsl
-#endif
-
-ENTRY (__strncmp_aarch64_mte)
- PTR_ARG (0)
- PTR_ARG (1)
- SIZE_ARG (2)
- cbz limit, L(ret0)
- eor tmp1, src1, src2
- mov zeroones, #REP8_01
- tst tmp1, #7
- and count, src1, #7
- b.ne L(misaligned8)
- cbnz count, L(mutual_align)
-
- /* NUL detection works on the principle that (X - 1) & (~X) & 0x80
- (=> (X - 1) & ~(X | 0x7f)) is non-zero iff a byte is zero, and
- can be done in parallel across the entire word. */
- .p2align 4
-L(loop_aligned):
- ldr data1, [src1], #8
- ldr data2, [src2], #8
-L(start_realigned):
- subs limit, limit, #8
- sub tmp1, data1, zeroones
- orr tmp2, data1, #REP8_7f
- eor diff, data1, data2 /* Non-zero if differences found. */
- csinv endloop, diff, xzr, hi /* Last Dword or differences. */
- bics has_nul, tmp1, tmp2 /* Non-zero if NUL terminator. */
- ccmp endloop, #0, #0, eq
- b.eq L(loop_aligned)
- /* End of main loop */
-
-L(full_check):
-#ifndef __AARCH64EB__
- orr syndrome, diff, has_nul
- add limit, limit, 8 /* Rewind limit to before last subs. */
-L(syndrome_check):
- /* Limit was reached. Check if the NUL byte or the difference
- is before the limit. */
- rev syndrome, syndrome
- rev data1, data1
- clz pos, syndrome
- rev data2, data2
- lsl data1, data1, pos
- cmp limit, pos, lsr #3
- lsl data2, data2, pos
- /* But we need to zero-extend (char is unsigned) the value and then
- perform a signed 32-bit subtraction. */
- lsr data1, data1, #56
- sub result, data1, data2, lsr #56
- csel result, result, xzr, hi
- ret
-#else
- /* Not reached the limit, must have found the end or a diff. */
- tbz limit, #63, L(not_limit)
- add tmp1, limit, 8
- cbz limit, L(not_limit)
-
- lsl limit, tmp1, #3 /* Bits -> bytes. */
- mov mask, #~0
- lsr mask, mask, limit
- bic data1, data1, mask
- bic data2, data2, mask
-
- /* Make sure that the NUL byte is marked in the syndrome. */
- orr has_nul, has_nul, mask
-
-L(not_limit):
- /* For big-endian we cannot use the trick with the syndrome value
- as carry-propagation can corrupt the upper bits if the trailing
- bytes in the string contain 0x01. */
- /* However, if there is no NUL byte in the dword, we can generate
- the result directly. We can't just subtract the bytes as the
- MSB might be significant. */
- cbnz has_nul, 1f
- cmp data1, data2
- cset result, ne
- cneg result, result, lo
- ret
-1:
- /* Re-compute the NUL-byte detection, using a byte-reversed value. */
- rev tmp3, data1
- sub tmp1, tmp3, zeroones
- orr tmp2, tmp3, #REP8_7f
- bic has_nul, tmp1, tmp2
- rev has_nul, has_nul
- orr syndrome, diff, has_nul
- clz pos, syndrome
- /* The most-significant-non-zero bit of the syndrome marks either the
- first bit that is different, or the top bit of the first zero byte.
- Shifting left now will bring the critical information into the
- top bits. */
-L(end_quick):
- lsl data1, data1, pos
- lsl data2, data2, pos
- /* But we need to zero-extend (char is unsigned) the value and then
- perform a signed 32-bit subtraction. */
- lsr data1, data1, #56
- sub result, data1, data2, lsr #56
- ret
-#endif
-
-L(mutual_align):
- /* Sources are mutually aligned, but are not currently at an
- alignment boundary. Round down the addresses and then mask off
- the bytes that precede the start point.
- We also need to adjust the limit calculations, but without
- overflowing if the limit is near ULONG_MAX. */
- bic src1, src1, #7
- bic src2, src2, #7
- ldr data1, [src1], #8
- neg tmp3, count, lsl #3 /* 64 - bits(bytes beyond align). */
- ldr data2, [src2], #8
- mov tmp2, #~0
- LS_FW tmp2, tmp2, tmp3 /* Shift (count & 63). */
- /* Adjust the limit and ensure it doesn't overflow. */
- adds limit, limit, count
- csinv limit, limit, xzr, lo
- orr data1, data1, tmp2
- orr data2, data2, tmp2
- b L(start_realigned)
-
- .p2align 4
- /* Don't bother with dwords for up to 16 bytes. */
-L(misaligned8):
- cmp limit, #16
- b.hs L(try_misaligned_words)
-
-L(byte_loop):
- /* Perhaps we can do better than this. */
- ldrb data1w, [src1], #1
- ldrb data2w, [src2], #1
- subs limit, limit, #1
- ccmp data1w, #1, #0, hi /* NZCV = 0b0000. */
- ccmp data1w, data2w, #0, cs /* NZCV = 0b0000. */
- b.eq L(byte_loop)
-L(done):
- sub result, data1, data2
- ret
- /* Align the SRC1 to a dword by doing a bytewise compare and then do
- the dword loop. */
-L(try_misaligned_words):
- cbz count, L(src1_aligned)
-
- neg count, count
- and count, count, #7
- sub limit, limit, count
-
-L(page_end_loop):
- ldrb data1w, [src1], #1
- ldrb data2w, [src2], #1
- cmp data1w, #1
- ccmp data1w, data2w, #0, cs /* NZCV = 0b0000. */
- b.ne L(done)
- subs count, count, #1
- b.hi L(page_end_loop)
-
- /* The following diagram explains the comparison of misaligned strings.
- The bytes are shown in natural order. For little-endian, it is
- reversed in the registers. The "x" bytes are before the string.
- The "|" separates data that is loaded at one time.
- src1 | a a a a a a a a | b b b c c c c c | . . .
- src2 | x x x x x a a a a a a a a b b b | c c c c c . . .
-
- After shifting in each step, the data looks like this:
- STEP_A STEP_B STEP_C
- data1 a a a a a a a a b b b c c c c c b b b c c c c c
- data2 a a a a a a a a b b b 0 0 0 0 0 0 0 0 c c c c c
-
- The bytes with "0" are eliminated from the syndrome via mask.
-
- Align SRC2 down to 16 bytes. This way we can read 16 bytes at a
- time from SRC2. The comparison happens in 3 steps. After each step
- the loop can exit, or read from SRC1 or SRC2. */
-L(src1_aligned):
- /* Calculate offset from 8 byte alignment to string start in bits. No
- need to mask offset since shifts are ignoring upper bits. */
- lsl offset, src2, #3
- bic src2, src2, #0xf
- mov mask, -1
- neg neg_offset, offset
- ldr data1, [src1], #8
- ldp tmp1, tmp2, [src2], #16
- LS_BK mask, mask, neg_offset
- and neg_offset, neg_offset, #63 /* Need actual value for cmp later. */
- /* Skip the first compare if data in tmp1 is irrelevant. */
- tbnz offset, 6, L(misaligned_mid_loop)
-
-L(loop_misaligned):
- /* STEP_A: Compare full 8 bytes when there is enough data from SRC2.*/
- LS_FW data2, tmp1, offset
- LS_BK tmp1, tmp2, neg_offset
- subs limit, limit, #8
- orr data2, data2, tmp1 /* 8 bytes from SRC2 combined from two regs.*/
- sub has_nul, data1, zeroones
- eor diff, data1, data2 /* Non-zero if differences found. */
- orr tmp3, data1, #REP8_7f
- csinv endloop, diff, xzr, hi /* If limit, set to all ones. */
- bic has_nul, has_nul, tmp3 /* Non-zero if NUL byte found in SRC1. */
- orr tmp3, endloop, has_nul
- cbnz tmp3, L(full_check)
-
- ldr data1, [src1], #8
-L(misaligned_mid_loop):
- /* STEP_B: Compare first part of data1 to second part of tmp2. */
- LS_FW data2, tmp2, offset
-#ifdef __AARCH64EB__
- /* For big-endian we do a byte reverse to avoid carry-propagation
- problem described above. This way we can reuse the has_nul in the
- next step and also use syndrome value trick at the end. */
- rev tmp3, data1
- #define data1_fixed tmp3
-#else
- #define data1_fixed data1
-#endif
- sub has_nul, data1_fixed, zeroones
- orr tmp3, data1_fixed, #REP8_7f
- eor diff, data2, data1 /* Non-zero if differences found. */
- bic has_nul, has_nul, tmp3 /* Non-zero if NUL terminator. */
-#ifdef __AARCH64EB__
- rev has_nul, has_nul
-#endif
- cmp limit, neg_offset, lsr #3
- orr syndrome, diff, has_nul
- bic syndrome, syndrome, mask /* Ignore later bytes. */
- csinv tmp3, syndrome, xzr, hi /* If limit, set to all ones. */
- cbnz tmp3, L(syndrome_check)
-
- /* STEP_C: Compare second part of data1 to first part of tmp1. */
- ldp tmp1, tmp2, [src2], #16
- cmp limit, #8
- LS_BK data2, tmp1, neg_offset
- eor diff, data2, data1 /* Non-zero if differences found. */
- orr syndrome, diff, has_nul
- and syndrome, syndrome, mask /* Ignore earlier bytes. */
- csinv tmp3, syndrome, xzr, hi /* If limit, set to all ones. */
- cbnz tmp3, L(syndrome_check)
-
- ldr data1, [src1], #8
- sub limit, limit, #8
- b L(loop_misaligned)
-
-#ifdef __AARCH64EB__
-L(syndrome_check):
- clz pos, syndrome
- cmp pos, limit, lsl #3
- b.lo L(end_quick)
-#endif
-
-L(ret0):
- mov result, #0
- ret
-END(__strncmp_aarch64_mte)
-
diff --git a/contrib/arm-optimized-routines/string/aarch64/strncmp.S b/contrib/arm-optimized-routines/string/aarch64/strncmp.S
index 738b6539cab6..7e636b4a593d 100644
--- a/contrib/arm-optimized-routines/string/aarch64/strncmp.S
+++ b/contrib/arm-optimized-routines/string/aarch64/strncmp.S
@@ -1,20 +1,20 @@
/*
* strncmp - compare two strings
*
- * Copyright (c) 2013-2021, Arm Limited.
+ * Copyright (c) 2013-2022, Arm Limited.
* SPDX-License-Identifier: MIT
*/
/* Assumptions:
*
- * ARMv8-a, AArch64
+ * ARMv8-a, AArch64.
+ * MTE compatible.
*/
#include "../asmdefs.h"
#define REP8_01 0x0101010101010101
#define REP8_7f 0x7f7f7f7f7f7f7f7f
-#define REP8_80 0x8080808080808080
/* Parameters and result. */
#define src1 x0
@@ -35,10 +35,24 @@
#define tmp3 x10
#define zeroones x11
#define pos x12
-#define limit_wd x13
-#define mask x14
-#define endloop x15
+#define mask x13
+#define endloop x14
#define count mask
+#define offset pos
+#define neg_offset x15
+
+/* Define endian dependent shift operations.
+ On big-endian early bytes are at MSB and on little-endian LSB.
+ LS_FW means shifting towards early bytes.
+ LS_BK means shifting towards later bytes.
+ */
+#ifdef __AARCH64EB__
+#define LS_FW lsl
+#define LS_BK lsr
+#else
+#define LS_FW lsr
+#define LS_BK lsl
+#endif
ENTRY (__strncmp_aarch64)
PTR_ARG (0)
@@ -51,9 +65,6 @@ ENTRY (__strncmp_aarch64)
and count, src1, #7
b.ne L(misaligned8)
cbnz count, L(mutual_align)
- /* Calculate the number of full and partial words -1. */
- sub limit_wd, limit, #1 /* limit != 0, so no underflow. */
- lsr limit_wd, limit_wd, #3 /* Convert to Dwords. */
/* NUL detection works on the principle that (X - 1) & (~X) & 0x80
(=> (X - 1) & ~(X | 0x7f)) is non-zero iff a byte is zero, and
@@ -63,56 +74,52 @@ L(loop_aligned):
ldr data1, [src1], #8
ldr data2, [src2], #8
L(start_realigned):
- subs limit_wd, limit_wd, #1
+ subs limit, limit, #8
sub tmp1, data1, zeroones
orr tmp2, data1, #REP8_7f
eor diff, data1, data2 /* Non-zero if differences found. */
- csinv endloop, diff, xzr, pl /* Last Dword or differences. */
+ csinv endloop, diff, xzr, hi /* Last Dword or differences. */
bics has_nul, tmp1, tmp2 /* Non-zero if NUL terminator. */
ccmp endloop, #0, #0, eq
b.eq L(loop_aligned)
/* End of main loop */
- /* Not reached the limit, must have found the end or a diff. */
- tbz limit_wd, #63, L(not_limit)
-
- /* Limit % 8 == 0 => all bytes significant. */
- ands limit, limit, #7
- b.eq L(not_limit)
-
- lsl limit, limit, #3 /* Bits -> bytes. */
- mov mask, #~0
-#ifdef __AARCH64EB__
- lsr mask, mask, limit
-#else
- lsl mask, mask, limit
-#endif
- bic data1, data1, mask
- bic data2, data2, mask
-
- /* Make sure that the NUL byte is marked in the syndrome. */
- orr has_nul, has_nul, mask
-
-L(not_limit):
+L(full_check):
+#ifndef __AARCH64EB__
orr syndrome, diff, has_nul
-
-#ifndef __AARCH64EB__
+ add limit, limit, 8 /* Rewind limit to before last subs. */
+L(syndrome_check):
+ /* Limit was reached. Check if the NUL byte or the difference
+ is before the limit. */
rev syndrome, syndrome
rev data1, data1
- /* The MS-non-zero bit of the syndrome marks either the first bit
- that is different, or the top bit of the first zero byte.
- Shifting left now will bring the critical information into the
- top bits. */
clz pos, syndrome
rev data2, data2
lsl data1, data1, pos
+ cmp limit, pos, lsr #3
lsl data2, data2, pos
/* But we need to zero-extend (char is unsigned) the value and then
perform a signed 32-bit subtraction. */
lsr data1, data1, #56
sub result, data1, data2, lsr #56
+ csel result, result, xzr, hi
ret
#else
+ /* Not reached the limit, must have found the end or a diff. */
+ tbz limit, #63, L(not_limit)
+ add tmp1, limit, 8
+ cbz limit, L(not_limit)
+
+ lsl limit, tmp1, #3 /* Bits -> bytes. */
+ mov mask, #~0
+ lsr mask, mask, limit
+ bic data1, data1, mask
+ bic data2, data2, mask
+
+ /* Make sure that the NUL byte is marked in the syndrome. */
+ orr has_nul, has_nul, mask
+
+L(not_limit):
/* For big-endian we cannot use the trick with the syndrome value
as carry-propagation can corrupt the upper bits if the trailing
bytes in the string contain 0x01. */
@@ -133,10 +140,11 @@ L(not_limit):
rev has_nul, has_nul
orr syndrome, diff, has_nul
clz pos, syndrome
- /* The MS-non-zero bit of the syndrome marks either the first bit
- that is different, or the top bit of the first zero byte.
+ /* The most-significant-non-zero bit of the syndrome marks either the
+ first bit that is different, or the top bit of the first zero byte.
Shifting left now will bring the critical information into the
top bits. */
+L(end_quick):
lsl data1, data1, pos
lsl data2, data2, pos
/* But we need to zero-extend (char is unsigned) the value and then
@@ -158,22 +166,12 @@ L(mutual_align):
neg tmp3, count, lsl #3 /* 64 - bits(bytes beyond align). */
ldr data2, [src2], #8
mov tmp2, #~0
- sub limit_wd, limit, #1 /* limit != 0, so no underflow. */
-#ifdef __AARCH64EB__
- /* Big-endian. Early bytes are at MSB. */
- lsl tmp2, tmp2, tmp3 /* Shift (count & 63). */
-#else
- /* Little-endian. Early bytes are at LSB. */
- lsr tmp2, tmp2, tmp3 /* Shift (count & 63). */
-#endif
- and tmp3, limit_wd, #7
- lsr limit_wd, limit_wd, #3
- /* Adjust the limit. Only low 3 bits used, so overflow irrelevant. */
- add limit, limit, count
- add tmp3, tmp3, count
+ LS_FW tmp2, tmp2, tmp3 /* Shift (count & 63). */
+ /* Adjust the limit and ensure it doesn't overflow. */
+ adds limit, limit, count
+ csinv limit, limit, xzr, lo
orr data1, data1, tmp2
orr data2, data2, tmp2
- add limit_wd, limit_wd, tmp3, lsr #3
b L(start_realigned)
.p2align 4
@@ -196,13 +194,11 @@ L(done):
/* Align the SRC1 to a dword by doing a bytewise compare and then do
the dword loop. */
L(try_misaligned_words):
- lsr limit_wd, limit, #3
- cbz count, L(do_misaligned)
+ cbz count, L(src1_aligned)
neg count, count
and count, count, #7
sub limit, limit, count
- lsr limit_wd, limit, #3
L(page_end_loop):
ldrb data1w, [src1], #1
@@ -213,48 +209,100 @@ L(page_end_loop):
subs count, count, #1
b.hi L(page_end_loop)
-L(do_misaligned):
- /* Prepare ourselves for the next page crossing. Unlike the aligned
- loop, we fetch 1 less dword because we risk crossing bounds on
- SRC2. */
- mov count, #8
- subs limit_wd, limit_wd, #1
- b.lo L(done_loop)
-L(loop_misaligned):
- and tmp2, src2, #0xff8
- eor tmp2, tmp2, #0xff8
- cbz tmp2, L(page_end_loop)
+ /* The following diagram explains the comparison of misaligned strings.
+ The bytes are shown in natural order. For little-endian, it is
+ reversed in the registers. The "x" bytes are before the string.
+ The "|" separates data that is loaded at one time.
+ src1 | a a a a a a a a | b b b c c c c c | . . .
+ src2 | x x x x x a a a a a a a a b b b | c c c c c . . .
+
+ After shifting in each step, the data looks like this:
+ STEP_A STEP_B STEP_C
+ data1 a a a a a a a a b b b c c c c c b b b c c c c c
+ data2 a a a a a a a a b b b 0 0 0 0 0 0 0 0 c c c c c
+ The bytes with "0" are eliminated from the syndrome via mask.
+
+ Align SRC2 down to 16 bytes. This way we can read 16 bytes at a
+ time from SRC2. The comparison happens in 3 steps. After each step
+ the loop can exit, or read from SRC1 or SRC2. */
+L(src1_aligned):
+ /* Calculate offset from 8 byte alignment to string start in bits. No
+ need to mask offset since shifts are ignoring upper bits. */
+ lsl offset, src2, #3
+ bic src2, src2, #0xf
+ mov mask, -1
+ neg neg_offset, offset
ldr data1, [src1], #8
- ldr data2, [src2], #8
- sub tmp1, data1, zeroones
- orr tmp2, data1, #REP8_7f
- eor diff, data1, data2 /* Non-zero if differences found. */
- bics has_nul, tmp1, tmp2 /* Non-zero if NUL terminator. */
- ccmp diff, #0, #0, eq
- b.ne L(not_limit)
- subs limit_wd, limit_wd, #1
- b.pl L(loop_misaligned)
+ ldp tmp1, tmp2, [src2], #16
+ LS_BK mask, mask, neg_offset
+ and neg_offset, neg_offset, #63 /* Need actual value for cmp later. */
+ /* Skip the first compare if data in tmp1 is irrelevant. */
+ tbnz offset, 6, L(misaligned_mid_loop)
-L(done_loop):
- /* We found a difference or a NULL before the limit was reached. */
- and limit, limit, #7
- cbz limit, L(not_limit)
- /* Read the last word. */
- sub src1, src1, 8
- sub src2, src2, 8
- ldr data1, [src1, limit]
- ldr data2, [src2, limit]
- sub tmp1, data1, zeroones
- orr tmp2, data1, #REP8_7f
+L(loop_misaligned):
+ /* STEP_A: Compare full 8 bytes when there is enough data from SRC2.*/
+ LS_FW data2, tmp1, offset
+ LS_BK tmp1, tmp2, neg_offset
+ subs limit, limit, #8
+ orr data2, data2, tmp1 /* 8 bytes from SRC2 combined from two regs.*/
+ sub has_nul, data1, zeroones
eor diff, data1, data2 /* Non-zero if differences found. */
- bics has_nul, tmp1, tmp2 /* Non-zero if NUL terminator. */
- ccmp diff, #0, #0, eq
- b.ne L(not_limit)
+ orr tmp3, data1, #REP8_7f
+ csinv endloop, diff, xzr, hi /* If limit, set to all ones. */
+ bic has_nul, has_nul, tmp3 /* Non-zero if NUL byte found in SRC1. */
+ orr tmp3, endloop, has_nul
+ cbnz tmp3, L(full_check)
+
+ ldr data1, [src1], #8
+L(misaligned_mid_loop):
+ /* STEP_B: Compare first part of data1 to second part of tmp2. */
+ LS_FW data2, tmp2, offset
+#ifdef __AARCH64EB__
+ /* For big-endian we do a byte reverse to avoid carry-propagation
+ problem described above. This way we can reuse the has_nul in the
+ next step and also use syndrome value trick at the end. */
+ rev tmp3, data1
+ #define data1_fixed tmp3
+#else
+ #define data1_fixed data1
+#endif
+ sub has_nul, data1_fixed, zeroones
+ orr tmp3, data1_fixed, #REP8_7f
+ eor diff, data2, data1 /* Non-zero if differences found. */
+ bic has_nul, has_nul, tmp3 /* Non-zero if NUL terminator. */
+#ifdef __AARCH64EB__
+ rev has_nul, has_nul
+#endif
+ cmp limit, neg_offset, lsr #3
+ orr syndrome, diff, has_nul
+ bic syndrome, syndrome, mask /* Ignore later bytes. */
+ csinv tmp3, syndrome, xzr, hi /* If limit, set to all ones. */
+ cbnz tmp3, L(syndrome_check)
+
+ /* STEP_C: Compare second part of data1 to first part of tmp1. */
+ ldp tmp1, tmp2, [src2], #16
+ cmp limit, #8
+ LS_BK data2, tmp1, neg_offset
+ eor diff, data2, data1 /* Non-zero if differences found. */
+ orr syndrome, diff, has_nul
+ and syndrome, syndrome, mask /* Ignore earlier bytes. */
+ csinv tmp3, syndrome, xzr, hi /* If limit, set to all ones. */
+ cbnz tmp3, L(syndrome_check)
+
+ ldr data1, [src1], #8
+ sub limit, limit, #8
+ b L(loop_misaligned)
+
+#ifdef __AARCH64EB__
+L(syndrome_check):
+ clz pos, syndrome
+ cmp pos, limit, lsl #3
+ b.lo L(end_quick)
+#endif
L(ret0):
mov result, #0
ret
-
-END ( __strncmp_aarch64)
+END(__strncmp_aarch64)
diff --git a/contrib/arm-optimized-routines/string/bench/memcpy.c b/contrib/arm-optimized-routines/string/bench/memcpy.c
index d5d4ea7e0309..6bd27633e224 100644
--- a/contrib/arm-optimized-routines/string/bench/memcpy.c
+++ b/contrib/arm-optimized-routines/string/bench/memcpy.c
@@ -1,7 +1,7 @@
/*
* memcpy benchmark.
*
- * Copyright (c) 2020, Arm Limited.
+ * Copyright (c) 2020-2021, Arm Limited.
* SPDX-License-Identifier: MIT
*/
@@ -13,14 +13,15 @@
#include "stringlib.h"
#include "benchlib.h"
-#define ITERS 5000
+#define ITERS 5000
#define ITERS2 20000000
-#define ITERS3 500000
-#define MAX_COPIES 8192
-#define SIZE (256*1024)
+#define ITERS3 200000
+#define NUM_TESTS 16384
+#define MIN_SIZE 32768
+#define MAX_SIZE (1024 * 1024)
-static uint8_t a[SIZE + 4096] __attribute__((__aligned__(64)));
-static uint8_t b[SIZE + 4096] __attribute__((__aligned__(64)));
+static uint8_t a[MAX_SIZE + 4096 + 64] __attribute__((__aligned__(64)));
+static uint8_t b[MAX_SIZE + 4096 + 64] __attribute__((__aligned__(64)));
#define F(x) {#x, x},
@@ -30,15 +31,18 @@ static const struct fun
void *(*fun)(void *, const void *, size_t);
} funtab[] =
{
- F(memcpy)
#if __aarch64__
F(__memcpy_aarch64)
# if __ARM_NEON
F(__memcpy_aarch64_simd)
# endif
+# if __ARM_FEATURE_SVE
+ F(__memcpy_aarch64_sve)
+# endif
#elif __arm__
F(__memcpy_arm)
#endif
+ F(memcpy)
#undef F
{0, 0}
};
@@ -109,7 +113,7 @@ typedef struct
uint64_t len : 16;
} copy_t;
-static copy_t copy[MAX_COPIES];
+static copy_t test_arr[NUM_TESTS];
typedef char *(*proto_t) (char *, const char *, size_t);
@@ -140,14 +144,14 @@ init_copies (size_t max_size)
size_t total = 0;
/* Create a random set of copies with the given size and alignment
distributions. */
- for (int i = 0; i < MAX_COPIES; i++)
+ for (int i = 0; i < NUM_TESTS; i++)
{
- copy[i].dst = (rand32 (0) & (max_size - 1));
- copy[i].dst &= ~dst_align_arr[rand32 (0) & ALIGN_MASK];
- copy[i].src = (rand32 (0) & (max_size - 1));
- copy[i].src &= ~src_align_arr[rand32 (0) & ALIGN_MASK];
- copy[i].len = size_arr[rand32 (0) & SIZE_MASK];
- total += copy[i].len;
+ test_arr[i].dst = (rand32 (0) & (max_size - 1));
+ test_arr[i].dst &= ~dst_align_arr[rand32 (0) & ALIGN_MASK];
+ test_arr[i].src = (rand32 (0) & (max_size - 1));
+ test_arr[i].src &= ~src_align_arr[rand32 (0) & ALIGN_MASK];
+ test_arr[i].len = size_arr[rand32 (0) & SIZE_MASK];
+ total += test_arr[i].len;
}
return total;
@@ -160,25 +164,27 @@ int main (void)
memset (a, 1, sizeof (a));
memset (b, 2, sizeof (b));
- printf("Random memcpy:\n");
+ printf("Random memcpy (bytes/ns):\n");
for (int f = 0; funtab[f].name != 0; f++)
{
size_t total = 0;
uint64_t tsum = 0;
- printf ("%22s (B/ns) ", funtab[f].name);
+ printf ("%22s ", funtab[f].name);
rand32 (0x12345678);
- for (int size = 16384; size <= SIZE; size *= 2)
+ for (int size = MIN_SIZE; size <= MAX_SIZE; size *= 2)
{
size_t copy_size = init_copies (size) * ITERS;
- for (int c = 0; c < MAX_COPIES; c++)
- funtab[f].fun (b + copy[c].dst, a + copy[c].src, copy[c].len);
+ for (int c = 0; c < NUM_TESTS; c++)
+ funtab[f].fun (b + test_arr[c].dst, a + test_arr[c].src,
+ test_arr[c].len);
uint64_t t = clock_get_ns ();
for (int i = 0; i < ITERS; i++)
- for (int c = 0; c < MAX_COPIES; c++)
- funtab[f].fun (b + copy[c].dst, a + copy[c].src, copy[c].len);
+ for (int c = 0; c < NUM_TESTS; c++)
+ funtab[f].fun (b + test_arr[c].dst, a + test_arr[c].src,
+ test_arr[c].len);
t = clock_get_ns () - t;
total += copy_size;
tsum += t;
@@ -187,74 +193,147 @@ int main (void)
printf( "avg %.2f\n", (double)total / tsum);
}
- printf ("\nMedium memcpy:\n");
+ size_t total = 0;
+ uint64_t tsum = 0;
+ printf ("%22s ", "memcpy_call");
+ rand32 (0x12345678);
+
+ for (int size = MIN_SIZE; size <= MAX_SIZE; size *= 2)
+ {
+ size_t copy_size = init_copies (size) * ITERS;
+
+ for (int c = 0; c < NUM_TESTS; c++)
+ memcpy (b + test_arr[c].dst, a + test_arr[c].src, test_arr[c].len);
+
+ uint64_t t = clock_get_ns ();
+ for (int i = 0; i < ITERS; i++)
+ for (int c = 0; c < NUM_TESTS; c++)
+ memcpy (b + test_arr[c].dst, a + test_arr[c].src, test_arr[c].len);
+ t = clock_get_ns () - t;
+ total += copy_size;
+ tsum += t;
+ printf ("%dK: %.2f ", size / 1024, (double)copy_size / t);
+ }
+ printf( "avg %.2f\n", (double)total / tsum);
+
+
+ printf ("\nAligned medium memcpy (bytes/ns):\n");
for (int f = 0; funtab[f].name != 0; f++)
{
- printf ("%22s (B/ns) ", funtab[f].name);
+ printf ("%22s ", funtab[f].name);
- for (int size = 16; size <= 512; size *= 2)
+ for (int size = 8; size <= 512; size *= 2)
{
uint64_t t = clock_get_ns ();
for (int i = 0; i < ITERS2; i++)
funtab[f].fun (b, a, size);
t = clock_get_ns () - t;
- printf ("%d%c: %.2f ", size < 1024 ? size : size / 1024,
- size < 1024 ? 'B' : 'K', (double)size * ITERS2 / t);
+ printf ("%dB: %.2f ", size, (double)size * ITERS2 / t);
+ }
+ printf ("\n");
+ }
+
+ printf ("%22s ", "memcpy_call");
+ for (int size = 8; size <= 512; size *= 2)
+ {
+ uint64_t t = clock_get_ns ();
+ for (int i = 0; i < ITERS2; i++)
+ memcpy (b, a, size);
+ t = clock_get_ns () - t;
+ printf ("%dB: %.2f ", size, (double)size * ITERS2 / t);
+ }
+ printf ("\n");
+
+
+ printf ("\nUnaligned medium memcpy (bytes/ns):\n");
+ for (int f = 0; funtab[f].name != 0; f++)
+ {
+ printf ("%22s ", funtab[f].name);
+
+ for (int size = 8; size <= 512; size *= 2)
+ {
+ uint64_t t = clock_get_ns ();
+ for (int i = 0; i < ITERS2; i++)
+ funtab[f].fun (b + 3, a + 1, size);
+ t = clock_get_ns () - t;
+ printf ("%dB: %.2f ", size, (double)size * ITERS2 / t);
}
printf ("\n");
}
- printf ("\nLarge memcpy:\n");
+ printf ("%22s ", "memcpy_call");
+ for (int size = 8; size <= 512; size *= 2)
+ {
+ uint64_t t = clock_get_ns ();
+ for (int i = 0; i < ITERS2; i++)
+ memcpy (b + 3, a + 1, size);
+ t = clock_get_ns () - t;
+ printf ("%dB: %.2f ", size, (double)size * ITERS2 / t);
+ }
+ printf ("\n");
+
+
+ printf ("\nLarge memcpy (bytes/ns):\n");
for (int f = 0; funtab[f].name != 0; f++)
{
- printf ("%22s (B/ns) ", funtab[f].name);
+ printf ("%22s ", funtab[f].name);
- for (int size = 1024; size <= 32768; size *= 2)
+ for (int size = 1024; size <= 65536; size *= 2)
{
uint64_t t = clock_get_ns ();
for (int i = 0; i < ITERS3; i++)
funtab[f].fun (b, a, size);
t = clock_get_ns () - t;
- printf ("%d%c: %.2f ", size < 1024 ? size : size / 1024,
- size < 1024 ? 'B' : 'K', (double)size * ITERS3 / t);
+ printf ("%dK: %.2f ", size / 1024, (double)size * ITERS3 / t);
}
printf ("\n");
}
- printf ("\nUnaligned forwards memmove:\n");
+ printf ("%22s ", "memcpy_call");
+ for (int size = 1024; size <= 65536; size *= 2)
+ {
+ uint64_t t = clock_get_ns ();
+ for (int i = 0; i < ITERS3; i++)
+ memcpy (b, a, size);
+ t = clock_get_ns () - t;
+ printf ("%dK: %.2f ", size / 1024, (double)size * ITERS3 / t);
+ }
+ printf ("\n");
+
+
+ printf ("\nUnaligned forwards memmove (bytes/ns):\n");
for (int f = 0; funtab[f].name != 0; f++)
{
- printf ("%22s (B/ns) ", funtab[f].name);
+ printf ("%22s ", funtab[f].name);
- for (int size = 1024; size <= 32768; size *= 2)
+ for (int size = 1024; size <= 65536; size *= 2)
{
uint64_t t = clock_get_ns ();
for (int i = 0; i < ITERS3; i++)
funtab[f].fun (a, a + 256 + (i & 31), size);
t = clock_get_ns () - t;
- printf ("%d%c: %.2f ", size < 1024 ? size : size / 1024,
- size < 1024 ? 'B' : 'K', (double)size * ITERS3 / t);
+ printf ("%dK: %.2f ", size / 1024, (double)size * ITERS3 / t);
}
printf ("\n");
}
- printf ("\nUnaligned backwards memmove:\n");
+ printf ("\nUnaligned backwards memmove (bytes/ns):\n");
for (int f = 0; funtab[f].name != 0; f++)
{
- printf ("%22s (B/ns) ", funtab[f].name);
+ printf ("%22s ", funtab[f].name);
- for (int size = 1024; size <= 32768; size *= 2)
+ for (int size = 1024; size <= 65536; size *= 2)
{
uint64_t t = clock_get_ns ();
for (int i = 0; i < ITERS3; i++)
funtab[f].fun (a + 256 + (i & 31), a, size);
t = clock_get_ns () - t;
- printf ("%d%c: %.2f ", size < 1024 ? size : size / 1024,
- size < 1024 ? 'B' : 'K', (double)size * ITERS3 / t);
+ printf ("%dK: %.2f ", size / 1024, (double)size * ITERS3 / t);
}
printf ("\n");
}
+ printf ("\n");
return 0;
}
diff --git a/contrib/arm-optimized-routines/string/bench/memset.c b/contrib/arm-optimized-routines/string/bench/memset.c
new file mode 100644
index 000000000000..2d6196931307
--- /dev/null
+++ b/contrib/arm-optimized-routines/string/bench/memset.c
@@ -0,0 +1,243 @@
+/*
+ * memset benchmark.
+ *
+ * Copyright (c) 2021, Arm Limited.
+ * SPDX-License-Identifier: MIT
+ */
+
+#define _GNU_SOURCE
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include "stringlib.h"
+#include "benchlib.h"
+
+#define ITERS 5000
+#define ITERS2 20000000
+#define ITERS3 1000000
+#define NUM_TESTS 16384
+#define MIN_SIZE 32768
+#define MAX_SIZE (1024 * 1024)
+
+static uint8_t a[MAX_SIZE + 4096] __attribute__((__aligned__(64)));
+
+#define F(x) {#x, x},
+
+static const struct fun
+{
+ const char *name;
+ void *(*fun)(void *, int, size_t);
+} funtab[] =
+{
+#if __aarch64__
+ F(__memset_aarch64)
+#elif __arm__
+ F(__memset_arm)
+#endif
+ F(memset)
+#undef F
+ {0, 0}
+};
+
+typedef struct { uint32_t offset : 20, len : 12; } memset_test_t;
+static memset_test_t test_arr[NUM_TESTS];
+
+typedef struct { uint16_t size; uint16_t freq; } freq_data_t;
+typedef struct { uint8_t align; uint16_t freq; } align_data_t;
+
+#define SIZE_NUM 65536
+#define SIZE_MASK (SIZE_NUM-1)
+static uint8_t len_arr[SIZE_NUM];
+
+/* Frequency data for memset sizes up to 4096 based on SPEC2017. */
+static freq_data_t memset_len_freq[] =
+{
+{40,28817}, {32,15336}, { 16,3823}, {296,3545}, { 24,3454}, { 8,1412},
+{292,1202}, { 48, 927}, { 12, 613}, { 11, 539}, {284, 493}, {108, 414},
+{ 88, 380}, { 20, 295}, {312, 271}, { 72, 233}, { 2, 200}, { 4, 192},
+{ 15, 180}, { 14, 174}, { 13, 160}, { 56, 151}, { 36, 144}, { 64, 140},
+{4095,133}, { 10, 130}, { 9, 124}, { 3, 124}, { 28, 120}, { 0, 118},
+{288, 110}, {1152, 96}, {104, 90}, { 1, 86}, {832, 76}, {248, 74},
+{1024, 69}, {120, 64}, {512, 63}, {384, 60}, { 6, 59}, { 80, 54},
+{ 17, 50}, { 7, 49}, {520, 47}, {2048, 39}, {256, 37}, {864, 33},
+{1440, 28}, { 22, 27}, {2056, 24}, {260, 23}, { 68, 23}, { 5, 22},
+{ 18, 21}, {200, 18}, {2120, 18}, { 60, 17}, { 52, 16}, {336, 15},
+{ 44, 13}, {192, 13}, {160, 12}, {2064, 12}, {128, 12}, { 76, 11},
+{164, 11}, {152, 10}, {136, 9}, {488, 7}, { 96, 6}, {560, 6},
+{1016, 6}, {112, 5}, {232, 5}, {168, 5}, {952, 5}, {184, 5},
+{144, 4}, {252, 4}, { 84, 3}, {960, 3}, {3808, 3}, {244, 3},
+{280, 3}, {224, 3}, {156, 3}, {1088, 3}, {440, 3}, {216, 2},
+{304, 2}, { 23, 2}, { 25, 2}, { 26, 2}, {264, 2}, {328, 2},
+{1096, 2}, {240, 2}, {1104, 2}, {704, 2}, {1664, 2}, {360, 2},
+{808, 1}, {544, 1}, {236, 1}, {720, 1}, {368, 1}, {424, 1},
+{640, 1}, {1112, 1}, {552, 1}, {272, 1}, {776, 1}, {376, 1},
+{ 92, 1}, {536, 1}, {824, 1}, {496, 1}, {760, 1}, {792, 1},
+{504, 1}, {344, 1}, {1816, 1}, {880, 1}, {176, 1}, {320, 1},
+{352, 1}, {2008, 1}, {208, 1}, {408, 1}, {228, 1}, {2072, 1},
+{568, 1}, {220, 1}, {616, 1}, {600, 1}, {392, 1}, {696, 1},
+{2144, 1}, {1280, 1}, {2136, 1}, {632, 1}, {584, 1}, {456, 1},
+{472, 1}, {3440, 1}, {2088, 1}, {680, 1}, {2928, 1}, {212, 1},
+{648, 1}, {1752, 1}, {664, 1}, {3512, 1}, {1032, 1}, {528, 1},
+{4072, 1}, {204, 1}, {2880, 1}, {3392, 1}, {712, 1}, { 59, 1},
+{736, 1}, {592, 1}, {2520, 1}, {744, 1}, {196, 1}, {172, 1},
+{728, 1}, {2040, 1}, {1192, 1}, {3600, 1}, {0, 0}
+};
+
+#define ALIGN_NUM 1024
+#define ALIGN_MASK (ALIGN_NUM-1)
+static uint8_t align_arr[ALIGN_NUM];
+
+/* Alignment data for memset based on SPEC2017. */
+static align_data_t memset_align_freq[] =
+{
+ {16, 338}, {8, 307}, {32, 148}, {64, 131}, {4, 72}, {1, 23}, {2, 5}, {0, 0}
+};
+
+static void
+init_memset_distribution (void)
+{
+ int i, j, freq, size, n;
+
+ for (n = i = 0; (freq = memset_len_freq[i].freq) != 0; i++)
+ for (j = 0, size = memset_len_freq[i].size; j < freq; j++)
+ len_arr[n++] = size;
+ assert (n == SIZE_NUM);
+
+ for (n = i = 0; (freq = memset_align_freq[i].freq) != 0; i++)
+ for (j = 0, size = memset_align_freq[i].align; j < freq; j++)
+ align_arr[n++] = size - 1;
+ assert (n == ALIGN_NUM);
+}
+
+static size_t
+init_memset (size_t max_size)
+{
+ size_t total = 0;
+ /* Create a random set of memsets with the given size and alignment
+ distributions. */
+ for (int i = 0; i < NUM_TESTS; i++)
+ {
+ test_arr[i].offset = (rand32 (0) & (max_size - 1));
+ test_arr[i].offset &= ~align_arr[rand32 (0) & ALIGN_MASK];
+ test_arr[i].len = len_arr[rand32 (0) & SIZE_MASK];
+ total += test_arr[i].len;
+ }
+
+ return total;
+}
+
+
+int main (void)
+{
+ init_memset_distribution ();
+
+ memset (a, 1, sizeof (a));
+
+ printf("Random memset (bytes/ns):\n");
+ for (int f = 0; funtab[f].name != 0; f++)
+ {
+ size_t total_size = 0;
+ uint64_t tsum = 0;
+ printf ("%22s ", funtab[f].name);
+ rand32 (0x12345678);
+
+ for (int size = MIN_SIZE; size <= MAX_SIZE; size *= 2)
+ {
+ size_t memset_size = init_memset (size) * ITERS;
+
+ for (int c = 0; c < NUM_TESTS; c++)
+ funtab[f].fun (a + test_arr[c].offset, 0, test_arr[c].len);
+
+ uint64_t t = clock_get_ns ();
+ for (int i = 0; i < ITERS; i++)
+ for (int c = 0; c < NUM_TESTS; c++)
+ funtab[f].fun (a + test_arr[c].offset, 0, test_arr[c].len);
+ t = clock_get_ns () - t;
+ total_size += memset_size;
+ tsum += t;
+ printf ("%dK: %.2f ", size / 1024, (double)memset_size / t);
+ }
+ printf( "avg %.2f\n", (double)total_size / tsum);
+ }
+
+ size_t total_size = 0;
+ uint64_t tsum = 0;
+ printf ("%22s ", "memset_call");
+ rand32 (0x12345678);
+
+ for (int size = MIN_SIZE; size <= MAX_SIZE; size *= 2)
+ {
+ size_t memset_size = init_memset (size) * ITERS;
+
+ for (int c = 0; c < NUM_TESTS; c++)
+ memset (a + test_arr[c].offset, 0, test_arr[c].len);
+
+ uint64_t t = clock_get_ns ();
+ for (int i = 0; i < ITERS; i++)
+ for (int c = 0; c < NUM_TESTS; c++)
+ memset (a + test_arr[c].offset, 0, test_arr[c].len);
+ t = clock_get_ns () - t;
+ total_size += memset_size;
+ tsum += t;
+ printf ("%dK: %.2f ", size / 1024, (double)memset_size / t);
+ }
+ printf( "avg %.2f\n", (double)total_size / tsum);
+
+
+ printf ("\nMedium memset (bytes/ns):\n");
+ for (int f = 0; funtab[f].name != 0; f++)
+ {
+ printf ("%22s ", funtab[f].name);
+
+ for (int size = 8; size <= 512; size *= 2)
+ {
+ uint64_t t = clock_get_ns ();
+ for (int i = 0; i < ITERS2; i++)
+ funtab[f].fun (a, 0, size);
+ t = clock_get_ns () - t;
+ printf ("%dB: %.2f ", size, (double)size * ITERS2 / t);
+ }
+ printf ("\n");
+ }
+
+ printf ("%22s ", "memset_call");
+ for (int size = 8; size <= 512; size *= 2)
+ {
+ uint64_t t = clock_get_ns ();
+ for (int i = 0; i < ITERS2; i++)
+ memset (a, 0, size);
+ t = clock_get_ns () - t;
+ printf ("%dB: %.2f ", size, (double)size * ITERS2 / t);
+ }
+
+
+ printf ("\nLarge memset (bytes/ns):\n");
+ for (int f = 0; funtab[f].name != 0; f++)
+ {
+ printf ("%22s ", funtab[f].name);
+
+ for (int size = 1024; size <= 65536; size *= 2)
+ {
+ uint64_t t = clock_get_ns ();
+ for (int i = 0; i < ITERS3; i++)
+ funtab[f].fun (a, 0, size);
+ t = clock_get_ns () - t;
+ printf ("%dK: %.2f ", size / 1024, (double)size * ITERS3 / t);
+ }
+ printf ("\n");
+ }
+
+ printf ("%22s ", "memset_call");
+ for (int size = 1024; size <= 65536; size *= 2)
+ {
+ uint64_t t = clock_get_ns ();
+ for (int i = 0; i < ITERS3; i++)
+ memset (a, 0, size);
+ t = clock_get_ns () - t;
+ printf ("%dK: %.2f ", size / 1024, (double)size * ITERS3 / t);
+ }
+ printf ("\n\n");
+
+ return 0;
+}
diff --git a/contrib/arm-optimized-routines/string/bench/strlen.c b/contrib/arm-optimized-routines/string/bench/strlen.c
index cc0f04bee547..b7eee6e905ab 100644
--- a/contrib/arm-optimized-routines/string/bench/strlen.c
+++ b/contrib/arm-optimized-routines/string/bench/strlen.c
@@ -1,7 +1,7 @@
/*
* strlen benchmark.
*
- * Copyright (c) 2020, Arm Limited.
+ * Copyright (c) 2020-2021, Arm Limited.
* SPDX-License-Identifier: MIT
*/
@@ -13,10 +13,10 @@
#include "stringlib.h"
#include "benchlib.h"
-#define ITERS 2000
+#define ITERS 5000
#define ITERS2 20000000
#define ITERS3 2000000
-#define NUM_STRLEN 16384
+#define NUM_TESTS 16384
#define MAX_ALIGN 32
#define MAX_STRLEN 256
@@ -49,7 +49,7 @@ static const struct fun
};
#undef F
-static uint16_t strlen_tests[NUM_STRLEN];
+static uint16_t strlen_tests[NUM_TESTS];
typedef struct { uint16_t size; uint16_t freq; } freq_data_t;
typedef struct { uint8_t align; uint16_t freq; } align_data_t;
@@ -117,7 +117,7 @@ init_strlen_tests (void)
/* Create a random set of strlen input strings using the string length
and alignment distributions. */
- for (int n = 0; n < NUM_STRLEN; n++)
+ for (int n = 0; n < NUM_TESTS; n++)
{
int align = strlen_align_arr[rand32 (0) & ALIGN_MASK];
int exp_len = strlen_len_arr[rand32 (0) & SIZE_MASK];
@@ -141,14 +141,14 @@ int main (void)
size_t res = 0, strlen_size = 0, mask = maskv;
printf ("%22s ", funtab[f].name);
- for (int c = 0; c < NUM_STRLEN; c++)
+ for (int c = 0; c < NUM_TESTS; c++)
strlen_size += funtab[f].fun (a + strlen_tests[c]);
strlen_size *= ITERS;
/* Measure latency of strlen result with (res & mask). */
uint64_t t = clock_get_ns ();
for (int i = 0; i < ITERS; i++)
- for (int c = 0; c < NUM_STRLEN; c++)
+ for (int c = 0; c < NUM_TESTS; c++)
res = funtab[f].fun (a + strlen_tests[c] + (res & mask));
t = clock_get_ns () - t;
printf ("%.2f\n", (double)strlen_size / t);
diff --git a/contrib/arm-optimized-routines/string/include/stringlib.h b/contrib/arm-optimized-routines/string/include/stringlib.h
index 378c3cd2d645..85e630279ceb 100644
--- a/contrib/arm-optimized-routines/string/include/stringlib.h
+++ b/contrib/arm-optimized-routines/string/include/stringlib.h
@@ -29,19 +29,17 @@ size_t __strlen_aarch64 (const char *);
size_t __strnlen_aarch64 (const char *, size_t);
int __strncmp_aarch64 (const char *, const char *, size_t);
void * __memchr_aarch64_mte (const void *, int, size_t);
-char *__strcpy_aarch64_mte (char *__restrict, const char *__restrict);
-char *__stpcpy_aarch64_mte (char *__restrict, const char *__restrict);
char *__strchr_aarch64_mte (const char *, int);
char * __strchrnul_aarch64_mte (const char *, int );
size_t __strlen_aarch64_mte (const char *);
char *__strrchr_aarch64_mte (const char *, int);
-int __strcmp_aarch64_mte (const char *, const char *);
-int __strncmp_aarch64_mte (const char *, const char *, size_t);
#if __ARM_NEON
void *__memcpy_aarch64_simd (void *__restrict, const void *__restrict, size_t);
void *__memmove_aarch64_simd (void *, const void *, size_t);
#endif
# if __ARM_FEATURE_SVE
+void *__memcpy_aarch64_sve (void *__restrict, const void *__restrict, size_t);
+void *__memmove_aarch64_sve (void *__restrict, const void *__restrict, size_t);
void *__memchr_aarch64_sve (const void *, int, size_t);
int __memcmp_aarch64_sve (const void *, const void *, size_t);
char *__strchr_aarch64_sve (const char *, int);
diff --git a/contrib/arm-optimized-routines/string/test/memcpy.c b/contrib/arm-optimized-routines/string/test/memcpy.c
index ce0ceeef5ee8..21b35b990b9b 100644
--- a/contrib/arm-optimized-routines/string/test/memcpy.c
+++ b/contrib/arm-optimized-routines/string/test/memcpy.c
@@ -28,6 +28,9 @@ static const struct fun
# if __ARM_NEON
F(__memcpy_aarch64_simd, 1)
# endif
+# if __ARM_FEATURE_SVE
+ F(__memcpy_aarch64_sve, 1)
+# endif
#elif __arm__
F(__memcpy_arm, 0)
#endif
diff --git a/contrib/arm-optimized-routines/string/test/memmove.c b/contrib/arm-optimized-routines/string/test/memmove.c
index 689b68c98af2..12a70574c7c5 100644
--- a/contrib/arm-optimized-routines/string/test/memmove.c
+++ b/contrib/arm-optimized-routines/string/test/memmove.c
@@ -28,6 +28,9 @@ static const struct fun
# if __ARM_NEON
F(__memmove_aarch64_simd, 1)
# endif
+# if __ARM_FEATURE_SVE
+ F(__memmove_aarch64_sve, 1)
+# endif
#endif
{0, 0, 0}
// clang-format on
diff --git a/contrib/arm-optimized-routines/string/test/stpcpy.c b/contrib/arm-optimized-routines/string/test/stpcpy.c
index 1827e68c9a30..1b61245bf8df 100644
--- a/contrib/arm-optimized-routines/string/test/stpcpy.c
+++ b/contrib/arm-optimized-routines/string/test/stpcpy.c
@@ -28,8 +28,7 @@ static const struct fun
// clang-format off
F(stpcpy, 0)
#if __aarch64__
- F(__stpcpy_aarch64, 0)
- F(__stpcpy_aarch64_mte, 1)
+ F(__stpcpy_aarch64, 1)
# if __ARM_FEATURE_SVE
F(__stpcpy_aarch64_sve, 1)
# endif
diff --git a/contrib/arm-optimized-routines/string/test/strcmp.c b/contrib/arm-optimized-routines/string/test/strcmp.c
index d57b54ed50a8..0262397dec88 100644
--- a/contrib/arm-optimized-routines/string/test/strcmp.c
+++ b/contrib/arm-optimized-routines/string/test/strcmp.c
@@ -24,8 +24,7 @@ static const struct fun
// clang-format off
F(strcmp, 0)
#if __aarch64__
- F(__strcmp_aarch64, 0)
- F(__strcmp_aarch64_mte, 1)
+ F(__strcmp_aarch64, 1)
# if __ARM_FEATURE_SVE
F(__strcmp_aarch64_sve, 1)
# endif
diff --git a/contrib/arm-optimized-routines/string/test/strcpy.c b/contrib/arm-optimized-routines/string/test/strcpy.c
index e84cace9c8c6..6de3bed590ef 100644
--- a/contrib/arm-optimized-routines/string/test/strcpy.c
+++ b/contrib/arm-optimized-routines/string/test/strcpy.c
@@ -24,8 +24,7 @@ static const struct fun
// clang-format off
F(strcpy, 0)
#if __aarch64__
- F(__strcpy_aarch64, 0)
- F(__strcpy_aarch64_mte, 1)
+ F(__strcpy_aarch64, 1)
# if __ARM_FEATURE_SVE
F(__strcpy_aarch64_sve, 1)
# endif
diff --git a/contrib/arm-optimized-routines/string/test/strncmp.c b/contrib/arm-optimized-routines/string/test/strncmp.c
index 018a8a431ab8..f8c2167f8f1e 100644
--- a/contrib/arm-optimized-routines/string/test/strncmp.c
+++ b/contrib/arm-optimized-routines/string/test/strncmp.c
@@ -24,8 +24,7 @@ static const struct fun
// clang-format off
F(strncmp, 0)
#if __aarch64__
- F(__strncmp_aarch64, 0)
- F(__strncmp_aarch64_mte, 1)
+ F(__strncmp_aarch64, 1)
# if __ARM_FEATURE_SVE
F(__strncmp_aarch64_sve, 1)
# endif
diff --git a/contrib/bionic-x86_64-string/avx2-memset-kbl.S b/contrib/bionic-x86_64-string/avx2-memset-kbl.S
new file mode 100644
index 000000000000..09dd07dd1655
--- /dev/null
+++ b/contrib/bionic-x86_64-string/avx2-memset-kbl.S
@@ -0,0 +1,160 @@
+/*
+Copyright (c) 2014, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <private/bionic_asm.h>
+
+#include "cache.h"
+
+#ifndef L
+# define L(label) .L##label
+#endif
+
+#ifndef ALIGN
+# define ALIGN(n) .p2align n
+#endif
+
+ .section .text.avx2,"ax",@progbits
+
+ENTRY(__memset_chk_avx2)
+ # %rdi = dst, %rsi = byte, %rdx = n, %rcx = dst_len
+ cmp %rcx, %rdx
+ ja __memset_chk_fail
+ // Fall through to memset...
+END(__memset_chk_avx2)
+
+ENTRY(memset_avx2)
+ movq %rdi, %rax
+ and $0xff, %rsi
+ mov $0x0101010101010101, %rcx
+ imul %rsi, %rcx
+ cmpq $16, %rdx
+ jae L(16bytesormore)
+ testb $8, %dl
+ jnz L(8_15bytes)
+ testb $4, %dl
+ jnz L(4_7bytes)
+ testb $2, %dl
+ jnz L(2_3bytes)
+ testb $1, %dl
+ jz L(return)
+ movb %cl, (%rdi)
+L(return):
+ ret
+
+L(8_15bytes):
+ movq %rcx, (%rdi)
+ movq %rcx, -8(%rdi, %rdx)
+ ret
+
+L(4_7bytes):
+ movl %ecx, (%rdi)
+ movl %ecx, -4(%rdi, %rdx)
+ ret
+
+L(2_3bytes):
+ movw %cx, (%rdi)
+ movw %cx, -2(%rdi, %rdx)
+ ret
+
+ ALIGN (4)
+L(16bytesormore):
+ movd %rcx, %xmm0
+ pshufd $0, %xmm0, %xmm0
+ movdqu %xmm0, (%rdi)
+ movdqu %xmm0, -16(%rdi, %rdx)
+ cmpq $32, %rdx
+ jbe L(32bytesless)
+ movdqu %xmm0, 16(%rdi)
+ movdqu %xmm0, -32(%rdi, %rdx)
+ cmpq $64, %rdx
+ jbe L(64bytesless)
+ movdqu %xmm0, 32(%rdi)
+ movdqu %xmm0, 48(%rdi)
+ movdqu %xmm0, -64(%rdi, %rdx)
+ movdqu %xmm0, -48(%rdi, %rdx)
+ cmpq $128, %rdx
+ jbe L(128bytesless)
+ vpbroadcastb %xmm0, %ymm0
+ vmovdqu %ymm0, 64(%rdi)
+ vmovdqu %ymm0, 96(%rdi)
+ vmovdqu %ymm0, -128(%rdi, %rdx)
+ vmovdqu %ymm0, -96(%rdi, %rdx)
+ cmpq $256, %rdx
+ ja L(256bytesmore)
+L(32bytesless):
+L(64bytesless):
+L(128bytesless):
+ ret
+
+ ALIGN (4)
+L(256bytesmore):
+ leaq 128(%rdi), %rcx
+ andq $-128, %rcx
+ movq %rdx, %r8
+ addq %rdi, %rdx
+ andq $-128, %rdx
+ cmpq %rcx, %rdx
+ je L(return)
+
+#ifdef SHARED_CACHE_SIZE
+ cmp $SHARED_CACHE_SIZE, %r8
+#else
+ cmp __x86_64_shared_cache_size(%rip), %r8
+#endif
+ ja L(256bytesmore_nt)
+
+ ALIGN (4)
+L(256bytesmore_normal):
+ vmovdqa %ymm0, (%rcx)
+ vmovdqa %ymm0, 32(%rcx)
+ vmovdqa %ymm0, 64(%rcx)
+ vmovdqa %ymm0, 96(%rcx)
+ addq $128, %rcx
+ cmpq %rcx, %rdx
+ jne L(256bytesmore_normal)
+ ret
+
+ ALIGN (4)
+L(256bytesmore_nt):
+ movntdq %xmm0, (%rcx)
+ movntdq %xmm0, 16(%rcx)
+ movntdq %xmm0, 32(%rcx)
+ movntdq %xmm0, 48(%rcx)
+ movntdq %xmm0, 64(%rcx)
+ movntdq %xmm0, 80(%rcx)
+ movntdq %xmm0, 96(%rcx)
+ movntdq %xmm0, 112(%rcx)
+ leaq 128(%rcx), %rcx
+ cmpq %rcx, %rdx
+ jne L(256bytesmore_nt)
+ sfence
+ ret
+
+END(memset_avx2)
diff --git a/contrib/bionic-x86_64-string/cache.h b/contrib/bionic-x86_64-string/cache.h
new file mode 100644
index 000000000000..4131509fbbc9
--- /dev/null
+++ b/contrib/bionic-x86_64-string/cache.h
@@ -0,0 +1,36 @@
+/*
+Copyright (c) 2014, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* Values are optimized for Core Architecture */
+#define SHARED_CACHE_SIZE (4096*1024) /* Core Architecture L2 Cache */
+#define DATA_CACHE_SIZE (24*1024) /* Core Architecture L1 Data Cache */
+
+#define SHARED_CACHE_SIZE_HALF (SHARED_CACHE_SIZE / 2)
+#define DATA_CACHE_SIZE_HALF (DATA_CACHE_SIZE / 2)
diff --git a/contrib/bionic-x86_64-string/sse2-memmove-slm.S b/contrib/bionic-x86_64-string/sse2-memmove-slm.S
new file mode 100644
index 000000000000..739502888b97
--- /dev/null
+++ b/contrib/bionic-x86_64-string/sse2-memmove-slm.S
@@ -0,0 +1,518 @@
+/*
+Copyright (c) 2014, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "cache.h"
+
+#ifndef MEMMOVE
+# define MEMMOVE memmove
+#endif
+
+#ifndef L
+# define L(label) .L##label
+#endif
+
+#ifndef cfi_startproc
+# define cfi_startproc .cfi_startproc
+#endif
+
+#ifndef cfi_endproc
+# define cfi_endproc .cfi_endproc
+#endif
+
+#ifndef cfi_rel_offset
+# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
+#endif
+
+#ifndef cfi_restore
+# define cfi_restore(reg) .cfi_restore reg
+#endif
+
+#ifndef cfi_adjust_cfa_offset
+# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
+#endif
+
+#ifndef ENTRY
+# define ENTRY(name) \
+ .type name, @function; \
+ .globl name; \
+ .p2align 4; \
+name: \
+ cfi_startproc
+#endif
+
+#ifndef ALIAS_SYMBOL
+# define ALIAS_SYMBOL(alias, original) \
+ .globl alias; \
+ .equ alias, original
+#endif
+
+#ifndef END
+# define END(name) \
+ cfi_endproc; \
+ .size name, .-name
+#endif
+
+#define CFI_PUSH(REG) \
+ cfi_adjust_cfa_offset (4); \
+ cfi_rel_offset (REG, 0)
+
+#define CFI_POP(REG) \
+ cfi_adjust_cfa_offset (-4); \
+ cfi_restore (REG)
+
+#define PUSH(REG) push REG;
+#define POP(REG) pop REG;
+
+#define ENTRANCE PUSH (%rbx);
+#define RETURN_END POP (%rbx); ret
+#define RETURN RETURN_END;
+
+ .section .text.sse2,"ax",@progbits
+ENTRY (MEMMOVE)
+ ENTRANCE
+ mov %rdi, %rax
+
+/* Check whether we should copy backward or forward. */
+ cmp %rsi, %rdi
+ je L(mm_return)
+ jg L(mm_len_0_or_more_backward)
+
+/* Now do checks for lengths. We do [0..16], [0..32], [0..64], [0..128]
+ separately. */
+ cmp $16, %rdx
+ jbe L(mm_len_0_16_bytes_forward)
+
+ cmp $32, %rdx
+ ja L(mm_len_32_or_more_forward)
+
+/* Copy [0..32] and return. */
+ movdqu (%rsi), %xmm0
+ movdqu -16(%rsi, %rdx), %xmm1
+ movdqu %xmm0, (%rdi)
+ movdqu %xmm1, -16(%rdi, %rdx)
+ jmp L(mm_return)
+
+L(mm_len_32_or_more_forward):
+ cmp $64, %rdx
+ ja L(mm_len_64_or_more_forward)
+
+/* Copy [0..64] and return. */
+ movdqu (%rsi), %xmm0
+ movdqu 16(%rsi), %xmm1
+ movdqu -16(%rsi, %rdx), %xmm2
+ movdqu -32(%rsi, %rdx), %xmm3
+ movdqu %xmm0, (%rdi)
+ movdqu %xmm1, 16(%rdi)
+ movdqu %xmm2, -16(%rdi, %rdx)
+ movdqu %xmm3, -32(%rdi, %rdx)
+ jmp L(mm_return)
+
+L(mm_len_64_or_more_forward):
+ cmp $128, %rdx
+ ja L(mm_len_128_or_more_forward)
+
+/* Copy [0..128] and return. */
+ movdqu (%rsi), %xmm0
+ movdqu 16(%rsi), %xmm1
+ movdqu 32(%rsi), %xmm2
+ movdqu 48(%rsi), %xmm3
+ movdqu -64(%rsi, %rdx), %xmm4
+ movdqu -48(%rsi, %rdx), %xmm5
+ movdqu -32(%rsi, %rdx), %xmm6
+ movdqu -16(%rsi, %rdx), %xmm7
+ movdqu %xmm0, (%rdi)
+ movdqu %xmm1, 16(%rdi)
+ movdqu %xmm2, 32(%rdi)
+ movdqu %xmm3, 48(%rdi)
+ movdqu %xmm4, -64(%rdi, %rdx)
+ movdqu %xmm5, -48(%rdi, %rdx)
+ movdqu %xmm6, -32(%rdi, %rdx)
+ movdqu %xmm7, -16(%rdi, %rdx)
+ jmp L(mm_return)
+
+L(mm_len_128_or_more_forward):
+/* Aligning the address of destination. */
+/* save first unaligned 64 bytes */
+ movdqu (%rsi), %xmm0
+ movdqu 16(%rsi), %xmm1
+ movdqu 32(%rsi), %xmm2
+ movdqu 48(%rsi), %xmm3
+
+ lea 64(%rdi), %r8
+ and $-64, %r8 /* r8 now aligned to next 64 byte boundary */
+ sub %rdi, %rsi /* rsi = src - dst = diff */
+
+ movdqu (%r8, %rsi), %xmm4
+ movdqu 16(%r8, %rsi), %xmm5
+ movdqu 32(%r8, %rsi), %xmm6
+ movdqu 48(%r8, %rsi), %xmm7
+
+ movdqu %xmm0, (%rdi)
+ movdqu %xmm1, 16(%rdi)
+ movdqu %xmm2, 32(%rdi)
+ movdqu %xmm3, 48(%rdi)
+ movdqa %xmm4, (%r8)
+ movaps %xmm5, 16(%r8)
+ movaps %xmm6, 32(%r8)
+ movaps %xmm7, 48(%r8)
+ add $64, %r8
+
+ lea (%rdi, %rdx), %rbx
+ and $-64, %rbx
+ cmp %r8, %rbx
+ jbe L(mm_copy_remaining_forward)
+
+ cmp $SHARED_CACHE_SIZE_HALF, %rdx
+ jae L(mm_large_page_loop_forward)
+
+ .p2align 4
+L(mm_main_loop_forward):
+
+ prefetcht0 128(%r8, %rsi)
+
+ movdqu (%r8, %rsi), %xmm0
+ movdqu 16(%r8, %rsi), %xmm1
+ movdqu 32(%r8, %rsi), %xmm2
+ movdqu 48(%r8, %rsi), %xmm3
+ movdqa %xmm0, (%r8)
+ movaps %xmm1, 16(%r8)
+ movaps %xmm2, 32(%r8)
+ movaps %xmm3, 48(%r8)
+ lea 64(%r8), %r8
+ cmp %r8, %rbx
+ ja L(mm_main_loop_forward)
+
+L(mm_copy_remaining_forward):
+ add %rdi, %rdx
+ sub %r8, %rdx
+/* We copied all up till %rdi position in the dst.
+ In %rdx now is how many bytes are left to copy.
+ Now we need to advance %r8. */
+ lea (%r8, %rsi), %r9
+
+L(mm_remaining_0_64_bytes_forward):
+ cmp $32, %rdx
+ ja L(mm_remaining_33_64_bytes_forward)
+ cmp $16, %rdx
+ ja L(mm_remaining_17_32_bytes_forward)
+ test %rdx, %rdx
+ .p2align 4,,2
+ je L(mm_return)
+
+ cmpb $8, %dl
+ ja L(mm_remaining_9_16_bytes_forward)
+ cmpb $4, %dl
+ .p2align 4,,5
+ ja L(mm_remaining_5_8_bytes_forward)
+ cmpb $2, %dl
+ .p2align 4,,1
+ ja L(mm_remaining_3_4_bytes_forward)
+ movzbl -1(%r9,%rdx), %esi
+ movzbl (%r9), %ebx
+ movb %sil, -1(%r8,%rdx)
+ movb %bl, (%r8)
+ jmp L(mm_return)
+
+L(mm_remaining_33_64_bytes_forward):
+ movdqu (%r9), %xmm0
+ movdqu 16(%r9), %xmm1
+ movdqu -32(%r9, %rdx), %xmm2
+ movdqu -16(%r9, %rdx), %xmm3
+ movdqu %xmm0, (%r8)
+ movdqu %xmm1, 16(%r8)
+ movdqu %xmm2, -32(%r8, %rdx)
+ movdqu %xmm3, -16(%r8, %rdx)
+ jmp L(mm_return)
+
+L(mm_remaining_17_32_bytes_forward):
+ movdqu (%r9), %xmm0
+ movdqu -16(%r9, %rdx), %xmm1
+ movdqu %xmm0, (%r8)
+ movdqu %xmm1, -16(%r8, %rdx)
+ jmp L(mm_return)
+
+L(mm_remaining_5_8_bytes_forward):
+ movl (%r9), %esi
+ movl -4(%r9,%rdx), %ebx
+ movl %esi, (%r8)
+ movl %ebx, -4(%r8,%rdx)
+ jmp L(mm_return)
+
+L(mm_remaining_9_16_bytes_forward):
+ mov (%r9), %rsi
+ mov -8(%r9, %rdx), %rbx
+ mov %rsi, (%r8)
+ mov %rbx, -8(%r8, %rdx)
+ jmp L(mm_return)
+
+L(mm_remaining_3_4_bytes_forward):
+ movzwl -2(%r9,%rdx), %esi
+ movzwl (%r9), %ebx
+ movw %si, -2(%r8,%rdx)
+ movw %bx, (%r8)
+ jmp L(mm_return)
+
+L(mm_len_0_16_bytes_forward):
+ testb $24, %dl
+ jne L(mm_len_9_16_bytes_forward)
+ testb $4, %dl
+ .p2align 4,,5
+ jne L(mm_len_5_8_bytes_forward)
+ test %rdx, %rdx
+ .p2align 4,,2
+ je L(mm_return)
+ testb $2, %dl
+ .p2align 4,,1
+ jne L(mm_len_2_4_bytes_forward)
+ movzbl -1(%rsi,%rdx), %ebx
+ movzbl (%rsi), %esi
+ movb %bl, -1(%rdi,%rdx)
+ movb %sil, (%rdi)
+ jmp L(mm_return)
+
+L(mm_len_2_4_bytes_forward):
+ movzwl -2(%rsi,%rdx), %ebx
+ movzwl (%rsi), %esi
+ movw %bx, -2(%rdi,%rdx)
+ movw %si, (%rdi)
+ jmp L(mm_return)
+
+L(mm_len_5_8_bytes_forward):
+ movl (%rsi), %ebx
+ movl -4(%rsi,%rdx), %esi
+ movl %ebx, (%rdi)
+ movl %esi, -4(%rdi,%rdx)
+ jmp L(mm_return)
+
+L(mm_len_9_16_bytes_forward):
+ mov (%rsi), %rbx
+ mov -8(%rsi, %rdx), %rsi
+ mov %rbx, (%rdi)
+ mov %rsi, -8(%rdi, %rdx)
+ jmp L(mm_return)
+
+L(mm_recalc_len):
+/* Compute in %rdx how many bytes are left to copy after
+ the main loop stops. */
+ mov %rbx, %rdx
+ sub %rdi, %rdx
+/* The code for copying backwards. */
+L(mm_len_0_or_more_backward):
+
+/* Now do checks for lengths. We do [0..16], [16..32], [32..64], [64..128]
+ separately. */
+ cmp $16, %rdx
+ jbe L(mm_len_0_16_bytes_backward)
+
+ cmp $32, %rdx
+ ja L(mm_len_32_or_more_backward)
+
+/* Copy [0..32] and return. */
+ movdqu (%rsi), %xmm0
+ movdqu -16(%rsi, %rdx), %xmm1
+ movdqu %xmm0, (%rdi)
+ movdqu %xmm1, -16(%rdi, %rdx)
+ jmp L(mm_return)
+
+L(mm_len_32_or_more_backward):
+ cmp $64, %rdx
+ ja L(mm_len_64_or_more_backward)
+
+/* Copy [0..64] and return. */
+ movdqu (%rsi), %xmm0
+ movdqu 16(%rsi), %xmm1
+ movdqu -16(%rsi, %rdx), %xmm2
+ movdqu -32(%rsi, %rdx), %xmm3
+ movdqu %xmm0, (%rdi)
+ movdqu %xmm1, 16(%rdi)
+ movdqu %xmm2, -16(%rdi, %rdx)
+ movdqu %xmm3, -32(%rdi, %rdx)
+ jmp L(mm_return)
+
+L(mm_len_64_or_more_backward):
+ cmp $128, %rdx
+ ja L(mm_len_128_or_more_backward)
+
+/* Copy [0..128] and return. */
+ movdqu (%rsi), %xmm0
+ movdqu 16(%rsi), %xmm1
+ movdqu 32(%rsi), %xmm2
+ movdqu 48(%rsi), %xmm3
+ movdqu -64(%rsi, %rdx), %xmm4
+ movdqu -48(%rsi, %rdx), %xmm5
+ movdqu -32(%rsi, %rdx), %xmm6
+ movdqu -16(%rsi, %rdx), %xmm7
+ movdqu %xmm0, (%rdi)
+ movdqu %xmm1, 16(%rdi)
+ movdqu %xmm2, 32(%rdi)
+ movdqu %xmm3, 48(%rdi)
+ movdqu %xmm4, -64(%rdi, %rdx)
+ movdqu %xmm5, -48(%rdi, %rdx)
+ movdqu %xmm6, -32(%rdi, %rdx)
+ movdqu %xmm7, -16(%rdi, %rdx)
+ jmp L(mm_return)
+
+L(mm_len_128_or_more_backward):
+/* Aligning the address of destination. We need to save
+ 16 bits from the source in order not to overwrite them. */
+ movdqu -16(%rsi, %rdx), %xmm0
+ movdqu -32(%rsi, %rdx), %xmm1
+ movdqu -48(%rsi, %rdx), %xmm2
+ movdqu -64(%rsi, %rdx), %xmm3
+
+ lea (%rdi, %rdx), %r9
+ and $-64, %r9 /* r9 = aligned dst */
+
+ mov %rsi, %r8
+ sub %rdi, %r8 /* r8 = src - dst, diff */
+
+ movdqu -16(%r9, %r8), %xmm4
+ movdqu -32(%r9, %r8), %xmm5
+ movdqu -48(%r9, %r8), %xmm6
+ movdqu -64(%r9, %r8), %xmm7
+
+ movdqu %xmm0, -16(%rdi, %rdx)
+ movdqu %xmm1, -32(%rdi, %rdx)
+ movdqu %xmm2, -48(%rdi, %rdx)
+ movdqu %xmm3, -64(%rdi, %rdx)
+ movdqa %xmm4, -16(%r9)
+ movaps %xmm5, -32(%r9)
+ movaps %xmm6, -48(%r9)
+ movaps %xmm7, -64(%r9)
+ lea -64(%r9), %r9
+
+ lea 64(%rdi), %rbx
+ and $-64, %rbx
+
+ cmp %r9, %rbx
+ jae L(mm_recalc_len)
+
+ cmp $SHARED_CACHE_SIZE_HALF, %rdx
+ jae L(mm_large_page_loop_backward)
+
+ .p2align 4
+L(mm_main_loop_backward):
+
+ prefetcht0 -128(%r9, %r8)
+
+ movdqu -64(%r9, %r8), %xmm0
+ movdqu -48(%r9, %r8), %xmm1
+ movdqu -32(%r9, %r8), %xmm2
+ movdqu -16(%r9, %r8), %xmm3
+ movdqa %xmm0, -64(%r9)
+ movaps %xmm1, -48(%r9)
+ movaps %xmm2, -32(%r9)
+ movaps %xmm3, -16(%r9)
+ lea -64(%r9), %r9
+ cmp %r9, %rbx
+ jb L(mm_main_loop_backward)
+ jmp L(mm_recalc_len)
+
+/* Copy [0..16] and return. */
+L(mm_len_0_16_bytes_backward):
+ testb $24, %dl
+ jnz L(mm_len_9_16_bytes_backward)
+ testb $4, %dl
+ .p2align 4,,5
+ jnz L(mm_len_5_8_bytes_backward)
+ test %rdx, %rdx
+ .p2align 4,,2
+ je L(mm_return)
+ testb $2, %dl
+ .p2align 4,,1
+ jne L(mm_len_3_4_bytes_backward)
+ movzbl -1(%rsi,%rdx), %ebx
+ movzbl (%rsi), %ecx
+ movb %bl, -1(%rdi,%rdx)
+ movb %cl, (%rdi)
+ jmp L(mm_return)
+
+L(mm_len_3_4_bytes_backward):
+ movzwl -2(%rsi,%rdx), %ebx
+ movzwl (%rsi), %ecx
+ movw %bx, -2(%rdi,%rdx)
+ movw %cx, (%rdi)
+ jmp L(mm_return)
+
+L(mm_len_9_16_bytes_backward):
+ movl -4(%rsi,%rdx), %ebx
+ movl -8(%rsi,%rdx), %ecx
+ movl %ebx, -4(%rdi,%rdx)
+ movl %ecx, -8(%rdi,%rdx)
+ sub $8, %rdx
+ jmp L(mm_len_0_16_bytes_backward)
+
+L(mm_len_5_8_bytes_backward):
+ movl (%rsi), %ebx
+ movl -4(%rsi,%rdx), %ecx
+ movl %ebx, (%rdi)
+ movl %ecx, -4(%rdi,%rdx)
+
+L(mm_return):
+ RETURN
+
+/* Big length copy forward part. */
+
+ .p2align 4
+L(mm_large_page_loop_forward):
+ movdqu (%r8, %rsi), %xmm0
+ movdqu 16(%r8, %rsi), %xmm1
+ movdqu 32(%r8, %rsi), %xmm2
+ movdqu 48(%r8, %rsi), %xmm3
+ movntdq %xmm0, (%r8)
+ movntdq %xmm1, 16(%r8)
+ movntdq %xmm2, 32(%r8)
+ movntdq %xmm3, 48(%r8)
+ lea 64(%r8), %r8
+ cmp %r8, %rbx
+ ja L(mm_large_page_loop_forward)
+ sfence
+ jmp L(mm_copy_remaining_forward)
+
+/* Big length copy backward part. */
+ .p2align 4
+L(mm_large_page_loop_backward):
+ movdqu -64(%r9, %r8), %xmm0
+ movdqu -48(%r9, %r8), %xmm1
+ movdqu -32(%r9, %r8), %xmm2
+ movdqu -16(%r9, %r8), %xmm3
+ movntdq %xmm0, -64(%r9)
+ movntdq %xmm1, -48(%r9)
+ movntdq %xmm2, -32(%r9)
+ movntdq %xmm3, -16(%r9)
+ lea -64(%r9), %r9
+ cmp %r9, %rbx
+ jb L(mm_large_page_loop_backward)
+ sfence
+ jmp L(mm_recalc_len)
+
+END (MEMMOVE)
+
+ALIAS_SYMBOL(memcpy, MEMMOVE)
diff --git a/contrib/bionic-x86_64-string/sse2-memset-slm.S b/contrib/bionic-x86_64-string/sse2-memset-slm.S
new file mode 100644
index 000000000000..cceadd2977d1
--- /dev/null
+++ b/contrib/bionic-x86_64-string/sse2-memset-slm.S
@@ -0,0 +1,149 @@
+/*
+Copyright (c) 2014, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <private/bionic_asm.h>
+
+#include "cache.h"
+
+#ifndef L
+# define L(label) .L##label
+#endif
+
+#ifndef ALIGN
+# define ALIGN(n) .p2align n
+#endif
+
+
+ENTRY(__memset_chk_generic)
+ # %rdi = dst, %rsi = byte, %rdx = n, %rcx = dst_len
+ cmp %rcx, %rdx
+ ja __memset_chk_fail
+ // Fall through to memset...
+END(__memset_chk_generic)
+
+
+ .section .text.sse2,"ax",@progbits
+ENTRY(memset_generic)
+ movq %rdi, %rax
+ and $0xff, %rsi
+ mov $0x0101010101010101, %rcx
+ imul %rsi, %rcx
+ cmpq $16, %rdx
+ jae L(16bytesormore)
+ testb $8, %dl
+ jnz L(8_15bytes)
+ testb $4, %dl
+ jnz L(4_7bytes)
+ testb $2, %dl
+ jnz L(2_3bytes)
+ testb $1, %dl
+ jz L(return)
+ movb %cl, (%rdi)
+L(return):
+ ret
+
+L(8_15bytes):
+ movq %rcx, (%rdi)
+ movq %rcx, -8(%rdi, %rdx)
+ ret
+
+L(4_7bytes):
+ movl %ecx, (%rdi)
+ movl %ecx, -4(%rdi, %rdx)
+ ret
+
+L(2_3bytes):
+ movw %cx, (%rdi)
+ movw %cx, -2(%rdi, %rdx)
+ ret
+
+ ALIGN (4)
+L(16bytesormore):
+ movd %rcx, %xmm0
+ pshufd $0, %xmm0, %xmm0
+ movdqu %xmm0, (%rdi)
+ movdqu %xmm0, -16(%rdi, %rdx)
+ cmpq $32, %rdx
+ jbe L(32bytesless)
+ movdqu %xmm0, 16(%rdi)
+ movdqu %xmm0, -32(%rdi, %rdx)
+ cmpq $64, %rdx
+ jbe L(64bytesless)
+ movdqu %xmm0, 32(%rdi)
+ movdqu %xmm0, 48(%rdi)
+ movdqu %xmm0, -64(%rdi, %rdx)
+ movdqu %xmm0, -48(%rdi, %rdx)
+ cmpq $128, %rdx
+ ja L(128bytesmore)
+L(32bytesless):
+L(64bytesless):
+ ret
+
+ ALIGN (4)
+L(128bytesmore):
+ leaq 64(%rdi), %rcx
+ andq $-64, %rcx
+ movq %rdx, %r8
+ addq %rdi, %rdx
+ andq $-64, %rdx
+ cmpq %rcx, %rdx
+ je L(return)
+
+#ifdef SHARED_CACHE_SIZE
+ cmp $SHARED_CACHE_SIZE, %r8
+#else
+ cmp __x86_64_shared_cache_size(%rip), %r8
+#endif
+ ja L(128bytesmore_nt)
+
+ ALIGN (4)
+L(128bytesmore_normal):
+ movdqa %xmm0, (%rcx)
+ movaps %xmm0, 0x10(%rcx)
+ movaps %xmm0, 0x20(%rcx)
+ movaps %xmm0, 0x30(%rcx)
+ addq $64, %rcx
+ cmpq %rcx, %rdx
+ jne L(128bytesmore_normal)
+ ret
+
+ ALIGN (4)
+L(128bytesmore_nt):
+ movntdq %xmm0, (%rcx)
+ movntdq %xmm0, 0x10(%rcx)
+ movntdq %xmm0, 0x20(%rcx)
+ movntdq %xmm0, 0x30(%rcx)
+ leaq 64(%rcx), %rcx
+ cmpq %rcx, %rdx
+ jne L(128bytesmore_nt)
+ sfence
+ ret
+
+END(memset_generic)
diff --git a/contrib/bionic-x86_64-string/sse2-stpcpy-slm.S b/contrib/bionic-x86_64-string/sse2-stpcpy-slm.S
new file mode 100644
index 000000000000..0ad2d44cf8ba
--- /dev/null
+++ b/contrib/bionic-x86_64-string/sse2-stpcpy-slm.S
@@ -0,0 +1,33 @@
+/*
+Copyright (c) 2014, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#define USE_AS_STPCPY
+#define STRCPY stpcpy
+#include "sse2-strcpy-slm.S"
diff --git a/contrib/bionic-x86_64-string/sse2-stpncpy-slm.S b/contrib/bionic-x86_64-string/sse2-stpncpy-slm.S
new file mode 100644
index 000000000000..30666850bea2
--- /dev/null
+++ b/contrib/bionic-x86_64-string/sse2-stpncpy-slm.S
@@ -0,0 +1,34 @@
+/*
+Copyright (c) 2014, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#define USE_AS_STRNCPY
+#define USE_AS_STPCPY
+#define STRCPY stpncpy
+#include "sse2-strcpy-slm.S"
diff --git a/contrib/bionic-x86_64-string/sse2-strcat-slm.S b/contrib/bionic-x86_64-string/sse2-strcat-slm.S
new file mode 100644
index 000000000000..dd8207ff54c4
--- /dev/null
+++ b/contrib/bionic-x86_64-string/sse2-strcat-slm.S
@@ -0,0 +1,87 @@
+/*
+Copyright (c) 2014, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef STRCAT
+# define STRCAT strcat
+#endif
+
+#ifndef L
+# define L(label) .L##label
+#endif
+
+#ifndef cfi_startproc
+# define cfi_startproc .cfi_startproc
+#endif
+
+#ifndef cfi_endproc
+# define cfi_endproc .cfi_endproc
+#endif
+
+#ifndef ENTRY
+# define ENTRY(name) \
+ .type name, @function; \
+ .globl name; \
+ .p2align 4; \
+name: \
+ cfi_startproc
+#endif
+
+#ifndef END
+# define END(name) \
+ cfi_endproc; \
+ .size name, .-name
+#endif
+
+#define USE_AS_STRCAT
+
+.text
+ENTRY (STRCAT)
+ mov %rdi, %r9
+#ifdef USE_AS_STRNCAT
+ mov %rdx, %r8
+#endif
+
+#define RETURN jmp L(Strcpy)
+#include "sse2-strlen-slm.S"
+
+#undef RETURN
+#define RETURN ret
+
+L(Strcpy):
+ lea (%r9, %rax), %rdi
+ mov %rsi, %rcx
+ mov %r9, %rax /* save result */
+
+#ifdef USE_AS_STRNCAT
+ test %r8, %r8
+ jz L(ExitZero)
+# define USE_AS_STRNCPY
+#endif
+#include "sse2-strcpy-slm.S"
diff --git a/contrib/bionic-x86_64-string/sse2-strcpy-slm.S b/contrib/bionic-x86_64-string/sse2-strcpy-slm.S
new file mode 100644
index 000000000000..3e146bfbcfa5
--- /dev/null
+++ b/contrib/bionic-x86_64-string/sse2-strcpy-slm.S
@@ -0,0 +1,1921 @@
+/*
+Copyright (c) 2014, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef USE_AS_STRCAT
+
+# ifndef STRCPY
+# define STRCPY strcpy
+# endif
+
+# ifndef L
+# define L(label) .L##label
+# endif
+
+# ifndef cfi_startproc
+# define cfi_startproc .cfi_startproc
+# endif
+
+# ifndef cfi_endproc
+# define cfi_endproc .cfi_endproc
+# endif
+
+# ifndef ENTRY
+# define ENTRY(name) \
+ .type name, @function; \
+ .globl name; \
+ .p2align 4; \
+name: \
+ cfi_startproc
+# endif
+
+# ifndef END
+# define END(name) \
+ cfi_endproc; \
+ .size name, .-name
+# endif
+
+#endif
+
+#define JMPTBL(I, B) I - B
+#define BRANCH_TO_JMPTBL_ENTRY(TABLE, INDEX, SCALE) \
+ lea TABLE(%rip), %r11; \
+ movslq (%r11, INDEX, SCALE), %rcx; \
+ lea (%r11, %rcx), %rcx; \
+ jmp *%rcx
+
+#ifndef USE_AS_STRCAT
+
+# define RETURN ret
+
+.text
+ENTRY (STRCPY)
+# ifdef USE_AS_STRNCPY
+ mov %rdx, %r8
+ test %r8, %r8
+ jz L(ExitZero)
+# endif
+ mov %rsi, %rcx
+# ifndef USE_AS_STPCPY
+ mov %rdi, %rax /* save result */
+# endif
+
+#endif
+ and $63, %rcx
+ cmp $32, %rcx
+ jbe L(SourceStringAlignmentLess32)
+
+ and $-16, %rsi
+ and $15, %rcx
+ pxor %xmm0, %xmm0
+ pxor %xmm1, %xmm1
+
+ pcmpeqb (%rsi), %xmm1
+ pmovmskb %xmm1, %rdx
+ shr %cl, %rdx
+#ifdef USE_AS_STRNCPY
+# if defined USE_AS_STPCPY || defined USE_AS_STRCAT
+ mov $16, %r10
+ sub %rcx, %r10
+ cmp %r10, %r8
+# else
+ mov $17, %r10
+ sub %rcx, %r10
+ cmp %r10, %r8
+# endif
+ jbe L(CopyFrom1To16BytesTailCase2OrCase3)
+#endif
+ test %rdx, %rdx
+ jnz L(CopyFrom1To16BytesTail)
+
+ pcmpeqb 16(%rsi), %xmm0
+ pmovmskb %xmm0, %rdx
+#ifdef USE_AS_STRNCPY
+ add $16, %r10
+ cmp %r10, %r8
+ jbe L(CopyFrom1To32BytesCase2OrCase3)
+#endif
+ test %rdx, %rdx
+ jnz L(CopyFrom1To32Bytes)
+
+ movdqu (%rsi, %rcx), %xmm1 /* copy 16 bytes */
+ movdqu %xmm1, (%rdi)
+
+/* If source adress alignment != destination adress alignment */
+ .p2align 4
+L(Unalign16Both):
+ sub %rcx, %rdi
+#ifdef USE_AS_STRNCPY
+ add %rcx, %r8
+#endif
+ mov $16, %rcx
+ movdqa (%rsi, %rcx), %xmm1
+ movaps 16(%rsi, %rcx), %xmm2
+ movdqu %xmm1, (%rdi, %rcx)
+ pcmpeqb %xmm2, %xmm0
+ pmovmskb %xmm0, %rdx
+ add $16, %rcx
+#ifdef USE_AS_STRNCPY
+ sub $48, %r8
+ jbe L(CopyFrom1To16BytesCase2OrCase3)
+#endif
+ test %rdx, %rdx
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ jnz L(CopyFrom1To16BytesUnalignedXmm2)
+#else
+ jnz L(CopyFrom1To16Bytes)
+#endif
+
+ movaps 16(%rsi, %rcx), %xmm3
+ movdqu %xmm2, (%rdi, %rcx)
+ pcmpeqb %xmm3, %xmm0
+ pmovmskb %xmm0, %rdx
+ add $16, %rcx
+#ifdef USE_AS_STRNCPY
+ sub $16, %r8
+ jbe L(CopyFrom1To16BytesCase2OrCase3)
+#endif
+ test %rdx, %rdx
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ jnz L(CopyFrom1To16BytesUnalignedXmm3)
+#else
+ jnz L(CopyFrom1To16Bytes)
+#endif
+
+ movaps 16(%rsi, %rcx), %xmm4
+ movdqu %xmm3, (%rdi, %rcx)
+ pcmpeqb %xmm4, %xmm0
+ pmovmskb %xmm0, %rdx
+ add $16, %rcx
+#ifdef USE_AS_STRNCPY
+ sub $16, %r8
+ jbe L(CopyFrom1To16BytesCase2OrCase3)
+#endif
+ test %rdx, %rdx
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ jnz L(CopyFrom1To16BytesUnalignedXmm4)
+#else
+ jnz L(CopyFrom1To16Bytes)
+#endif
+
+ movaps 16(%rsi, %rcx), %xmm1
+ movdqu %xmm4, (%rdi, %rcx)
+ pcmpeqb %xmm1, %xmm0
+ pmovmskb %xmm0, %rdx
+ add $16, %rcx
+#ifdef USE_AS_STRNCPY
+ sub $16, %r8
+ jbe L(CopyFrom1To16BytesCase2OrCase3)
+#endif
+ test %rdx, %rdx
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ jnz L(CopyFrom1To16BytesUnalignedXmm1)
+#else
+ jnz L(CopyFrom1To16Bytes)
+#endif
+
+ movaps 16(%rsi, %rcx), %xmm2
+ movdqu %xmm1, (%rdi, %rcx)
+ pcmpeqb %xmm2, %xmm0
+ pmovmskb %xmm0, %rdx
+ add $16, %rcx
+#ifdef USE_AS_STRNCPY
+ sub $16, %r8
+ jbe L(CopyFrom1To16BytesCase2OrCase3)
+#endif
+ test %rdx, %rdx
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ jnz L(CopyFrom1To16BytesUnalignedXmm2)
+#else
+ jnz L(CopyFrom1To16Bytes)
+#endif
+
+ movaps 16(%rsi, %rcx), %xmm3
+ movdqu %xmm2, (%rdi, %rcx)
+ pcmpeqb %xmm3, %xmm0
+ pmovmskb %xmm0, %rdx
+ add $16, %rcx
+#ifdef USE_AS_STRNCPY
+ sub $16, %r8
+ jbe L(CopyFrom1To16BytesCase2OrCase3)
+#endif
+ test %rdx, %rdx
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ jnz L(CopyFrom1To16BytesUnalignedXmm3)
+#else
+ jnz L(CopyFrom1To16Bytes)
+#endif
+
+ movdqu %xmm3, (%rdi, %rcx)
+ mov %rsi, %rdx
+ lea 16(%rsi, %rcx), %rsi
+ and $-0x40, %rsi
+ sub %rsi, %rdx
+ sub %rdx, %rdi
+#ifdef USE_AS_STRNCPY
+ lea 128(%r8, %rdx), %r8
+#endif
+L(Unaligned64Loop):
+ movaps (%rsi), %xmm2
+ movaps %xmm2, %xmm4
+ movaps 16(%rsi), %xmm5
+ movaps 32(%rsi), %xmm3
+ movaps %xmm3, %xmm6
+ movaps 48(%rsi), %xmm7
+ pminub %xmm5, %xmm2
+ pminub %xmm7, %xmm3
+ pminub %xmm2, %xmm3
+ pcmpeqb %xmm0, %xmm3
+ pmovmskb %xmm3, %rdx
+#ifdef USE_AS_STRNCPY
+ sub $64, %r8
+ jbe L(UnalignedLeaveCase2OrCase3)
+#endif
+ test %rdx, %rdx
+ jnz L(Unaligned64Leave)
+
+L(Unaligned64Loop_start):
+ add $64, %rdi
+ add $64, %rsi
+ movdqu %xmm4, -64(%rdi)
+ movaps (%rsi), %xmm2
+ movdqa %xmm2, %xmm4
+ movdqu %xmm5, -48(%rdi)
+ movaps 16(%rsi), %xmm5
+ pminub %xmm5, %xmm2
+ movaps 32(%rsi), %xmm3
+ movdqu %xmm6, -32(%rdi)
+ movaps %xmm3, %xmm6
+ movdqu %xmm7, -16(%rdi)
+ movaps 48(%rsi), %xmm7
+ pminub %xmm7, %xmm3
+ pminub %xmm2, %xmm3
+ pcmpeqb %xmm0, %xmm3
+ pmovmskb %xmm3, %rdx
+#ifdef USE_AS_STRNCPY
+ sub $64, %r8
+ jbe L(UnalignedLeaveCase2OrCase3)
+#endif
+ test %rdx, %rdx
+ jz L(Unaligned64Loop_start)
+
+L(Unaligned64Leave):
+ pxor %xmm1, %xmm1
+
+ pcmpeqb %xmm4, %xmm0
+ pcmpeqb %xmm5, %xmm1
+ pmovmskb %xmm0, %rdx
+ pmovmskb %xmm1, %rcx
+ test %rdx, %rdx
+ jnz L(CopyFrom1To16BytesUnaligned_0)
+ test %rcx, %rcx
+ jnz L(CopyFrom1To16BytesUnaligned_16)
+
+ pcmpeqb %xmm6, %xmm0
+ pcmpeqb %xmm7, %xmm1
+ pmovmskb %xmm0, %rdx
+ pmovmskb %xmm1, %rcx
+ test %rdx, %rdx
+ jnz L(CopyFrom1To16BytesUnaligned_32)
+
+ bsf %rcx, %rdx
+ movdqu %xmm4, (%rdi)
+ movdqu %xmm5, 16(%rdi)
+ movdqu %xmm6, 32(%rdi)
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+# ifdef USE_AS_STPCPY
+ lea 48(%rdi, %rdx), %rax
+# endif
+ movdqu %xmm7, 48(%rdi)
+ add $15, %r8
+ sub %rdx, %r8
+ lea 49(%rdi, %rdx), %rdi
+ jmp L(StrncpyFillTailWithZero)
+#else
+ add $48, %rsi
+ add $48, %rdi
+ BRANCH_TO_JMPTBL_ENTRY (L(ExitTable), %rdx, 4)
+#endif
+
+/* If source adress alignment == destination adress alignment */
+
+L(SourceStringAlignmentLess32):
+ pxor %xmm0, %xmm0
+ movdqu (%rsi), %xmm1
+ movdqu 16(%rsi), %xmm2
+ pcmpeqb %xmm1, %xmm0
+ pmovmskb %xmm0, %rdx
+
+#ifdef USE_AS_STRNCPY
+# if defined USE_AS_STPCPY || defined USE_AS_STRCAT
+ cmp $16, %r8
+# else
+ cmp $17, %r8
+# endif
+ jbe L(CopyFrom1To16BytesTail1Case2OrCase3)
+#endif
+ test %rdx, %rdx
+ jnz L(CopyFrom1To16BytesTail1)
+
+ pcmpeqb %xmm2, %xmm0
+ movdqu %xmm1, (%rdi)
+ pmovmskb %xmm0, %rdx
+
+#ifdef USE_AS_STRNCPY
+# if defined USE_AS_STPCPY || defined USE_AS_STRCAT
+ cmp $32, %r8
+# else
+ cmp $33, %r8
+# endif
+ jbe L(CopyFrom1To32Bytes1Case2OrCase3)
+#endif
+ test %rdx, %rdx
+ jnz L(CopyFrom1To32Bytes1)
+
+ and $15, %rcx
+ and $-16, %rsi
+
+ jmp L(Unalign16Both)
+
+/*------End of main part with loops---------------------*/
+
+/* Case1 */
+
+#if (!defined USE_AS_STRNCPY) || (defined USE_AS_STRCAT)
+ .p2align 4
+L(CopyFrom1To16Bytes):
+ add %rcx, %rdi
+ add %rcx, %rsi
+ bsf %rdx, %rdx
+ BRANCH_TO_JMPTBL_ENTRY (L(ExitTable), %rdx, 4)
+#endif
+ .p2align 4
+L(CopyFrom1To16BytesTail):
+ add %rcx, %rsi
+ bsf %rdx, %rdx
+ BRANCH_TO_JMPTBL_ENTRY (L(ExitTable), %rdx, 4)
+
+ .p2align 4
+L(CopyFrom1To32Bytes1):
+ add $16, %rsi
+ add $16, %rdi
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $16, %r8
+#endif
+L(CopyFrom1To16BytesTail1):
+ bsf %rdx, %rdx
+ BRANCH_TO_JMPTBL_ENTRY (L(ExitTable), %rdx, 4)
+
+ .p2align 4
+L(CopyFrom1To32Bytes):
+ bsf %rdx, %rdx
+ add %rcx, %rsi
+ add $16, %rdx
+ sub %rcx, %rdx
+ BRANCH_TO_JMPTBL_ENTRY (L(ExitTable), %rdx, 4)
+
+ .p2align 4
+L(CopyFrom1To16BytesUnaligned_0):
+ bsf %rdx, %rdx
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+# ifdef USE_AS_STPCPY
+ lea (%rdi, %rdx), %rax
+# endif
+ movdqu %xmm4, (%rdi)
+ add $63, %r8
+ sub %rdx, %r8
+ lea 1(%rdi, %rdx), %rdi
+ jmp L(StrncpyFillTailWithZero)
+#else
+ BRANCH_TO_JMPTBL_ENTRY (L(ExitTable), %rdx, 4)
+#endif
+
+ .p2align 4
+L(CopyFrom1To16BytesUnaligned_16):
+ bsf %rcx, %rdx
+ movdqu %xmm4, (%rdi)
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+# ifdef USE_AS_STPCPY
+ lea 16(%rdi, %rdx), %rax
+# endif
+ movdqu %xmm5, 16(%rdi)
+ add $47, %r8
+ sub %rdx, %r8
+ lea 17(%rdi, %rdx), %rdi
+ jmp L(StrncpyFillTailWithZero)
+#else
+ add $16, %rsi
+ add $16, %rdi
+ BRANCH_TO_JMPTBL_ENTRY (L(ExitTable), %rdx, 4)
+#endif
+
+ .p2align 4
+L(CopyFrom1To16BytesUnaligned_32):
+ bsf %rdx, %rdx
+ movdqu %xmm4, (%rdi)
+ movdqu %xmm5, 16(%rdi)
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+# ifdef USE_AS_STPCPY
+ lea 32(%rdi, %rdx), %rax
+# endif
+ movdqu %xmm6, 32(%rdi)
+ add $31, %r8
+ sub %rdx, %r8
+ lea 33(%rdi, %rdx), %rdi
+ jmp L(StrncpyFillTailWithZero)
+#else
+ add $32, %rsi
+ add $32, %rdi
+ BRANCH_TO_JMPTBL_ENTRY (L(ExitTable), %rdx, 4)
+#endif
+
+#ifdef USE_AS_STRNCPY
+# ifndef USE_AS_STRCAT
+ .p2align 4
+L(CopyFrom1To16BytesUnalignedXmm6):
+ movdqu %xmm6, (%rdi, %rcx)
+ jmp L(CopyFrom1To16BytesXmmExit)
+
+ .p2align 4
+L(CopyFrom1To16BytesUnalignedXmm5):
+ movdqu %xmm5, (%rdi, %rcx)
+ jmp L(CopyFrom1To16BytesXmmExit)
+
+ .p2align 4
+L(CopyFrom1To16BytesUnalignedXmm4):
+ movdqu %xmm4, (%rdi, %rcx)
+ jmp L(CopyFrom1To16BytesXmmExit)
+
+ .p2align 4
+L(CopyFrom1To16BytesUnalignedXmm3):
+ movdqu %xmm3, (%rdi, %rcx)
+ jmp L(CopyFrom1To16BytesXmmExit)
+
+ .p2align 4
+L(CopyFrom1To16BytesUnalignedXmm1):
+ movdqu %xmm1, (%rdi, %rcx)
+ jmp L(CopyFrom1To16BytesXmmExit)
+# endif
+
+ .p2align 4
+L(CopyFrom1To16BytesExit):
+ BRANCH_TO_JMPTBL_ENTRY (L(ExitTable), %rdx, 4)
+
+/* Case2 */
+
+ .p2align 4
+L(CopyFrom1To16BytesCase2):
+ add $16, %r8
+ add %rcx, %rdi
+ add %rcx, %rsi
+ bsf %rdx, %rdx
+ cmp %r8, %rdx
+ jb L(CopyFrom1To16BytesExit)
+ BRANCH_TO_JMPTBL_ENTRY (L(ExitStrncpyTable), %r8, 4)
+
+ .p2align 4
+L(CopyFrom1To32BytesCase2):
+ add %rcx, %rsi
+ bsf %rdx, %rdx
+ add $16, %rdx
+ sub %rcx, %rdx
+ cmp %r8, %rdx
+ jb L(CopyFrom1To16BytesExit)
+ BRANCH_TO_JMPTBL_ENTRY (L(ExitStrncpyTable), %r8, 4)
+
+L(CopyFrom1To16BytesTailCase2):
+ add %rcx, %rsi
+ bsf %rdx, %rdx
+ cmp %r8, %rdx
+ jb L(CopyFrom1To16BytesExit)
+ BRANCH_TO_JMPTBL_ENTRY (L(ExitStrncpyTable), %r8, 4)
+
+L(CopyFrom1To16BytesTail1Case2):
+ bsf %rdx, %rdx
+ cmp %r8, %rdx
+ jb L(CopyFrom1To16BytesExit)
+ BRANCH_TO_JMPTBL_ENTRY (L(ExitStrncpyTable), %r8, 4)
+
+/* Case2 or Case3, Case3 */
+
+ .p2align 4
+L(CopyFrom1To16BytesCase2OrCase3):
+ test %rdx, %rdx
+ jnz L(CopyFrom1To16BytesCase2)
+L(CopyFrom1To16BytesCase3):
+ add $16, %r8
+ add %rcx, %rdi
+ add %rcx, %rsi
+ BRANCH_TO_JMPTBL_ENTRY (L(ExitStrncpyTable), %r8, 4)
+
+ .p2align 4
+L(CopyFrom1To32BytesCase2OrCase3):
+ test %rdx, %rdx
+ jnz L(CopyFrom1To32BytesCase2)
+ add %rcx, %rsi
+ BRANCH_TO_JMPTBL_ENTRY (L(ExitStrncpyTable), %r8, 4)
+
+ .p2align 4
+L(CopyFrom1To16BytesTailCase2OrCase3):
+ test %rdx, %rdx
+ jnz L(CopyFrom1To16BytesTailCase2)
+ add %rcx, %rsi
+ BRANCH_TO_JMPTBL_ENTRY (L(ExitStrncpyTable), %r8, 4)
+
+ .p2align 4
+L(CopyFrom1To32Bytes1Case2OrCase3):
+ add $16, %rdi
+ add $16, %rsi
+ sub $16, %r8
+L(CopyFrom1To16BytesTail1Case2OrCase3):
+ test %rdx, %rdx
+ jnz L(CopyFrom1To16BytesTail1Case2)
+ BRANCH_TO_JMPTBL_ENTRY (L(ExitStrncpyTable), %r8, 4)
+
+#endif
+
+/*------------End labels regarding with copying 1-16 bytes--and 1-32 bytes----*/
+
+ .p2align 4
+L(Exit1):
+ mov %dh, (%rdi)
+#ifdef USE_AS_STPCPY
+ lea (%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $1, %r8
+ lea 1(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit2):
+ mov (%rsi), %dx
+ mov %dx, (%rdi)
+#ifdef USE_AS_STPCPY
+ lea 1(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $2, %r8
+ lea 2(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit3):
+ mov (%rsi), %cx
+ mov %cx, (%rdi)
+ mov %dh, 2(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 2(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $3, %r8
+ lea 3(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit4):
+ mov (%rsi), %edx
+ mov %edx, (%rdi)
+#ifdef USE_AS_STPCPY
+ lea 3(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $4, %r8
+ lea 4(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit5):
+ mov (%rsi), %ecx
+ mov %dh, 4(%rdi)
+ mov %ecx, (%rdi)
+#ifdef USE_AS_STPCPY
+ lea 4(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $5, %r8
+ lea 5(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit6):
+ mov (%rsi), %ecx
+ mov 4(%rsi), %dx
+ mov %ecx, (%rdi)
+ mov %dx, 4(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 5(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $6, %r8
+ lea 6(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit7):
+ mov (%rsi), %ecx
+ mov 3(%rsi), %edx
+ mov %ecx, (%rdi)
+ mov %edx, 3(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 6(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $7, %r8
+ lea 7(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit8):
+ mov (%rsi), %rdx
+ mov %rdx, (%rdi)
+#ifdef USE_AS_STPCPY
+ lea 7(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $8, %r8
+ lea 8(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit9):
+ mov (%rsi), %rcx
+ mov %dh, 8(%rdi)
+ mov %rcx, (%rdi)
+#ifdef USE_AS_STPCPY
+ lea 8(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $9, %r8
+ lea 9(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit10):
+ mov (%rsi), %rcx
+ mov 8(%rsi), %dx
+ mov %rcx, (%rdi)
+ mov %dx, 8(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 9(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $10, %r8
+ lea 10(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit11):
+ mov (%rsi), %rcx
+ mov 7(%rsi), %edx
+ mov %rcx, (%rdi)
+ mov %edx, 7(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 10(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $11, %r8
+ lea 11(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit12):
+ mov (%rsi), %rcx
+ mov 8(%rsi), %edx
+ mov %rcx, (%rdi)
+ mov %edx, 8(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 11(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $12, %r8
+ lea 12(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit13):
+ mov (%rsi), %rcx
+ mov 5(%rsi), %rdx
+ mov %rcx, (%rdi)
+ mov %rdx, 5(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 12(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $13, %r8
+ lea 13(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit14):
+ mov (%rsi), %rcx
+ mov 6(%rsi), %rdx
+ mov %rcx, (%rdi)
+ mov %rdx, 6(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 13(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $14, %r8
+ lea 14(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit15):
+ mov (%rsi), %rcx
+ mov 7(%rsi), %rdx
+ mov %rcx, (%rdi)
+ mov %rdx, 7(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 14(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $15, %r8
+ lea 15(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit16):
+ movdqu (%rsi), %xmm0
+ movdqu %xmm0, (%rdi)
+#ifdef USE_AS_STPCPY
+ lea 15(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $16, %r8
+ lea 16(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit17):
+ movdqu (%rsi), %xmm0
+ movdqu %xmm0, (%rdi)
+ mov %dh, 16(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 16(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $17, %r8
+ lea 17(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit18):
+ movdqu (%rsi), %xmm0
+ mov 16(%rsi), %cx
+ movdqu %xmm0, (%rdi)
+ mov %cx, 16(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 17(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $18, %r8
+ lea 18(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit19):
+ movdqu (%rsi), %xmm0
+ mov 15(%rsi), %ecx
+ movdqu %xmm0, (%rdi)
+ mov %ecx, 15(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 18(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $19, %r8
+ lea 19(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit20):
+ movdqu (%rsi), %xmm0
+ mov 16(%rsi), %ecx
+ movdqu %xmm0, (%rdi)
+ mov %ecx, 16(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 19(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $20, %r8
+ lea 20(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit21):
+ movdqu (%rsi), %xmm0
+ mov 16(%rsi), %ecx
+ movdqu %xmm0, (%rdi)
+ mov %ecx, 16(%rdi)
+ mov %dh, 20(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 20(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $21, %r8
+ lea 21(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit22):
+ movdqu (%rsi), %xmm0
+ mov 14(%rsi), %rcx
+ movdqu %xmm0, (%rdi)
+ mov %rcx, 14(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 21(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $22, %r8
+ lea 22(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit23):
+ movdqu (%rsi), %xmm0
+ mov 15(%rsi), %rcx
+ movdqu %xmm0, (%rdi)
+ mov %rcx, 15(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 22(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $23, %r8
+ lea 23(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit24):
+ movdqu (%rsi), %xmm0
+ mov 16(%rsi), %rcx
+ movdqu %xmm0, (%rdi)
+ mov %rcx, 16(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 23(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $24, %r8
+ lea 24(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit25):
+ movdqu (%rsi), %xmm0
+ mov 16(%rsi), %rcx
+ movdqu %xmm0, (%rdi)
+ mov %rcx, 16(%rdi)
+ mov %dh, 24(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 24(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $25, %r8
+ lea 25(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit26):
+ movdqu (%rsi), %xmm0
+ mov 16(%rsi), %rdx
+ mov 24(%rsi), %cx
+ movdqu %xmm0, (%rdi)
+ mov %rdx, 16(%rdi)
+ mov %cx, 24(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 25(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $26, %r8
+ lea 26(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit27):
+ movdqu (%rsi), %xmm0
+ mov 16(%rsi), %rdx
+ mov 23(%rsi), %ecx
+ movdqu %xmm0, (%rdi)
+ mov %rdx, 16(%rdi)
+ mov %ecx, 23(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 26(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $27, %r8
+ lea 27(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit28):
+ movdqu (%rsi), %xmm0
+ mov 16(%rsi), %rdx
+ mov 24(%rsi), %ecx
+ movdqu %xmm0, (%rdi)
+ mov %rdx, 16(%rdi)
+ mov %ecx, 24(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 27(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $28, %r8
+ lea 28(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit29):
+ movdqu (%rsi), %xmm0
+ movdqu 13(%rsi), %xmm2
+ movdqu %xmm0, (%rdi)
+ movdqu %xmm2, 13(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 28(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $29, %r8
+ lea 29(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit30):
+ movdqu (%rsi), %xmm0
+ movdqu 14(%rsi), %xmm2
+ movdqu %xmm0, (%rdi)
+ movdqu %xmm2, 14(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 29(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $30, %r8
+ lea 30(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit31):
+ movdqu (%rsi), %xmm0
+ movdqu 15(%rsi), %xmm2
+ movdqu %xmm0, (%rdi)
+ movdqu %xmm2, 15(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 30(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $31, %r8
+ lea 31(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+ .p2align 4
+L(Exit32):
+ movdqu (%rsi), %xmm0
+ movdqu 16(%rsi), %xmm2
+ movdqu %xmm0, (%rdi)
+ movdqu %xmm2, 16(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 31(%rdi), %rax
+#endif
+#if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT
+ sub $32, %r8
+ lea 32(%rdi), %rdi
+ jnz L(StrncpyFillTailWithZero)
+#endif
+ RETURN
+
+#ifdef USE_AS_STRNCPY
+
+ .p2align 4
+L(StrncpyExit0):
+#ifdef USE_AS_STPCPY
+ mov %rdi, %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, (%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit1):
+ mov (%rsi), %dl
+ mov %dl, (%rdi)
+#ifdef USE_AS_STPCPY
+ lea 1(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 1(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit2):
+ mov (%rsi), %dx
+ mov %dx, (%rdi)
+#ifdef USE_AS_STPCPY
+ lea 2(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 2(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit3):
+ mov (%rsi), %cx
+ mov 2(%rsi), %dl
+ mov %cx, (%rdi)
+ mov %dl, 2(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 3(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 3(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit4):
+ mov (%rsi), %edx
+ mov %edx, (%rdi)
+#ifdef USE_AS_STPCPY
+ lea 4(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 4(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit5):
+ mov (%rsi), %ecx
+ mov 4(%rsi), %dl
+ mov %ecx, (%rdi)
+ mov %dl, 4(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 5(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 5(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit6):
+ mov (%rsi), %ecx
+ mov 4(%rsi), %dx
+ mov %ecx, (%rdi)
+ mov %dx, 4(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 6(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 6(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit7):
+ mov (%rsi), %ecx
+ mov 3(%rsi), %edx
+ mov %ecx, (%rdi)
+ mov %edx, 3(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 7(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 7(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit8):
+ mov (%rsi), %rdx
+ mov %rdx, (%rdi)
+#ifdef USE_AS_STPCPY
+ lea 8(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 8(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit9):
+ mov (%rsi), %rcx
+ mov 8(%rsi), %dl
+ mov %rcx, (%rdi)
+ mov %dl, 8(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 9(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 9(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit10):
+ mov (%rsi), %rcx
+ mov 8(%rsi), %dx
+ mov %rcx, (%rdi)
+ mov %dx, 8(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 10(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 10(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit11):
+ mov (%rsi), %rcx
+ mov 7(%rsi), %edx
+ mov %rcx, (%rdi)
+ mov %edx, 7(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 11(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 11(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit12):
+ mov (%rsi), %rcx
+ mov 8(%rsi), %edx
+ mov %rcx, (%rdi)
+ mov %edx, 8(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 12(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 12(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit13):
+ mov (%rsi), %rcx
+ mov 5(%rsi), %rdx
+ mov %rcx, (%rdi)
+ mov %rdx, 5(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 13(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 13(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit14):
+ mov (%rsi), %rcx
+ mov 6(%rsi), %rdx
+ mov %rcx, (%rdi)
+ mov %rdx, 6(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 14(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 14(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit15):
+ mov (%rsi), %rcx
+ mov 7(%rsi), %rdx
+ mov %rcx, (%rdi)
+ mov %rdx, 7(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 15(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 15(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit16):
+ movdqu (%rsi), %xmm0
+ movdqu %xmm0, (%rdi)
+#ifdef USE_AS_STPCPY
+ lea 16(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 16(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit17):
+ movdqu (%rsi), %xmm0
+ mov 16(%rsi), %cl
+ movdqu %xmm0, (%rdi)
+ mov %cl, 16(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 17(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 17(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit18):
+ movdqu (%rsi), %xmm0
+ mov 16(%rsi), %cx
+ movdqu %xmm0, (%rdi)
+ mov %cx, 16(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 18(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 18(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit19):
+ movdqu (%rsi), %xmm0
+ mov 15(%rsi), %ecx
+ movdqu %xmm0, (%rdi)
+ mov %ecx, 15(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 19(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 19(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit20):
+ movdqu (%rsi), %xmm0
+ mov 16(%rsi), %ecx
+ movdqu %xmm0, (%rdi)
+ mov %ecx, 16(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 20(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 20(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit21):
+ movdqu (%rsi), %xmm0
+ mov 16(%rsi), %ecx
+ mov 20(%rsi), %dl
+ movdqu %xmm0, (%rdi)
+ mov %ecx, 16(%rdi)
+ mov %dl, 20(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 21(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 21(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit22):
+ movdqu (%rsi), %xmm0
+ mov 14(%rsi), %rcx
+ movdqu %xmm0, (%rdi)
+ mov %rcx, 14(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 22(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 22(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit23):
+ movdqu (%rsi), %xmm0
+ mov 15(%rsi), %rcx
+ movdqu %xmm0, (%rdi)
+ mov %rcx, 15(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 23(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 23(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit24):
+ movdqu (%rsi), %xmm0
+ mov 16(%rsi), %rcx
+ movdqu %xmm0, (%rdi)
+ mov %rcx, 16(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 24(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 24(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit25):
+ movdqu (%rsi), %xmm0
+ mov 16(%rsi), %rdx
+ mov 24(%rsi), %cl
+ movdqu %xmm0, (%rdi)
+ mov %rdx, 16(%rdi)
+ mov %cl, 24(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 25(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 25(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit26):
+ movdqu (%rsi), %xmm0
+ mov 16(%rsi), %rdx
+ mov 24(%rsi), %cx
+ movdqu %xmm0, (%rdi)
+ mov %rdx, 16(%rdi)
+ mov %cx, 24(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 26(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 26(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit27):
+ movdqu (%rsi), %xmm0
+ mov 16(%rsi), %rdx
+ mov 23(%rsi), %ecx
+ movdqu %xmm0, (%rdi)
+ mov %rdx, 16(%rdi)
+ mov %ecx, 23(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 27(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 27(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit28):
+ movdqu (%rsi), %xmm0
+ mov 16(%rsi), %rdx
+ mov 24(%rsi), %ecx
+ movdqu %xmm0, (%rdi)
+ mov %rdx, 16(%rdi)
+ mov %ecx, 24(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 28(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 28(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit29):
+ movdqu (%rsi), %xmm0
+ movdqu 13(%rsi), %xmm2
+ movdqu %xmm0, (%rdi)
+ movdqu %xmm2, 13(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 29(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 29(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit30):
+ movdqu (%rsi), %xmm0
+ movdqu 14(%rsi), %xmm2
+ movdqu %xmm0, (%rdi)
+ movdqu %xmm2, 14(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 30(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 30(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit31):
+ movdqu (%rsi), %xmm0
+ movdqu 15(%rsi), %xmm2
+ movdqu %xmm0, (%rdi)
+ movdqu %xmm2, 15(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 31(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 31(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit32):
+ movdqu (%rsi), %xmm0
+ movdqu 16(%rsi), %xmm2
+ movdqu %xmm0, (%rdi)
+ movdqu %xmm2, 16(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 32(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 32(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(StrncpyExit33):
+ movdqu (%rsi), %xmm0
+ movdqu 16(%rsi), %xmm2
+ mov 32(%rsi), %cl
+ movdqu %xmm0, (%rdi)
+ movdqu %xmm2, 16(%rdi)
+ mov %cl, 32(%rdi)
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 33(%rdi)
+#endif
+ RETURN
+
+#ifndef USE_AS_STRCAT
+
+ .p2align 4
+L(Fill0):
+ RETURN
+
+ .p2align 4
+L(Fill1):
+ mov %dl, (%rdi)
+ RETURN
+
+ .p2align 4
+L(Fill2):
+ mov %dx, (%rdi)
+ RETURN
+
+ .p2align 4
+L(Fill3):
+ mov %edx, -1(%rdi)
+ RETURN
+
+ .p2align 4
+L(Fill4):
+ mov %edx, (%rdi)
+ RETURN
+
+ .p2align 4
+L(Fill5):
+ mov %edx, (%rdi)
+ mov %dl, 4(%rdi)
+ RETURN
+
+ .p2align 4
+L(Fill6):
+ mov %edx, (%rdi)
+ mov %dx, 4(%rdi)
+ RETURN
+
+ .p2align 4
+L(Fill7):
+ mov %rdx, -1(%rdi)
+ RETURN
+
+ .p2align 4
+L(Fill8):
+ mov %rdx, (%rdi)
+ RETURN
+
+ .p2align 4
+L(Fill9):
+ mov %rdx, (%rdi)
+ mov %dl, 8(%rdi)
+ RETURN
+
+ .p2align 4
+L(Fill10):
+ mov %rdx, (%rdi)
+ mov %dx, 8(%rdi)
+ RETURN
+
+ .p2align 4
+L(Fill11):
+ mov %rdx, (%rdi)
+ mov %edx, 7(%rdi)
+ RETURN
+
+ .p2align 4
+L(Fill12):
+ mov %rdx, (%rdi)
+ mov %edx, 8(%rdi)
+ RETURN
+
+ .p2align 4
+L(Fill13):
+ mov %rdx, (%rdi)
+ mov %rdx, 5(%rdi)
+ RETURN
+
+ .p2align 4
+L(Fill14):
+ mov %rdx, (%rdi)
+ mov %rdx, 6(%rdi)
+ RETURN
+
+ .p2align 4
+L(Fill15):
+ movdqu %xmm0, -1(%rdi)
+ RETURN
+
+ .p2align 4
+L(Fill16):
+ movdqu %xmm0, (%rdi)
+ RETURN
+
+ .p2align 4
+L(CopyFrom1To16BytesUnalignedXmm2):
+ movdqu %xmm2, (%rdi, %rcx)
+
+ .p2align 4
+L(CopyFrom1To16BytesXmmExit):
+ bsf %rdx, %rdx
+ add $15, %r8
+ add %rcx, %rdi
+#ifdef USE_AS_STPCPY
+ lea (%rdi, %rdx), %rax
+#endif
+ sub %rdx, %r8
+ lea 1(%rdi, %rdx), %rdi
+
+ .p2align 4
+L(StrncpyFillTailWithZero):
+ pxor %xmm0, %xmm0
+ xor %rdx, %rdx
+ sub $16, %r8
+ jbe L(StrncpyFillExit)
+
+ movdqu %xmm0, (%rdi)
+ add $16, %rdi
+
+ mov %rdi, %rsi
+ and $0xf, %rsi
+ sub %rsi, %rdi
+ add %rsi, %r8
+ sub $64, %r8
+ jb L(StrncpyFillLess64)
+
+L(StrncpyFillLoopMovdqa):
+ movdqa %xmm0, (%rdi)
+ movdqa %xmm0, 16(%rdi)
+ movdqa %xmm0, 32(%rdi)
+ movdqa %xmm0, 48(%rdi)
+ add $64, %rdi
+ sub $64, %r8
+ jae L(StrncpyFillLoopMovdqa)
+
+L(StrncpyFillLess64):
+ add $32, %r8
+ jl L(StrncpyFillLess32)
+ movdqa %xmm0, (%rdi)
+ movdqa %xmm0, 16(%rdi)
+ add $32, %rdi
+ sub $16, %r8
+ jl L(StrncpyFillExit)
+ movdqa %xmm0, (%rdi)
+ add $16, %rdi
+ BRANCH_TO_JMPTBL_ENTRY (L(FillTable), %r8, 4)
+
+L(StrncpyFillLess32):
+ add $16, %r8
+ jl L(StrncpyFillExit)
+ movdqa %xmm0, (%rdi)
+ add $16, %rdi
+ BRANCH_TO_JMPTBL_ENTRY (L(FillTable), %r8, 4)
+
+L(StrncpyFillExit):
+ add $16, %r8
+ BRANCH_TO_JMPTBL_ENTRY (L(FillTable), %r8, 4)
+
+/* end of ifndef USE_AS_STRCAT */
+#endif
+
+ .p2align 4
+L(UnalignedLeaveCase2OrCase3):
+ test %rdx, %rdx
+ jnz L(Unaligned64LeaveCase2)
+L(Unaligned64LeaveCase3):
+ lea 64(%r8), %rcx
+ and $-16, %rcx
+ add $48, %r8
+ jl L(CopyFrom1To16BytesCase3)
+ movdqu %xmm4, (%rdi)
+ sub $16, %r8
+ jb L(CopyFrom1To16BytesCase3)
+ movdqu %xmm5, 16(%rdi)
+ sub $16, %r8
+ jb L(CopyFrom1To16BytesCase3)
+ movdqu %xmm6, 32(%rdi)
+ sub $16, %r8
+ jb L(CopyFrom1To16BytesCase3)
+ movdqu %xmm7, 48(%rdi)
+#ifdef USE_AS_STPCPY
+ lea 64(%rdi), %rax
+#endif
+#ifdef USE_AS_STRCAT
+ xor %ch, %ch
+ movb %ch, 64(%rdi)
+#endif
+ RETURN
+
+ .p2align 4
+L(Unaligned64LeaveCase2):
+ xor %rcx, %rcx
+ pcmpeqb %xmm4, %xmm0
+ pmovmskb %xmm0, %rdx
+ add $48, %r8
+ jle L(CopyFrom1To16BytesCase2OrCase3)
+ test %rdx, %rdx
+#ifndef USE_AS_STRCAT
+ jnz L(CopyFrom1To16BytesUnalignedXmm4)
+#else
+ jnz L(CopyFrom1To16Bytes)
+#endif
+ pcmpeqb %xmm5, %xmm0
+ pmovmskb %xmm0, %rdx
+ movdqu %xmm4, (%rdi)
+ add $16, %rcx
+ sub $16, %r8
+ jbe L(CopyFrom1To16BytesCase2OrCase3)
+ test %rdx, %rdx
+#ifndef USE_AS_STRCAT
+ jnz L(CopyFrom1To16BytesUnalignedXmm5)
+#else
+ jnz L(CopyFrom1To16Bytes)
+#endif
+
+ pcmpeqb %xmm6, %xmm0
+ pmovmskb %xmm0, %rdx
+ movdqu %xmm5, 16(%rdi)
+ add $16, %rcx
+ sub $16, %r8
+ jbe L(CopyFrom1To16BytesCase2OrCase3)
+ test %rdx, %rdx
+#ifndef USE_AS_STRCAT
+ jnz L(CopyFrom1To16BytesUnalignedXmm6)
+#else
+ jnz L(CopyFrom1To16Bytes)
+#endif
+
+ pcmpeqb %xmm7, %xmm0
+ pmovmskb %xmm0, %rdx
+ movdqu %xmm6, 32(%rdi)
+ lea 16(%rdi, %rcx), %rdi
+ lea 16(%rsi, %rcx), %rsi
+ bsf %rdx, %rdx
+ cmp %r8, %rdx
+ jb L(CopyFrom1To16BytesExit)
+ BRANCH_TO_JMPTBL_ENTRY (L(ExitStrncpyTable), %r8, 4)
+
+ .p2align 4
+L(ExitZero):
+#ifndef USE_AS_STRCAT
+ mov %rdi, %rax
+#endif
+ RETURN
+
+#endif
+
+#ifndef USE_AS_STRCAT
+END (STRCPY)
+#else
+END (STRCAT)
+#endif
+ .p2align 4
+ .section .rodata
+L(ExitTable):
+ .int JMPTBL(L(Exit1), L(ExitTable))
+ .int JMPTBL(L(Exit2), L(ExitTable))
+ .int JMPTBL(L(Exit3), L(ExitTable))
+ .int JMPTBL(L(Exit4), L(ExitTable))
+ .int JMPTBL(L(Exit5), L(ExitTable))
+ .int JMPTBL(L(Exit6), L(ExitTable))
+ .int JMPTBL(L(Exit7), L(ExitTable))
+ .int JMPTBL(L(Exit8), L(ExitTable))
+ .int JMPTBL(L(Exit9), L(ExitTable))
+ .int JMPTBL(L(Exit10), L(ExitTable))
+ .int JMPTBL(L(Exit11), L(ExitTable))
+ .int JMPTBL(L(Exit12), L(ExitTable))
+ .int JMPTBL(L(Exit13), L(ExitTable))
+ .int JMPTBL(L(Exit14), L(ExitTable))
+ .int JMPTBL(L(Exit15), L(ExitTable))
+ .int JMPTBL(L(Exit16), L(ExitTable))
+ .int JMPTBL(L(Exit17), L(ExitTable))
+ .int JMPTBL(L(Exit18), L(ExitTable))
+ .int JMPTBL(L(Exit19), L(ExitTable))
+ .int JMPTBL(L(Exit20), L(ExitTable))
+ .int JMPTBL(L(Exit21), L(ExitTable))
+ .int JMPTBL(L(Exit22), L(ExitTable))
+ .int JMPTBL(L(Exit23), L(ExitTable))
+ .int JMPTBL(L(Exit24), L(ExitTable))
+ .int JMPTBL(L(Exit25), L(ExitTable))
+ .int JMPTBL(L(Exit26), L(ExitTable))
+ .int JMPTBL(L(Exit27), L(ExitTable))
+ .int JMPTBL(L(Exit28), L(ExitTable))
+ .int JMPTBL(L(Exit29), L(ExitTable))
+ .int JMPTBL(L(Exit30), L(ExitTable))
+ .int JMPTBL(L(Exit31), L(ExitTable))
+ .int JMPTBL(L(Exit32), L(ExitTable))
+#ifdef USE_AS_STRNCPY
+L(ExitStrncpyTable):
+ .int JMPTBL(L(StrncpyExit0), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit1), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit2), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit3), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit4), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit5), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit6), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit7), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit8), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit9), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit10), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit11), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit12), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit13), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit14), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit15), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit16), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit17), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit18), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit19), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit20), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit21), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit22), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit23), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit24), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit25), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit26), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit27), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit28), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit29), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit30), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit31), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit32), L(ExitStrncpyTable))
+ .int JMPTBL(L(StrncpyExit33), L(ExitStrncpyTable))
+# ifndef USE_AS_STRCAT
+ .p2align 4
+L(FillTable):
+ .int JMPTBL(L(Fill0), L(FillTable))
+ .int JMPTBL(L(Fill1), L(FillTable))
+ .int JMPTBL(L(Fill2), L(FillTable))
+ .int JMPTBL(L(Fill3), L(FillTable))
+ .int JMPTBL(L(Fill4), L(FillTable))
+ .int JMPTBL(L(Fill5), L(FillTable))
+ .int JMPTBL(L(Fill6), L(FillTable))
+ .int JMPTBL(L(Fill7), L(FillTable))
+ .int JMPTBL(L(Fill8), L(FillTable))
+ .int JMPTBL(L(Fill9), L(FillTable))
+ .int JMPTBL(L(Fill10), L(FillTable))
+ .int JMPTBL(L(Fill11), L(FillTable))
+ .int JMPTBL(L(Fill12), L(FillTable))
+ .int JMPTBL(L(Fill13), L(FillTable))
+ .int JMPTBL(L(Fill14), L(FillTable))
+ .int JMPTBL(L(Fill15), L(FillTable))
+ .int JMPTBL(L(Fill16), L(FillTable))
+# endif
+#endif
diff --git a/contrib/bionic-x86_64-string/sse2-strlen-slm.S b/contrib/bionic-x86_64-string/sse2-strlen-slm.S
new file mode 100644
index 000000000000..3772fe77043a
--- /dev/null
+++ b/contrib/bionic-x86_64-string/sse2-strlen-slm.S
@@ -0,0 +1,294 @@
+/*
+Copyright (c) 2014, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef USE_AS_STRCAT
+
+#ifndef STRLEN
+# define STRLEN strlen
+#endif
+
+#ifndef L
+# define L(label) .L##label
+#endif
+
+#ifndef cfi_startproc
+# define cfi_startproc .cfi_startproc
+#endif
+
+#ifndef cfi_endproc
+# define cfi_endproc .cfi_endproc
+#endif
+
+#ifndef ENTRY
+# define ENTRY(name) \
+ .type name, @function; \
+ .globl name; \
+ .p2align 4; \
+name: \
+ cfi_startproc
+#endif
+
+#ifndef END
+# define END(name) \
+ cfi_endproc; \
+ .size name, .-name
+#endif
+#define RETURN ret
+ .section .text.sse2,"ax",@progbits
+ENTRY (STRLEN)
+/* end ifndef USE_AS_STRCAT */
+#endif
+ xor %rax, %rax
+ mov %edi, %ecx
+ and $0x3f, %ecx
+ pxor %xmm0, %xmm0
+ cmp $0x30, %ecx
+ ja L(next)
+ movdqu (%rdi), %xmm1
+ pcmpeqb %xmm1, %xmm0
+ pmovmskb %xmm0, %edx
+ test %edx, %edx
+ jnz L(exit_less16)
+ mov %rdi, %rax
+ and $-16, %rax
+ jmp L(align16_start)
+L(next):
+ mov %rdi, %rax
+ and $-16, %rax
+ pcmpeqb (%rax), %xmm0
+ mov $-1, %r10d
+ sub %rax, %rcx
+ shl %cl, %r10d
+ pmovmskb %xmm0, %edx
+ and %r10d, %edx
+ jnz L(exit)
+L(align16_start):
+ pxor %xmm0, %xmm0
+ pxor %xmm1, %xmm1
+ pxor %xmm2, %xmm2
+ pxor %xmm3, %xmm3
+ pcmpeqb 16(%rax), %xmm0
+ pmovmskb %xmm0, %edx
+ test %edx, %edx
+ jnz L(exit16)
+
+ pcmpeqb 32(%rax), %xmm1
+ pmovmskb %xmm1, %edx
+ test %edx, %edx
+ jnz L(exit32)
+
+ pcmpeqb 48(%rax), %xmm2
+ pmovmskb %xmm2, %edx
+ test %edx, %edx
+ jnz L(exit48)
+
+ pcmpeqb 64(%rax), %xmm3
+ pmovmskb %xmm3, %edx
+ test %edx, %edx
+ jnz L(exit64)
+
+ pcmpeqb 80(%rax), %xmm0
+ add $64, %rax
+ pmovmskb %xmm0, %edx
+ test %edx, %edx
+ jnz L(exit16)
+
+ pcmpeqb 32(%rax), %xmm1
+ pmovmskb %xmm1, %edx
+ test %edx, %edx
+ jnz L(exit32)
+
+ pcmpeqb 48(%rax), %xmm2
+ pmovmskb %xmm2, %edx
+ test %edx, %edx
+ jnz L(exit48)
+
+ pcmpeqb 64(%rax), %xmm3
+ pmovmskb %xmm3, %edx
+ test %edx, %edx
+ jnz L(exit64)
+
+ pcmpeqb 80(%rax), %xmm0
+ add $64, %rax
+ pmovmskb %xmm0, %edx
+ test %edx, %edx
+ jnz L(exit16)
+
+ pcmpeqb 32(%rax), %xmm1
+ pmovmskb %xmm1, %edx
+ test %edx, %edx
+ jnz L(exit32)
+
+ pcmpeqb 48(%rax), %xmm2
+ pmovmskb %xmm2, %edx
+ test %edx, %edx
+ jnz L(exit48)
+
+ pcmpeqb 64(%rax), %xmm3
+ pmovmskb %xmm3, %edx
+ test %edx, %edx
+ jnz L(exit64)
+
+ pcmpeqb 80(%rax), %xmm0
+ add $64, %rax
+ pmovmskb %xmm0, %edx
+ test %edx, %edx
+ jnz L(exit16)
+
+ pcmpeqb 32(%rax), %xmm1
+ pmovmskb %xmm1, %edx
+ test %edx, %edx
+ jnz L(exit32)
+
+ pcmpeqb 48(%rax), %xmm2
+ pmovmskb %xmm2, %edx
+ test %edx, %edx
+ jnz L(exit48)
+
+ pcmpeqb 64(%rax), %xmm3
+ pmovmskb %xmm3, %edx
+ test %edx, %edx
+ jnz L(exit64)
+
+
+ test $0x3f, %rax
+ jz L(align64_loop)
+
+ pcmpeqb 80(%rax), %xmm0
+ add $80, %rax
+ pmovmskb %xmm0, %edx
+ test %edx, %edx
+ jnz L(exit)
+
+ test $0x3f, %rax
+ jz L(align64_loop)
+
+ pcmpeqb 16(%rax), %xmm1
+ add $16, %rax
+ pmovmskb %xmm1, %edx
+ test %edx, %edx
+ jnz L(exit)
+
+ test $0x3f, %rax
+ jz L(align64_loop)
+
+ pcmpeqb 16(%rax), %xmm2
+ add $16, %rax
+ pmovmskb %xmm2, %edx
+ test %edx, %edx
+ jnz L(exit)
+
+ test $0x3f, %rax
+ jz L(align64_loop)
+
+ pcmpeqb 16(%rax), %xmm3
+ add $16, %rax
+ pmovmskb %xmm3, %edx
+ test %edx, %edx
+ jnz L(exit)
+
+ add $16, %rax
+ .p2align 4
+ L(align64_loop):
+ movaps (%rax), %xmm4
+ pminub 16(%rax), %xmm4
+ movaps 32(%rax), %xmm5
+ pminub 48(%rax), %xmm5
+ add $64, %rax
+ pminub %xmm4, %xmm5
+ pcmpeqb %xmm0, %xmm5
+ pmovmskb %xmm5, %edx
+ test %edx, %edx
+ jz L(align64_loop)
+
+
+ pcmpeqb -64(%rax), %xmm0
+ sub $80, %rax
+ pmovmskb %xmm0, %edx
+ test %edx, %edx
+ jnz L(exit16)
+
+ pcmpeqb 32(%rax), %xmm1
+ pmovmskb %xmm1, %edx
+ test %edx, %edx
+ jnz L(exit32)
+
+ pcmpeqb 48(%rax), %xmm2
+ pmovmskb %xmm2, %edx
+ test %edx, %edx
+ jnz L(exit48)
+
+ pcmpeqb 64(%rax), %xmm3
+ pmovmskb %xmm3, %edx
+ sub %rdi, %rax
+ bsf %rdx, %rdx
+ add %rdx, %rax
+ add $64, %rax
+ RETURN
+
+ .p2align 4
+L(exit):
+ sub %rdi, %rax
+L(exit_less16):
+ bsf %rdx, %rdx
+ add %rdx, %rax
+ RETURN
+ .p2align 4
+L(exit16):
+ sub %rdi, %rax
+ bsf %rdx, %rdx
+ add %rdx, %rax
+ add $16, %rax
+ RETURN
+ .p2align 4
+L(exit32):
+ sub %rdi, %rax
+ bsf %rdx, %rdx
+ add %rdx, %rax
+ add $32, %rax
+ RETURN
+ .p2align 4
+L(exit48):
+ sub %rdi, %rax
+ bsf %rdx, %rdx
+ add %rdx, %rax
+ add $48, %rax
+ RETURN
+ .p2align 4
+L(exit64):
+ sub %rdi, %rax
+ bsf %rdx, %rdx
+ add %rdx, %rax
+ add $64, %rax
+#ifndef USE_AS_STRCAT
+ RETURN
+
+END (STRLEN)
+#endif
diff --git a/contrib/bionic-x86_64-string/sse2-strncat-slm.S b/contrib/bionic-x86_64-string/sse2-strncat-slm.S
new file mode 100644
index 000000000000..6b4a430846b0
--- /dev/null
+++ b/contrib/bionic-x86_64-string/sse2-strncat-slm.S
@@ -0,0 +1,33 @@
+/*
+Copyright (c) 2014, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#define USE_AS_STRNCAT
+#define STRCAT strncat
+#include "sse2-strcat-slm.S"
diff --git a/contrib/bionic-x86_64-string/sse2-strncpy-slm.S b/contrib/bionic-x86_64-string/sse2-strncpy-slm.S
new file mode 100644
index 000000000000..594e78f74479
--- /dev/null
+++ b/contrib/bionic-x86_64-string/sse2-strncpy-slm.S
@@ -0,0 +1,33 @@
+/*
+Copyright (c) 2014, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#define USE_AS_STRNCPY
+#define STRCPY strncpy
+#include "sse2-strcpy-slm.S"
diff --git a/contrib/bionic-x86_64-string/sse4-memcmp-slm.S b/contrib/bionic-x86_64-string/sse4-memcmp-slm.S
new file mode 100644
index 000000000000..8a8b180a29e5
--- /dev/null
+++ b/contrib/bionic-x86_64-string/sse4-memcmp-slm.S
@@ -0,0 +1,1799 @@
+/*
+Copyright (c) 2014, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "cache.h"
+
+#ifndef MEMCMP
+# define MEMCMP memcmp
+#endif
+
+#ifndef L
+# define L(label) .L##label
+#endif
+
+#ifndef ALIGN
+# define ALIGN(n) .p2align n
+#endif
+
+#ifndef cfi_startproc
+# define cfi_startproc .cfi_startproc
+#endif
+
+#ifndef cfi_endproc
+# define cfi_endproc .cfi_endproc
+#endif
+
+#ifndef ENTRY
+# define ENTRY(name) \
+ .type name, @function; \
+ .globl name; \
+ .p2align 4; \
+name: \
+ cfi_startproc
+#endif
+
+#ifndef END
+# define END(name) \
+ cfi_endproc; \
+ .size name, .-name
+#endif
+
+#ifndef ALIGN
+# define ALIGN(n) .p2align n
+#endif
+
+#define JMPTBL(I, B) (I - B)
+
+#define BRANCH_TO_JMPTBL_ENTRY(TABLE, INDEX, SCALE) \
+ lea TABLE(%rip), %r11; \
+ movslq (%r11, INDEX, SCALE), %rcx; \
+ add %r11, %rcx; \
+ jmp *%rcx; \
+ ud2
+
+ .section .text.sse4.1,"ax",@progbits
+ENTRY (MEMCMP)
+#ifdef USE_AS_WMEMCMP
+ shl $2, %rdx
+#endif
+ pxor %xmm0, %xmm0
+ cmp $79, %rdx
+ ja L(79bytesormore)
+#ifndef USE_AS_WMEMCMP
+ cmp $1, %rdx
+ je L(firstbyte)
+#endif
+ add %rdx, %rsi
+ add %rdx, %rdi
+ BRANCH_TO_JMPTBL_ENTRY(L(table_64bytes), %rdx, 4)
+
+#ifndef USE_AS_WMEMCMP
+ ALIGN (4)
+L(firstbyte):
+ movzbl (%rdi), %eax
+ movzbl (%rsi), %ecx
+ sub %ecx, %eax
+ ret
+#endif
+
+ ALIGN (4)
+L(79bytesormore):
+ movdqu (%rsi), %xmm1
+ movdqu (%rdi), %xmm2
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(16bytesin256)
+ mov %rsi, %rcx
+ and $-16, %rsi
+ add $16, %rsi
+ sub %rsi, %rcx
+
+ sub %rcx, %rdi
+ add %rcx, %rdx
+ test $0xf, %rdi
+ jz L(2aligned)
+
+ cmp $128, %rdx
+ ja L(128bytesormore)
+L(less128bytes):
+ sub $64, %rdx
+
+ movdqu (%rdi), %xmm2
+ pxor (%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(16bytesin256)
+
+ movdqu 16(%rdi), %xmm2
+ pxor 16(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(32bytesin256)
+
+ movdqu 32(%rdi), %xmm2
+ pxor 32(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(48bytesin256)
+
+ movdqu 48(%rdi), %xmm2
+ pxor 48(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(64bytesin256)
+ cmp $32, %rdx
+ jb L(less32bytesin64)
+
+ movdqu 64(%rdi), %xmm2
+ pxor 64(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(80bytesin256)
+
+ movdqu 80(%rdi), %xmm2
+ pxor 80(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(96bytesin256)
+ sub $32, %rdx
+ add $32, %rdi
+ add $32, %rsi
+L(less32bytesin64):
+ add $64, %rdi
+ add $64, %rsi
+ add %rdx, %rsi
+ add %rdx, %rdi
+ BRANCH_TO_JMPTBL_ENTRY(L(table_64bytes), %rdx, 4)
+
+L(128bytesormore):
+ cmp $512, %rdx
+ ja L(512bytesormore)
+ cmp $256, %rdx
+ ja L(less512bytes)
+L(less256bytes):
+ sub $128, %rdx
+
+ movdqu (%rdi), %xmm2
+ pxor (%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(16bytesin256)
+
+ movdqu 16(%rdi), %xmm2
+ pxor 16(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(32bytesin256)
+
+ movdqu 32(%rdi), %xmm2
+ pxor 32(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(48bytesin256)
+
+ movdqu 48(%rdi), %xmm2
+ pxor 48(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(64bytesin256)
+
+ movdqu 64(%rdi), %xmm2
+ pxor 64(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(80bytesin256)
+
+ movdqu 80(%rdi), %xmm2
+ pxor 80(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(96bytesin256)
+
+ movdqu 96(%rdi), %xmm2
+ pxor 96(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(112bytesin256)
+
+ movdqu 112(%rdi), %xmm2
+ pxor 112(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(128bytesin256)
+
+ add $128, %rsi
+ add $128, %rdi
+
+ cmp $64, %rdx
+ jae L(less128bytes)
+
+ cmp $32, %rdx
+ jb L(less32bytesin128)
+
+ movdqu (%rdi), %xmm2
+ pxor (%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(16bytesin256)
+
+ movdqu 16(%rdi), %xmm2
+ pxor 16(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(32bytesin256)
+ sub $32, %rdx
+ add $32, %rdi
+ add $32, %rsi
+L(less32bytesin128):
+ add %rdx, %rsi
+ add %rdx, %rdi
+ BRANCH_TO_JMPTBL_ENTRY(L(table_64bytes), %rdx, 4)
+
+L(less512bytes):
+ sub $256, %rdx
+ movdqu (%rdi), %xmm2
+ pxor (%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(16bytesin256)
+
+ movdqu 16(%rdi), %xmm2
+ pxor 16(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(32bytesin256)
+
+ movdqu 32(%rdi), %xmm2
+ pxor 32(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(48bytesin256)
+
+ movdqu 48(%rdi), %xmm2
+ pxor 48(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(64bytesin256)
+
+ movdqu 64(%rdi), %xmm2
+ pxor 64(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(80bytesin256)
+
+ movdqu 80(%rdi), %xmm2
+ pxor 80(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(96bytesin256)
+
+ movdqu 96(%rdi), %xmm2
+ pxor 96(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(112bytesin256)
+
+ movdqu 112(%rdi), %xmm2
+ pxor 112(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(128bytesin256)
+
+ movdqu 128(%rdi), %xmm2
+ pxor 128(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(144bytesin256)
+
+ movdqu 144(%rdi), %xmm2
+ pxor 144(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(160bytesin256)
+
+ movdqu 160(%rdi), %xmm2
+ pxor 160(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(176bytesin256)
+
+ movdqu 176(%rdi), %xmm2
+ pxor 176(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(192bytesin256)
+
+ movdqu 192(%rdi), %xmm2
+ pxor 192(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(208bytesin256)
+
+ movdqu 208(%rdi), %xmm2
+ pxor 208(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(224bytesin256)
+
+ movdqu 224(%rdi), %xmm2
+ pxor 224(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(240bytesin256)
+
+ movdqu 240(%rdi), %xmm2
+ pxor 240(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(256bytesin256)
+
+ add $256, %rsi
+ add $256, %rdi
+
+ cmp $128, %rdx
+ jae L(less256bytes)
+
+ cmp $64, %rdx
+ jae L(less128bytes)
+
+ cmp $32, %rdx
+ jb L(less32bytesin256)
+
+ movdqu (%rdi), %xmm2
+ pxor (%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(16bytesin256)
+
+ movdqu 16(%rdi), %xmm2
+ pxor 16(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(32bytesin256)
+ sub $32, %rdx
+ add $32, %rdi
+ add $32, %rsi
+L(less32bytesin256):
+ add %rdx, %rsi
+ add %rdx, %rdi
+ BRANCH_TO_JMPTBL_ENTRY(L(table_64bytes), %rdx, 4)
+
+ ALIGN (4)
+L(512bytesormore):
+#ifdef DATA_CACHE_SIZE_HALF
+ mov $DATA_CACHE_SIZE_HALF, %r8
+#else
+ mov __x86_64_data_cache_size_half(%rip), %r8
+#endif
+ mov %r8, %r9
+ shr $1, %r8
+ add %r9, %r8
+ cmp %r8, %rdx
+ ja L(L2_L3_cache_unaglined)
+ sub $64, %rdx
+ ALIGN (4)
+L(64bytesormore_loop):
+ movdqu (%rdi), %xmm2
+ pxor (%rsi), %xmm2
+ movdqa %xmm2, %xmm1
+
+ movdqu 16(%rdi), %xmm3
+ pxor 16(%rsi), %xmm3
+ por %xmm3, %xmm1
+
+ movdqu 32(%rdi), %xmm4
+ pxor 32(%rsi), %xmm4
+ por %xmm4, %xmm1
+
+ movdqu 48(%rdi), %xmm5
+ pxor 48(%rsi), %xmm5
+ por %xmm5, %xmm1
+
+ ptest %xmm1, %xmm0
+ jnc L(64bytesormore_loop_end)
+ add $64, %rsi
+ add $64, %rdi
+ sub $64, %rdx
+ jae L(64bytesormore_loop)
+
+ add $64, %rdx
+ add %rdx, %rsi
+ add %rdx, %rdi
+ BRANCH_TO_JMPTBL_ENTRY(L(table_64bytes), %rdx, 4)
+
+L(L2_L3_cache_unaglined):
+ sub $64, %rdx
+ ALIGN (4)
+L(L2_L3_unaligned_128bytes_loop):
+ prefetchnta 0x1c0(%rdi)
+ prefetchnta 0x1c0(%rsi)
+ movdqu (%rdi), %xmm2
+ pxor (%rsi), %xmm2
+ movdqa %xmm2, %xmm1
+
+ movdqu 16(%rdi), %xmm3
+ pxor 16(%rsi), %xmm3
+ por %xmm3, %xmm1
+
+ movdqu 32(%rdi), %xmm4
+ pxor 32(%rsi), %xmm4
+ por %xmm4, %xmm1
+
+ movdqu 48(%rdi), %xmm5
+ pxor 48(%rsi), %xmm5
+ por %xmm5, %xmm1
+
+ ptest %xmm1, %xmm0
+ jnc L(64bytesormore_loop_end)
+ add $64, %rsi
+ add $64, %rdi
+ sub $64, %rdx
+ jae L(L2_L3_unaligned_128bytes_loop)
+
+ add $64, %rdx
+ add %rdx, %rsi
+ add %rdx, %rdi
+ BRANCH_TO_JMPTBL_ENTRY(L(table_64bytes), %rdx, 4)
+
+/*
+ * This case is for machines which are sensitive for unaligned instructions.
+ */
+ ALIGN (4)
+L(2aligned):
+ cmp $128, %rdx
+ ja L(128bytesormorein2aligned)
+L(less128bytesin2aligned):
+ sub $64, %rdx
+
+ movdqa (%rdi), %xmm2
+ pxor (%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(16bytesin256)
+
+ movdqa 16(%rdi), %xmm2
+ pxor 16(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(32bytesin256)
+
+ movdqa 32(%rdi), %xmm2
+ pxor 32(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(48bytesin256)
+
+ movdqa 48(%rdi), %xmm2
+ pxor 48(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(64bytesin256)
+ cmp $32, %rdx
+ jb L(less32bytesin64in2alinged)
+
+ movdqa 64(%rdi), %xmm2
+ pxor 64(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(80bytesin256)
+
+ movdqa 80(%rdi), %xmm2
+ pxor 80(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(96bytesin256)
+ sub $32, %rdx
+ add $32, %rdi
+ add $32, %rsi
+L(less32bytesin64in2alinged):
+ add $64, %rdi
+ add $64, %rsi
+ add %rdx, %rsi
+ add %rdx, %rdi
+ BRANCH_TO_JMPTBL_ENTRY(L(table_64bytes), %rdx, 4)
+
+ ALIGN (4)
+L(128bytesormorein2aligned):
+ cmp $512, %rdx
+ ja L(512bytesormorein2aligned)
+ cmp $256, %rdx
+ ja L(256bytesormorein2aligned)
+L(less256bytesin2alinged):
+ sub $128, %rdx
+
+ movdqa (%rdi), %xmm2
+ pxor (%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(16bytesin256)
+
+ movdqa 16(%rdi), %xmm2
+ pxor 16(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(32bytesin256)
+
+ movdqa 32(%rdi), %xmm2
+ pxor 32(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(48bytesin256)
+
+ movdqa 48(%rdi), %xmm2
+ pxor 48(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(64bytesin256)
+
+ movdqa 64(%rdi), %xmm2
+ pxor 64(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(80bytesin256)
+
+ movdqa 80(%rdi), %xmm2
+ pxor 80(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(96bytesin256)
+
+ movdqa 96(%rdi), %xmm2
+ pxor 96(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(112bytesin256)
+
+ movdqa 112(%rdi), %xmm2
+ pxor 112(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(128bytesin256)
+
+ add $128, %rsi
+ add $128, %rdi
+
+ cmp $64, %rdx
+ jae L(less128bytesin2aligned)
+
+ cmp $32, %rdx
+ jb L(less32bytesin128in2aligned)
+
+ movdqu (%rdi), %xmm2
+ pxor (%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(16bytesin256)
+
+ movdqu 16(%rdi), %xmm2
+ pxor 16(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(32bytesin256)
+ sub $32, %rdx
+ add $32, %rdi
+ add $32, %rsi
+L(less32bytesin128in2aligned):
+ add %rdx, %rsi
+ add %rdx, %rdi
+ BRANCH_TO_JMPTBL_ENTRY(L(table_64bytes), %rdx, 4)
+
+ ALIGN (4)
+L(256bytesormorein2aligned):
+
+ sub $256, %rdx
+ movdqa (%rdi), %xmm2
+ pxor (%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(16bytesin256)
+
+ movdqa 16(%rdi), %xmm2
+ pxor 16(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(32bytesin256)
+
+ movdqa 32(%rdi), %xmm2
+ pxor 32(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(48bytesin256)
+
+ movdqa 48(%rdi), %xmm2
+ pxor 48(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(64bytesin256)
+
+ movdqa 64(%rdi), %xmm2
+ pxor 64(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(80bytesin256)
+
+ movdqa 80(%rdi), %xmm2
+ pxor 80(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(96bytesin256)
+
+ movdqa 96(%rdi), %xmm2
+ pxor 96(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(112bytesin256)
+
+ movdqa 112(%rdi), %xmm2
+ pxor 112(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(128bytesin256)
+
+ movdqa 128(%rdi), %xmm2
+ pxor 128(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(144bytesin256)
+
+ movdqa 144(%rdi), %xmm2
+ pxor 144(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(160bytesin256)
+
+ movdqa 160(%rdi), %xmm2
+ pxor 160(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(176bytesin256)
+
+ movdqa 176(%rdi), %xmm2
+ pxor 176(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(192bytesin256)
+
+ movdqa 192(%rdi), %xmm2
+ pxor 192(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(208bytesin256)
+
+ movdqa 208(%rdi), %xmm2
+ pxor 208(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(224bytesin256)
+
+ movdqa 224(%rdi), %xmm2
+ pxor 224(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(240bytesin256)
+
+ movdqa 240(%rdi), %xmm2
+ pxor 240(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(256bytesin256)
+
+ add $256, %rsi
+ add $256, %rdi
+
+ cmp $128, %rdx
+ jae L(less256bytesin2alinged)
+
+ cmp $64, %rdx
+ jae L(less128bytesin2aligned)
+
+ cmp $32, %rdx
+ jb L(less32bytesin256in2alinged)
+
+ movdqa (%rdi), %xmm2
+ pxor (%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(16bytesin256)
+
+ movdqa 16(%rdi), %xmm2
+ pxor 16(%rsi), %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(32bytesin256)
+ sub $32, %rdx
+ add $32, %rdi
+ add $32, %rsi
+L(less32bytesin256in2alinged):
+ add %rdx, %rsi
+ add %rdx, %rdi
+ BRANCH_TO_JMPTBL_ENTRY(L(table_64bytes), %rdx, 4)
+
+ ALIGN (4)
+L(512bytesormorein2aligned):
+#ifdef DATA_CACHE_SIZE_HALF
+ mov $DATA_CACHE_SIZE_HALF, %r8
+#else
+ mov __x86_64_data_cache_size_half(%rip), %r8
+#endif
+ mov %r8, %r9
+ shr $1, %r8
+ add %r9, %r8
+ cmp %r8, %rdx
+ ja L(L2_L3_cache_aglined)
+
+ sub $64, %rdx
+ ALIGN (4)
+L(64bytesormore_loopin2aligned):
+ movdqa (%rdi), %xmm2
+ pxor (%rsi), %xmm2
+ movdqa %xmm2, %xmm1
+
+ movdqa 16(%rdi), %xmm3
+ pxor 16(%rsi), %xmm3
+ por %xmm3, %xmm1
+
+ movdqa 32(%rdi), %xmm4
+ pxor 32(%rsi), %xmm4
+ por %xmm4, %xmm1
+
+ movdqa 48(%rdi), %xmm5
+ pxor 48(%rsi), %xmm5
+ por %xmm5, %xmm1
+
+ ptest %xmm1, %xmm0
+ jnc L(64bytesormore_loop_end)
+ add $64, %rsi
+ add $64, %rdi
+ sub $64, %rdx
+ jae L(64bytesormore_loopin2aligned)
+
+ add $64, %rdx
+ add %rdx, %rsi
+ add %rdx, %rdi
+ BRANCH_TO_JMPTBL_ENTRY(L(table_64bytes), %rdx, 4)
+L(L2_L3_cache_aglined):
+ sub $64, %rdx
+ ALIGN (4)
+L(L2_L3_aligned_128bytes_loop):
+ prefetchnta 0x1c0(%rdi)
+ prefetchnta 0x1c0(%rsi)
+ movdqa (%rdi), %xmm2
+ pxor (%rsi), %xmm2
+ movdqa %xmm2, %xmm1
+
+ movdqa 16(%rdi), %xmm3
+ pxor 16(%rsi), %xmm3
+ por %xmm3, %xmm1
+
+ movdqa 32(%rdi), %xmm4
+ pxor 32(%rsi), %xmm4
+ por %xmm4, %xmm1
+
+ movdqa 48(%rdi), %xmm5
+ pxor 48(%rsi), %xmm5
+ por %xmm5, %xmm1
+
+ ptest %xmm1, %xmm0
+ jnc L(64bytesormore_loop_end)
+ add $64, %rsi
+ add $64, %rdi
+ sub $64, %rdx
+ jae L(L2_L3_aligned_128bytes_loop)
+
+ add $64, %rdx
+ add %rdx, %rsi
+ add %rdx, %rdi
+ BRANCH_TO_JMPTBL_ENTRY(L(table_64bytes), %rdx, 4)
+
+
+ ALIGN (4)
+L(64bytesormore_loop_end):
+ add $16, %rdi
+ add $16, %rsi
+ ptest %xmm2, %xmm0
+ jnc L(16bytes)
+
+ add $16, %rdi
+ add $16, %rsi
+ ptest %xmm3, %xmm0
+ jnc L(16bytes)
+
+ add $16, %rdi
+ add $16, %rsi
+ ptest %xmm4, %xmm0
+ jnc L(16bytes)
+
+ add $16, %rdi
+ add $16, %rsi
+ jmp L(16bytes)
+
+L(256bytesin256):
+ add $256, %rdi
+ add $256, %rsi
+ jmp L(16bytes)
+L(240bytesin256):
+ add $240, %rdi
+ add $240, %rsi
+ jmp L(16bytes)
+L(224bytesin256):
+ add $224, %rdi
+ add $224, %rsi
+ jmp L(16bytes)
+L(208bytesin256):
+ add $208, %rdi
+ add $208, %rsi
+ jmp L(16bytes)
+L(192bytesin256):
+ add $192, %rdi
+ add $192, %rsi
+ jmp L(16bytes)
+L(176bytesin256):
+ add $176, %rdi
+ add $176, %rsi
+ jmp L(16bytes)
+L(160bytesin256):
+ add $160, %rdi
+ add $160, %rsi
+ jmp L(16bytes)
+L(144bytesin256):
+ add $144, %rdi
+ add $144, %rsi
+ jmp L(16bytes)
+L(128bytesin256):
+ add $128, %rdi
+ add $128, %rsi
+ jmp L(16bytes)
+L(112bytesin256):
+ add $112, %rdi
+ add $112, %rsi
+ jmp L(16bytes)
+L(96bytesin256):
+ add $96, %rdi
+ add $96, %rsi
+ jmp L(16bytes)
+L(80bytesin256):
+ add $80, %rdi
+ add $80, %rsi
+ jmp L(16bytes)
+L(64bytesin256):
+ add $64, %rdi
+ add $64, %rsi
+ jmp L(16bytes)
+L(48bytesin256):
+ add $16, %rdi
+ add $16, %rsi
+L(32bytesin256):
+ add $16, %rdi
+ add $16, %rsi
+L(16bytesin256):
+ add $16, %rdi
+ add $16, %rsi
+L(16bytes):
+ mov -16(%rdi), %rax
+ mov -16(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+L(8bytes):
+ mov -8(%rdi), %rax
+ mov -8(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ xor %eax, %eax
+ ret
+
+ ALIGN (4)
+L(12bytes):
+ mov -12(%rdi), %rax
+ mov -12(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+L(4bytes):
+ mov -4(%rsi), %ecx
+ mov -4(%rdi), %eax
+ cmp %eax, %ecx
+ jne L(diffin4bytes)
+L(0bytes):
+ xor %eax, %eax
+ ret
+
+#ifndef USE_AS_WMEMCMP
+/* unreal case for wmemcmp */
+ ALIGN (4)
+L(65bytes):
+ movdqu -65(%rdi), %xmm1
+ movdqu -65(%rsi), %xmm2
+ mov $-65, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(49bytes):
+ movdqu -49(%rdi), %xmm1
+ movdqu -49(%rsi), %xmm2
+ mov $-49, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(33bytes):
+ movdqu -33(%rdi), %xmm1
+ movdqu -33(%rsi), %xmm2
+ mov $-33, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(17bytes):
+ mov -17(%rdi), %rax
+ mov -17(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+L(9bytes):
+ mov -9(%rdi), %rax
+ mov -9(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ movzbl -1(%rdi), %eax
+ movzbl -1(%rsi), %edx
+ sub %edx, %eax
+ ret
+
+ ALIGN (4)
+L(13bytes):
+ mov -13(%rdi), %rax
+ mov -13(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ mov -8(%rdi), %rax
+ mov -8(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ xor %eax, %eax
+ ret
+
+ ALIGN (4)
+L(5bytes):
+ mov -5(%rdi), %eax
+ mov -5(%rsi), %ecx
+ cmp %eax, %ecx
+ jne L(diffin4bytes)
+ movzbl -1(%rdi), %eax
+ movzbl -1(%rsi), %edx
+ sub %edx, %eax
+ ret
+
+ ALIGN (4)
+L(66bytes):
+ movdqu -66(%rdi), %xmm1
+ movdqu -66(%rsi), %xmm2
+ mov $-66, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(50bytes):
+ movdqu -50(%rdi), %xmm1
+ movdqu -50(%rsi), %xmm2
+ mov $-50, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(34bytes):
+ movdqu -34(%rdi), %xmm1
+ movdqu -34(%rsi), %xmm2
+ mov $-34, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(18bytes):
+ mov -18(%rdi), %rax
+ mov -18(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+L(10bytes):
+ mov -10(%rdi), %rax
+ mov -10(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ movzwl -2(%rdi), %eax
+ movzwl -2(%rsi), %ecx
+ cmp %cl, %al
+ jne L(end)
+ and $0xffff, %eax
+ and $0xffff, %ecx
+ sub %ecx, %eax
+ ret
+
+ ALIGN (4)
+L(14bytes):
+ mov -14(%rdi), %rax
+ mov -14(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ mov -8(%rdi), %rax
+ mov -8(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ xor %eax, %eax
+ ret
+
+ ALIGN (4)
+L(6bytes):
+ mov -6(%rdi), %eax
+ mov -6(%rsi), %ecx
+ cmp %eax, %ecx
+ jne L(diffin4bytes)
+L(2bytes):
+ movzwl -2(%rsi), %ecx
+ movzwl -2(%rdi), %eax
+ cmp %cl, %al
+ jne L(end)
+ and $0xffff, %eax
+ and $0xffff, %ecx
+ sub %ecx, %eax
+ ret
+
+ ALIGN (4)
+L(67bytes):
+ movdqu -67(%rdi), %xmm2
+ movdqu -67(%rsi), %xmm1
+ mov $-67, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(51bytes):
+ movdqu -51(%rdi), %xmm2
+ movdqu -51(%rsi), %xmm1
+ mov $-51, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(35bytes):
+ movdqu -35(%rsi), %xmm1
+ movdqu -35(%rdi), %xmm2
+ mov $-35, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(19bytes):
+ mov -19(%rdi), %rax
+ mov -19(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+L(11bytes):
+ mov -11(%rdi), %rax
+ mov -11(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ mov -4(%rdi), %eax
+ mov -4(%rsi), %ecx
+ cmp %eax, %ecx
+ jne L(diffin4bytes)
+ xor %eax, %eax
+ ret
+
+ ALIGN (4)
+L(15bytes):
+ mov -15(%rdi), %rax
+ mov -15(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ mov -8(%rdi), %rax
+ mov -8(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ xor %eax, %eax
+ ret
+
+ ALIGN (4)
+L(7bytes):
+ mov -7(%rdi), %eax
+ mov -7(%rsi), %ecx
+ cmp %eax, %ecx
+ jne L(diffin4bytes)
+ mov -4(%rdi), %eax
+ mov -4(%rsi), %ecx
+ cmp %eax, %ecx
+ jne L(diffin4bytes)
+ xor %eax, %eax
+ ret
+
+ ALIGN (4)
+L(3bytes):
+ movzwl -3(%rdi), %eax
+ movzwl -3(%rsi), %ecx
+ cmp %eax, %ecx
+ jne L(diffin2bytes)
+L(1bytes):
+ movzbl -1(%rdi), %eax
+ movzbl -1(%rsi), %ecx
+ sub %ecx, %eax
+ ret
+#endif
+
+ ALIGN (4)
+L(68bytes):
+ movdqu -68(%rdi), %xmm2
+ movdqu -68(%rsi), %xmm1
+ mov $-68, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(52bytes):
+ movdqu -52(%rdi), %xmm2
+ movdqu -52(%rsi), %xmm1
+ mov $-52, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(36bytes):
+ movdqu -36(%rdi), %xmm2
+ movdqu -36(%rsi), %xmm1
+ mov $-36, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(20bytes):
+ movdqu -20(%rdi), %xmm2
+ movdqu -20(%rsi), %xmm1
+ mov $-20, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+ mov -4(%rdi), %eax
+ mov -4(%rsi), %ecx
+ cmp %eax, %ecx
+ jne L(diffin4bytes)
+ xor %eax, %eax
+ ret
+
+#ifndef USE_AS_WMEMCMP
+/* unreal cases for wmemcmp */
+ ALIGN (4)
+L(69bytes):
+ movdqu -69(%rsi), %xmm1
+ movdqu -69(%rdi), %xmm2
+ mov $-69, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(53bytes):
+ movdqu -53(%rsi), %xmm1
+ movdqu -53(%rdi), %xmm2
+ mov $-53, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(37bytes):
+ movdqu -37(%rsi), %xmm1
+ movdqu -37(%rdi), %xmm2
+ mov $-37, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(21bytes):
+ movdqu -21(%rsi), %xmm1
+ movdqu -21(%rdi), %xmm2
+ mov $-21, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+ mov -8(%rdi), %rax
+ mov -8(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ xor %eax, %eax
+ ret
+
+ ALIGN (4)
+L(70bytes):
+ movdqu -70(%rsi), %xmm1
+ movdqu -70(%rdi), %xmm2
+ mov $-70, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(54bytes):
+ movdqu -54(%rsi), %xmm1
+ movdqu -54(%rdi), %xmm2
+ mov $-54, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(38bytes):
+ movdqu -38(%rsi), %xmm1
+ movdqu -38(%rdi), %xmm2
+ mov $-38, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(22bytes):
+ movdqu -22(%rsi), %xmm1
+ movdqu -22(%rdi), %xmm2
+ mov $-22, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+ mov -8(%rdi), %rax
+ mov -8(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ xor %eax, %eax
+ ret
+
+ ALIGN (4)
+L(71bytes):
+ movdqu -71(%rsi), %xmm1
+ movdqu -71(%rdi), %xmm2
+ mov $-71, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(55bytes):
+ movdqu -55(%rdi), %xmm2
+ movdqu -55(%rsi), %xmm1
+ mov $-55, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(39bytes):
+ movdqu -39(%rdi), %xmm2
+ movdqu -39(%rsi), %xmm1
+ mov $-39, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(23bytes):
+ movdqu -23(%rdi), %xmm2
+ movdqu -23(%rsi), %xmm1
+ mov $-23, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+ mov -8(%rdi), %rax
+ mov -8(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ xor %eax, %eax
+ ret
+#endif
+
+ ALIGN (4)
+L(72bytes):
+ movdqu -72(%rsi), %xmm1
+ movdqu -72(%rdi), %xmm2
+ mov $-72, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(56bytes):
+ movdqu -56(%rdi), %xmm2
+ movdqu -56(%rsi), %xmm1
+ mov $-56, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(40bytes):
+ movdqu -40(%rdi), %xmm2
+ movdqu -40(%rsi), %xmm1
+ mov $-40, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(24bytes):
+ movdqu -24(%rdi), %xmm2
+ movdqu -24(%rsi), %xmm1
+ mov $-24, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+ mov -8(%rdi), %rax
+ mov -8(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ xor %eax, %eax
+ ret
+
+#ifndef USE_AS_WMEMCMP
+/* unreal cases for wmemcmp */
+ ALIGN (4)
+L(73bytes):
+ movdqu -73(%rsi), %xmm1
+ movdqu -73(%rdi), %xmm2
+ mov $-73, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(57bytes):
+ movdqu -57(%rdi), %xmm2
+ movdqu -57(%rsi), %xmm1
+ mov $-57, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(41bytes):
+ movdqu -41(%rdi), %xmm2
+ movdqu -41(%rsi), %xmm1
+ mov $-41, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(25bytes):
+ movdqu -25(%rdi), %xmm2
+ movdqu -25(%rsi), %xmm1
+ mov $-25, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+ mov -9(%rdi), %rax
+ mov -9(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ movzbl -1(%rdi), %eax
+ movzbl -1(%rsi), %ecx
+ sub %ecx, %eax
+ ret
+
+ ALIGN (4)
+L(74bytes):
+ movdqu -74(%rsi), %xmm1
+ movdqu -74(%rdi), %xmm2
+ mov $-74, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(58bytes):
+ movdqu -58(%rdi), %xmm2
+ movdqu -58(%rsi), %xmm1
+ mov $-58, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(42bytes):
+ movdqu -42(%rdi), %xmm2
+ movdqu -42(%rsi), %xmm1
+ mov $-42, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(26bytes):
+ movdqu -26(%rdi), %xmm2
+ movdqu -26(%rsi), %xmm1
+ mov $-26, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+ mov -10(%rdi), %rax
+ mov -10(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ movzwl -2(%rdi), %eax
+ movzwl -2(%rsi), %ecx
+ jmp L(diffin2bytes)
+
+ ALIGN (4)
+L(75bytes):
+ movdqu -75(%rsi), %xmm1
+ movdqu -75(%rdi), %xmm2
+ mov $-75, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(59bytes):
+ movdqu -59(%rdi), %xmm2
+ movdqu -59(%rsi), %xmm1
+ mov $-59, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(43bytes):
+ movdqu -43(%rdi), %xmm2
+ movdqu -43(%rsi), %xmm1
+ mov $-43, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(27bytes):
+ movdqu -27(%rdi), %xmm2
+ movdqu -27(%rsi), %xmm1
+ mov $-27, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+ mov -11(%rdi), %rax
+ mov -11(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ mov -4(%rdi), %eax
+ mov -4(%rsi), %ecx
+ cmp %eax, %ecx
+ jne L(diffin4bytes)
+ xor %eax, %eax
+ ret
+#endif
+ ALIGN (4)
+L(76bytes):
+ movdqu -76(%rsi), %xmm1
+ movdqu -76(%rdi), %xmm2
+ mov $-76, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(60bytes):
+ movdqu -60(%rdi), %xmm2
+ movdqu -60(%rsi), %xmm1
+ mov $-60, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(44bytes):
+ movdqu -44(%rdi), %xmm2
+ movdqu -44(%rsi), %xmm1
+ mov $-44, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(28bytes):
+ movdqu -28(%rdi), %xmm2
+ movdqu -28(%rsi), %xmm1
+ mov $-28, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+ mov -12(%rdi), %rax
+ mov -12(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ mov -4(%rdi), %eax
+ mov -4(%rsi), %ecx
+ cmp %eax, %ecx
+ jne L(diffin4bytes)
+ xor %eax, %eax
+ ret
+
+#ifndef USE_AS_WMEMCMP
+/* unreal cases for wmemcmp */
+ ALIGN (4)
+L(77bytes):
+ movdqu -77(%rsi), %xmm1
+ movdqu -77(%rdi), %xmm2
+ mov $-77, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(61bytes):
+ movdqu -61(%rdi), %xmm2
+ movdqu -61(%rsi), %xmm1
+ mov $-61, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(45bytes):
+ movdqu -45(%rdi), %xmm2
+ movdqu -45(%rsi), %xmm1
+ mov $-45, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(29bytes):
+ movdqu -29(%rdi), %xmm2
+ movdqu -29(%rsi), %xmm1
+ mov $-29, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+
+ mov -13(%rdi), %rax
+ mov -13(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+
+ mov -8(%rdi), %rax
+ mov -8(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ xor %eax, %eax
+ ret
+
+ ALIGN (4)
+L(78bytes):
+ movdqu -78(%rsi), %xmm1
+ movdqu -78(%rdi), %xmm2
+ mov $-78, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(62bytes):
+ movdqu -62(%rdi), %xmm2
+ movdqu -62(%rsi), %xmm1
+ mov $-62, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(46bytes):
+ movdqu -46(%rdi), %xmm2
+ movdqu -46(%rsi), %xmm1
+ mov $-46, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(30bytes):
+ movdqu -30(%rdi), %xmm2
+ movdqu -30(%rsi), %xmm1
+ mov $-30, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+ mov -14(%rdi), %rax
+ mov -14(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ mov -8(%rdi), %rax
+ mov -8(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ xor %eax, %eax
+ ret
+
+ ALIGN (4)
+L(79bytes):
+ movdqu -79(%rsi), %xmm1
+ movdqu -79(%rdi), %xmm2
+ mov $-79, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(63bytes):
+ movdqu -63(%rdi), %xmm2
+ movdqu -63(%rsi), %xmm1
+ mov $-63, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(47bytes):
+ movdqu -47(%rdi), %xmm2
+ movdqu -47(%rsi), %xmm1
+ mov $-47, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(31bytes):
+ movdqu -31(%rdi), %xmm2
+ movdqu -31(%rsi), %xmm1
+ mov $-31, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+ mov -15(%rdi), %rax
+ mov -15(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ mov -8(%rdi), %rax
+ mov -8(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ xor %eax, %eax
+ ret
+#endif
+ ALIGN (4)
+L(64bytes):
+ movdqu -64(%rdi), %xmm2
+ movdqu -64(%rsi), %xmm1
+ mov $-64, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(48bytes):
+ movdqu -48(%rdi), %xmm2
+ movdqu -48(%rsi), %xmm1
+ mov $-48, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+L(32bytes):
+ movdqu -32(%rdi), %xmm2
+ movdqu -32(%rsi), %xmm1
+ mov $-32, %dl
+ pxor %xmm1, %xmm2
+ ptest %xmm2, %xmm0
+ jnc L(less16bytes)
+
+ mov -16(%rdi), %rax
+ mov -16(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+
+ mov -8(%rdi), %rax
+ mov -8(%rsi), %rcx
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ xor %eax, %eax
+ ret
+
+/*
+ * Aligned 8 bytes to avoid 2 branch "taken" in one 16 alinged code block.
+ */
+ ALIGN (3)
+L(less16bytes):
+ movsbq %dl, %rdx
+ mov (%rsi, %rdx), %rcx
+ mov (%rdi, %rdx), %rax
+ cmp %rax, %rcx
+ jne L(diffin8bytes)
+ mov 8(%rsi, %rdx), %rcx
+ mov 8(%rdi, %rdx), %rax
+L(diffin8bytes):
+ cmp %eax, %ecx
+ jne L(diffin4bytes)
+ shr $32, %rcx
+ shr $32, %rax
+
+#ifdef USE_AS_WMEMCMP
+/* for wmemcmp */
+ cmp %eax, %ecx
+ jne L(diffin4bytes)
+ xor %eax, %eax
+ ret
+#endif
+
+L(diffin4bytes):
+#ifndef USE_AS_WMEMCMP
+ cmp %cx, %ax
+ jne L(diffin2bytes)
+ shr $16, %ecx
+ shr $16, %eax
+L(diffin2bytes):
+ cmp %cl, %al
+ jne L(end)
+ and $0xffff, %eax
+ and $0xffff, %ecx
+ sub %ecx, %eax
+ ret
+#else
+
+/* for wmemcmp */
+ mov $1, %eax
+ jl L(nequal_bigger)
+ neg %eax
+ ret
+
+ ALIGN (4)
+L(nequal_bigger):
+ ret
+
+L(unreal_case):
+ xor %eax, %eax
+ ret
+#endif
+
+ ALIGN (4)
+L(end):
+ and $0xff, %eax
+ and $0xff, %ecx
+ sub %ecx, %eax
+ ret
+
+END (MEMCMP)
+
+ .section .rodata.sse4.1,"a",@progbits
+ ALIGN (3)
+#ifndef USE_AS_WMEMCMP
+L(table_64bytes):
+ .int JMPTBL (L(0bytes), L(table_64bytes))
+ .int JMPTBL (L(1bytes), L(table_64bytes))
+ .int JMPTBL (L(2bytes), L(table_64bytes))
+ .int JMPTBL (L(3bytes), L(table_64bytes))
+ .int JMPTBL (L(4bytes), L(table_64bytes))
+ .int JMPTBL (L(5bytes), L(table_64bytes))
+ .int JMPTBL (L(6bytes), L(table_64bytes))
+ .int JMPTBL (L(7bytes), L(table_64bytes))
+ .int JMPTBL (L(8bytes), L(table_64bytes))
+ .int JMPTBL (L(9bytes), L(table_64bytes))
+ .int JMPTBL (L(10bytes), L(table_64bytes))
+ .int JMPTBL (L(11bytes), L(table_64bytes))
+ .int JMPTBL (L(12bytes), L(table_64bytes))
+ .int JMPTBL (L(13bytes), L(table_64bytes))
+ .int JMPTBL (L(14bytes), L(table_64bytes))
+ .int JMPTBL (L(15bytes), L(table_64bytes))
+ .int JMPTBL (L(16bytes), L(table_64bytes))
+ .int JMPTBL (L(17bytes), L(table_64bytes))
+ .int JMPTBL (L(18bytes), L(table_64bytes))
+ .int JMPTBL (L(19bytes), L(table_64bytes))
+ .int JMPTBL (L(20bytes), L(table_64bytes))
+ .int JMPTBL (L(21bytes), L(table_64bytes))
+ .int JMPTBL (L(22bytes), L(table_64bytes))
+ .int JMPTBL (L(23bytes), L(table_64bytes))
+ .int JMPTBL (L(24bytes), L(table_64bytes))
+ .int JMPTBL (L(25bytes), L(table_64bytes))
+ .int JMPTBL (L(26bytes), L(table_64bytes))
+ .int JMPTBL (L(27bytes), L(table_64bytes))
+ .int JMPTBL (L(28bytes), L(table_64bytes))
+ .int JMPTBL (L(29bytes), L(table_64bytes))
+ .int JMPTBL (L(30bytes), L(table_64bytes))
+ .int JMPTBL (L(31bytes), L(table_64bytes))
+ .int JMPTBL (L(32bytes), L(table_64bytes))
+ .int JMPTBL (L(33bytes), L(table_64bytes))
+ .int JMPTBL (L(34bytes), L(table_64bytes))
+ .int JMPTBL (L(35bytes), L(table_64bytes))
+ .int JMPTBL (L(36bytes), L(table_64bytes))
+ .int JMPTBL (L(37bytes), L(table_64bytes))
+ .int JMPTBL (L(38bytes), L(table_64bytes))
+ .int JMPTBL (L(39bytes), L(table_64bytes))
+ .int JMPTBL (L(40bytes), L(table_64bytes))
+ .int JMPTBL (L(41bytes), L(table_64bytes))
+ .int JMPTBL (L(42bytes), L(table_64bytes))
+ .int JMPTBL (L(43bytes), L(table_64bytes))
+ .int JMPTBL (L(44bytes), L(table_64bytes))
+ .int JMPTBL (L(45bytes), L(table_64bytes))
+ .int JMPTBL (L(46bytes), L(table_64bytes))
+ .int JMPTBL (L(47bytes), L(table_64bytes))
+ .int JMPTBL (L(48bytes), L(table_64bytes))
+ .int JMPTBL (L(49bytes), L(table_64bytes))
+ .int JMPTBL (L(50bytes), L(table_64bytes))
+ .int JMPTBL (L(51bytes), L(table_64bytes))
+ .int JMPTBL (L(52bytes), L(table_64bytes))
+ .int JMPTBL (L(53bytes), L(table_64bytes))
+ .int JMPTBL (L(54bytes), L(table_64bytes))
+ .int JMPTBL (L(55bytes), L(table_64bytes))
+ .int JMPTBL (L(56bytes), L(table_64bytes))
+ .int JMPTBL (L(57bytes), L(table_64bytes))
+ .int JMPTBL (L(58bytes), L(table_64bytes))
+ .int JMPTBL (L(59bytes), L(table_64bytes))
+ .int JMPTBL (L(60bytes), L(table_64bytes))
+ .int JMPTBL (L(61bytes), L(table_64bytes))
+ .int JMPTBL (L(62bytes), L(table_64bytes))
+ .int JMPTBL (L(63bytes), L(table_64bytes))
+ .int JMPTBL (L(64bytes), L(table_64bytes))
+ .int JMPTBL (L(65bytes), L(table_64bytes))
+ .int JMPTBL (L(66bytes), L(table_64bytes))
+ .int JMPTBL (L(67bytes), L(table_64bytes))
+ .int JMPTBL (L(68bytes), L(table_64bytes))
+ .int JMPTBL (L(69bytes), L(table_64bytes))
+ .int JMPTBL (L(70bytes), L(table_64bytes))
+ .int JMPTBL (L(71bytes), L(table_64bytes))
+ .int JMPTBL (L(72bytes), L(table_64bytes))
+ .int JMPTBL (L(73bytes), L(table_64bytes))
+ .int JMPTBL (L(74bytes), L(table_64bytes))
+ .int JMPTBL (L(75bytes), L(table_64bytes))
+ .int JMPTBL (L(76bytes), L(table_64bytes))
+ .int JMPTBL (L(77bytes), L(table_64bytes))
+ .int JMPTBL (L(78bytes), L(table_64bytes))
+ .int JMPTBL (L(79bytes), L(table_64bytes))
+#else
+L(table_64bytes):
+ .int JMPTBL (L(0bytes), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(4bytes), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(8bytes), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(12bytes), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(16bytes), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(20bytes), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(24bytes), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(28bytes), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(32bytes), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(36bytes), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(40bytes), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(44bytes), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(48bytes), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(52bytes), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(56bytes), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(60bytes), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(64bytes), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(68bytes), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(72bytes), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(76bytes), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+ .int JMPTBL (L(unreal_case), L(table_64bytes))
+#endif
diff --git a/contrib/bionic-x86_64-string/ssse3-strcmp-slm.S b/contrib/bionic-x86_64-string/ssse3-strcmp-slm.S
new file mode 100644
index 000000000000..e8acd5ba4612
--- /dev/null
+++ b/contrib/bionic-x86_64-string/ssse3-strcmp-slm.S
@@ -0,0 +1,1925 @@
+/*
+Copyright (c) 2014, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef USE_AS_STRNCMP
+/* Since the counter, %r11, is unsigned, we branch to strcmp_exitz
+ if the new counter > the old one or is 0. */
+#define UPDATE_STRNCMP_COUNTER \
+ /* calculate left number to compare */ \
+ lea -16(%rcx, %r11), %r9; \
+ cmp %r9, %r11; \
+ jb L(strcmp_exitz); \
+ test %r9, %r9; \
+ je L(strcmp_exitz); \
+ mov %r9, %r11
+
+#else
+#define UPDATE_STRNCMP_COUNTER
+#ifndef STRCMP
+#define STRCMP strcmp
+#endif
+#endif
+
+#ifndef L
+# define L(label) .L##label
+#endif
+
+#ifndef cfi_startproc
+# define cfi_startproc .cfi_startproc
+#endif
+
+#ifndef cfi_endproc
+# define cfi_endproc .cfi_endproc
+#endif
+
+#ifndef ENTRY
+# define ENTRY(name) \
+ .type name, @function; \
+ .globl name; \
+ .p2align 4; \
+name: \
+ cfi_startproc
+#endif
+
+#ifndef END
+# define END(name) \
+ cfi_endproc; \
+ .size name, .-name
+#endif
+#define RETURN ret
+ .section .text.ssse3,"ax",@progbits
+ENTRY (STRCMP)
+/*
+ * This implementation uses SSE to compare up to 16 bytes at a time.
+ */
+#ifdef USE_AS_STRNCMP
+ test %rdx, %rdx
+ je L(strcmp_exitz)
+ cmp $1, %rdx
+ je L(Byte0)
+ mov %rdx, %r11
+#endif
+ mov %esi, %ecx
+ mov %edi, %eax
+/* Use 64bit AND here to avoid long NOP padding. */
+ and $0x3f, %rcx /* rsi alignment in cache line */
+ and $0x3f, %rax /* rdi alignment in cache line */
+ cmp $0x30, %ecx
+ ja L(crosscache) /* rsi: 16-byte load will cross cache line */
+ cmp $0x30, %eax
+ ja L(crosscache) /* rdi: 16-byte load will cross cache line */
+ movlpd (%rdi), %xmm1
+ movlpd (%rsi), %xmm2
+ movhpd 8(%rdi), %xmm1
+ movhpd 8(%rsi), %xmm2
+ pxor %xmm0, %xmm0 /* clear %xmm0 for null char checks */
+ pcmpeqb %xmm1, %xmm0 /* Any null chars? */
+ pcmpeqb %xmm2, %xmm1 /* compare first 16 bytes for equality */
+ psubb %xmm0, %xmm1 /* packed sub of comparison results*/
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx /* if first 16 bytes are same, edx == 0xffff */
+ jnz L(less16bytes) /* If not, find different value or null char */
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz) /* finish comparision */
+#endif
+ add $16, %rsi /* prepare to search next 16 bytes */
+ add $16, %rdi /* prepare to search next 16 bytes */
+
+ /*
+ * Determine source and destination string offsets from 16-byte alignment.
+ * Use relative offset difference between the two to determine which case
+ * below to use.
+ */
+ .p2align 4
+L(crosscache):
+ and $0xfffffffffffffff0, %rsi /* force %rsi is 16 byte aligned */
+ and $0xfffffffffffffff0, %rdi /* force %rdi is 16 byte aligned */
+ mov $0xffff, %edx /* for equivalent offset */
+ xor %r8d, %r8d
+ and $0xf, %ecx /* offset of rsi */
+ and $0xf, %eax /* offset of rdi */
+ cmp %eax, %ecx
+ je L(ashr_0) /* rsi and rdi relative offset same */
+ ja L(bigger)
+ mov %edx, %r8d /* r8d is offset flag for exit tail */
+ xchg %ecx, %eax
+ xchg %rsi, %rdi
+L(bigger):
+ lea 15(%rax), %r9
+ sub %rcx, %r9
+ lea L(unaligned_table)(%rip), %r10
+ movslq (%r10, %r9,4), %r9
+ lea (%r10, %r9), %r10
+ jmp *%r10 /* jump to corresponding case */
+
+/*
+ * The following cases will be handled by ashr_0
+ * rcx(offset of rsi) rax(offset of rdi) relative offset corresponding case
+ * n(0~15) n(0~15) 15(15+ n-n) ashr_0
+ */
+ .p2align 4
+L(ashr_0):
+
+ movdqa (%rsi), %xmm1
+ pxor %xmm0, %xmm0 /* clear %xmm0 for null char check */
+ pcmpeqb %xmm1, %xmm0 /* Any null chars? */
+ pcmpeqb (%rdi), %xmm1 /* compare 16 bytes for equality */
+ psubb %xmm0, %xmm1 /* packed sub of comparison results*/
+ pmovmskb %xmm1, %r9d
+ shr %cl, %edx /* adjust 0xffff for offset */
+ shr %cl, %r9d /* adjust for 16-byte offset */
+ sub %r9d, %edx
+ /*
+ * edx must be the same with r9d if in left byte (16-rcx) is equal to
+ * the start from (16-rax) and no null char was seen.
+ */
+ jne L(less32bytes) /* mismatch or null char */
+ UPDATE_STRNCMP_COUNTER
+ mov $16, %rcx
+ mov $16, %r9
+ pxor %xmm0, %xmm0 /* clear xmm0, may have changed above */
+
+ /*
+ * Now both strings are aligned at 16-byte boundary. Loop over strings
+ * checking 32-bytes per iteration.
+ */
+ .p2align 4
+L(loop_ashr_0):
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit) /* mismatch or null char seen */
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+ add $16, %rcx
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+ add $16, %rcx
+ jmp L(loop_ashr_0)
+
+/*
+ * The following cases will be handled by ashr_1
+ * rcx(offset of rsi) rax(offset of rdi) relative offset corresponding case
+ * n(15) n -15 0(15 +(n-15) - n) ashr_1
+ */
+ .p2align 4
+L(ashr_1):
+ pxor %xmm0, %xmm0
+ movdqa (%rdi), %xmm2
+ movdqa (%rsi), %xmm1
+ pcmpeqb %xmm1, %xmm0 /* Any null chars? */
+ pslldq $15, %xmm2 /* shift first string to align with second */
+ pcmpeqb %xmm1, %xmm2 /* compare 16 bytes for equality */
+ psubb %xmm0, %xmm2 /* packed sub of comparison results*/
+ pmovmskb %xmm2, %r9d
+ shr %cl, %edx /* adjust 0xffff for offset */
+ shr %cl, %r9d /* adjust for 16-byte offset */
+ sub %r9d, %edx
+ jnz L(less32bytes) /* mismatch or null char seen */
+ movdqa (%rdi), %xmm3
+ UPDATE_STRNCMP_COUNTER
+
+ pxor %xmm0, %xmm0
+ mov $16, %rcx /* index for loads*/
+ mov $1, %r9d /* byte position left over from less32bytes case */
+ /*
+ * Setup %r10 value allows us to detect crossing a page boundary.
+ * When %r10 goes positive we have crossed a page boundary and
+ * need to do a nibble.
+ */
+ lea 1(%rdi), %r10
+ and $0xfff, %r10 /* offset into 4K page */
+ sub $0x1000, %r10 /* subtract 4K pagesize */
+
+ .p2align 4
+L(loop_ashr_1):
+ add $16, %r10
+ jg L(nibble_ashr_1) /* cross page boundary */
+
+L(gobble_ashr_1):
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4 /* store for next cycle */
+
+ palignr $1, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+
+ add $16, %r10
+ jg L(nibble_ashr_1) /* cross page boundary */
+
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4 /* store for next cycle */
+
+ palignr $1, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+ jmp L(loop_ashr_1)
+
+ /*
+ * Nibble avoids loads across page boundary. This is to avoid a potential
+ * access into unmapped memory.
+ */
+ .p2align 4
+L(nibble_ashr_1):
+ pcmpeqb %xmm3, %xmm0 /* check nibble for null char*/
+ pmovmskb %xmm0, %edx
+ test $0xfffe, %edx
+ jnz L(ashr_1_exittail) /* find null char*/
+
+#ifdef USE_AS_STRNCMP
+ cmp $14, %r11
+ jbe L(ashr_1_exittail)
+#endif
+
+ pxor %xmm0, %xmm0
+ sub $0x1000, %r10 /* substract 4K from %r10 */
+ jmp L(gobble_ashr_1)
+
+ /*
+ * Once find null char, determine if there is a string mismatch
+ * before the null char.
+ */
+ .p2align 4
+L(ashr_1_exittail):
+ movdqa (%rsi, %rcx), %xmm1
+ psrldq $1, %xmm0
+ psrldq $1, %xmm3
+ jmp L(aftertail)
+
+/*
+ * The following cases will be handled by ashr_2
+ * rcx(offset of rsi) rax(offset of rdi) relative offset corresponding case
+ * n(14~15) n -14 1(15 +(n-14) - n) ashr_2
+ */
+ .p2align 4
+L(ashr_2):
+ pxor %xmm0, %xmm0
+ movdqa (%rdi), %xmm2
+ movdqa (%rsi), %xmm1
+ pcmpeqb %xmm1, %xmm0
+ pslldq $14, %xmm2
+ pcmpeqb %xmm1, %xmm2
+ psubb %xmm0, %xmm2
+ pmovmskb %xmm2, %r9d
+ shr %cl, %edx
+ shr %cl, %r9d
+ sub %r9d, %edx
+ jnz L(less32bytes)
+ movdqa (%rdi), %xmm3
+ UPDATE_STRNCMP_COUNTER
+
+ pxor %xmm0, %xmm0
+ mov $16, %rcx /* index for loads */
+ mov $2, %r9d /* byte position left over from less32bytes case */
+ /*
+ * Setup %r10 value allows us to detect crossing a page boundary.
+ * When %r10 goes positive we have crossed a page boundary and
+ * need to do a nibble.
+ */
+ lea 2(%rdi), %r10
+ and $0xfff, %r10 /* offset into 4K page */
+ sub $0x1000, %r10 /* subtract 4K pagesize */
+
+ .p2align 4
+L(loop_ashr_2):
+ add $16, %r10
+ jg L(nibble_ashr_2)
+
+L(gobble_ashr_2):
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $2, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+
+ add $16, %r10
+ jg L(nibble_ashr_2) /* cross page boundary */
+
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $2, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+ jmp L(loop_ashr_2)
+
+ .p2align 4
+L(nibble_ashr_2):
+ pcmpeqb %xmm3, %xmm0 /* check nibble for null char */
+ pmovmskb %xmm0, %edx
+ test $0xfffc, %edx
+ jnz L(ashr_2_exittail)
+
+#ifdef USE_AS_STRNCMP
+ cmp $13, %r11
+ jbe L(ashr_2_exittail)
+#endif
+
+ pxor %xmm0, %xmm0
+ sub $0x1000, %r10
+ jmp L(gobble_ashr_2)
+
+ .p2align 4
+L(ashr_2_exittail):
+ movdqa (%rsi, %rcx), %xmm1
+ psrldq $2, %xmm0
+ psrldq $2, %xmm3
+ jmp L(aftertail)
+
+/*
+ * The following cases will be handled by ashr_3
+ * rcx(offset of rsi) rax(offset of rdi) relative offset corresponding case
+ * n(13~15) n -13 2(15 +(n-13) - n) ashr_3
+ */
+ .p2align 4
+L(ashr_3):
+ pxor %xmm0, %xmm0
+ movdqa (%rdi), %xmm2
+ movdqa (%rsi), %xmm1
+ pcmpeqb %xmm1, %xmm0
+ pslldq $13, %xmm2
+ pcmpeqb %xmm1, %xmm2
+ psubb %xmm0, %xmm2
+ pmovmskb %xmm2, %r9d
+ shr %cl, %edx
+ shr %cl, %r9d
+ sub %r9d, %edx
+ jnz L(less32bytes)
+ movdqa (%rdi), %xmm3
+
+ UPDATE_STRNCMP_COUNTER
+
+ pxor %xmm0, %xmm0
+ mov $16, %rcx /* index for loads */
+ mov $3, %r9d /* byte position left over from less32bytes case */
+ /*
+ * Setup %r10 value allows us to detect crossing a page boundary.
+ * When %r10 goes positive we have crossed a page boundary and
+ * need to do a nibble.
+ */
+ lea 3(%rdi), %r10
+ and $0xfff, %r10 /* offset into 4K page */
+ sub $0x1000, %r10 /* subtract 4K pagesize */
+
+ .p2align 4
+L(loop_ashr_3):
+ add $16, %r10
+ jg L(nibble_ashr_3)
+
+L(gobble_ashr_3):
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $3, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+
+ add $16, %r10
+ jg L(nibble_ashr_3) /* cross page boundary */
+
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $3, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+ jmp L(loop_ashr_3)
+
+ .p2align 4
+L(nibble_ashr_3):
+ pcmpeqb %xmm3, %xmm0 /* check nibble for null char */
+ pmovmskb %xmm0, %edx
+ test $0xfff8, %edx
+ jnz L(ashr_3_exittail)
+
+#ifdef USE_AS_STRNCMP
+ cmp $12, %r11
+ jbe L(ashr_3_exittail)
+#endif
+
+ pxor %xmm0, %xmm0
+ sub $0x1000, %r10
+ jmp L(gobble_ashr_3)
+
+ .p2align 4
+L(ashr_3_exittail):
+ movdqa (%rsi, %rcx), %xmm1
+ psrldq $3, %xmm0
+ psrldq $3, %xmm3
+ jmp L(aftertail)
+
+/*
+ * The following cases will be handled by ashr_4
+ * rcx(offset of rsi) rax(offset of rdi) relative offset corresponding case
+ * n(12~15) n -12 3(15 +(n-12) - n) ashr_4
+ */
+ .p2align 4
+L(ashr_4):
+ pxor %xmm0, %xmm0
+ movdqa (%rdi), %xmm2
+ movdqa (%rsi), %xmm1
+ pcmpeqb %xmm1, %xmm0
+ pslldq $12, %xmm2
+ pcmpeqb %xmm1, %xmm2
+ psubb %xmm0, %xmm2
+ pmovmskb %xmm2, %r9d
+ shr %cl, %edx
+ shr %cl, %r9d
+ sub %r9d, %edx
+ jnz L(less32bytes)
+ movdqa (%rdi), %xmm3
+
+ UPDATE_STRNCMP_COUNTER
+
+ pxor %xmm0, %xmm0
+ mov $16, %rcx /* index for loads */
+ mov $4, %r9d /* byte position left over from less32bytes case */
+ /*
+ * Setup %r10 value allows us to detect crossing a page boundary.
+ * When %r10 goes positive we have crossed a page boundary and
+ * need to do a nibble.
+ */
+ lea 4(%rdi), %r10
+ and $0xfff, %r10 /* offset into 4K page */
+ sub $0x1000, %r10 /* subtract 4K pagesize */
+
+ .p2align 4
+L(loop_ashr_4):
+ add $16, %r10
+ jg L(nibble_ashr_4)
+
+L(gobble_ashr_4):
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $4, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+
+ add $16, %r10
+ jg L(nibble_ashr_4) /* cross page boundary */
+
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $4, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+ jmp L(loop_ashr_4)
+
+ .p2align 4
+L(nibble_ashr_4):
+ pcmpeqb %xmm3, %xmm0 /* check nibble for null char */
+ pmovmskb %xmm0, %edx
+ test $0xfff0, %edx
+ jnz L(ashr_4_exittail)
+
+#ifdef USE_AS_STRNCMP
+ cmp $11, %r11
+ jbe L(ashr_4_exittail)
+#endif
+
+ pxor %xmm0, %xmm0
+ sub $0x1000, %r10
+ jmp L(gobble_ashr_4)
+
+ .p2align 4
+L(ashr_4_exittail):
+ movdqa (%rsi, %rcx), %xmm1
+ psrldq $4, %xmm0
+ psrldq $4, %xmm3
+ jmp L(aftertail)
+
+/*
+ * The following cases will be handled by ashr_5
+ * rcx(offset of rsi) rax(offset of rdi) relative offset corresponding case
+ * n(11~15) n - 11 4(15 +(n-11) - n) ashr_5
+ */
+ .p2align 4
+L(ashr_5):
+ pxor %xmm0, %xmm0
+ movdqa (%rdi), %xmm2
+ movdqa (%rsi), %xmm1
+ pcmpeqb %xmm1, %xmm0
+ pslldq $11, %xmm2
+ pcmpeqb %xmm1, %xmm2
+ psubb %xmm0, %xmm2
+ pmovmskb %xmm2, %r9d
+ shr %cl, %edx
+ shr %cl, %r9d
+ sub %r9d, %edx
+ jnz L(less32bytes)
+ movdqa (%rdi), %xmm3
+
+ UPDATE_STRNCMP_COUNTER
+
+ pxor %xmm0, %xmm0
+ mov $16, %rcx /* index for loads */
+ mov $5, %r9d /* byte position left over from less32bytes case */
+ /*
+ * Setup %r10 value allows us to detect crossing a page boundary.
+ * When %r10 goes positive we have crossed a page boundary and
+ * need to do a nibble.
+ */
+ lea 5(%rdi), %r10
+ and $0xfff, %r10 /* offset into 4K page */
+ sub $0x1000, %r10 /* subtract 4K pagesize */
+
+ .p2align 4
+L(loop_ashr_5):
+ add $16, %r10
+ jg L(nibble_ashr_5)
+
+L(gobble_ashr_5):
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $5, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+
+ add $16, %r10
+ jg L(nibble_ashr_5) /* cross page boundary */
+
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $5, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+ jmp L(loop_ashr_5)
+
+ .p2align 4
+L(nibble_ashr_5):
+ pcmpeqb %xmm3, %xmm0 /* check nibble for null char */
+ pmovmskb %xmm0, %edx
+ test $0xffe0, %edx
+ jnz L(ashr_5_exittail)
+
+#ifdef USE_AS_STRNCMP
+ cmp $10, %r11
+ jbe L(ashr_5_exittail)
+#endif
+
+ pxor %xmm0, %xmm0
+ sub $0x1000, %r10
+ jmp L(gobble_ashr_5)
+
+ .p2align 4
+L(ashr_5_exittail):
+ movdqa (%rsi, %rcx), %xmm1
+ psrldq $5, %xmm0
+ psrldq $5, %xmm3
+ jmp L(aftertail)
+
+/*
+ * The following cases will be handled by ashr_6
+ * rcx(offset of rsi) rax(offset of rdi) relative offset corresponding case
+ * n(10~15) n - 10 5(15 +(n-10) - n) ashr_6
+ */
+ .p2align 4
+L(ashr_6):
+ pxor %xmm0, %xmm0
+ movdqa (%rdi), %xmm2
+ movdqa (%rsi), %xmm1
+ pcmpeqb %xmm1, %xmm0
+ pslldq $10, %xmm2
+ pcmpeqb %xmm1, %xmm2
+ psubb %xmm0, %xmm2
+ pmovmskb %xmm2, %r9d
+ shr %cl, %edx
+ shr %cl, %r9d
+ sub %r9d, %edx
+ jnz L(less32bytes)
+ movdqa (%rdi), %xmm3
+
+ UPDATE_STRNCMP_COUNTER
+
+ pxor %xmm0, %xmm0
+ mov $16, %rcx /* index for loads */
+ mov $6, %r9d /* byte position left over from less32bytes case */
+ /*
+ * Setup %r10 value allows us to detect crossing a page boundary.
+ * When %r10 goes positive we have crossed a page boundary and
+ * need to do a nibble.
+ */
+ lea 6(%rdi), %r10
+ and $0xfff, %r10 /* offset into 4K page */
+ sub $0x1000, %r10 /* subtract 4K pagesize */
+
+ .p2align 4
+L(loop_ashr_6):
+ add $16, %r10
+ jg L(nibble_ashr_6)
+
+L(gobble_ashr_6):
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $6, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+
+ add $16, %r10
+ jg L(nibble_ashr_6) /* cross page boundary */
+
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $6, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+ jmp L(loop_ashr_6)
+
+ .p2align 4
+L(nibble_ashr_6):
+ pcmpeqb %xmm3, %xmm0 /* check nibble for null char */
+ pmovmskb %xmm0, %edx
+ test $0xffc0, %edx
+ jnz L(ashr_6_exittail)
+
+#ifdef USE_AS_STRNCMP
+ cmp $9, %r11
+ jbe L(ashr_6_exittail)
+#endif
+
+ pxor %xmm0, %xmm0
+ sub $0x1000, %r10
+ jmp L(gobble_ashr_6)
+
+ .p2align 4
+L(ashr_6_exittail):
+ movdqa (%rsi, %rcx), %xmm1
+ psrldq $6, %xmm0
+ psrldq $6, %xmm3
+ jmp L(aftertail)
+
+/*
+ * The following cases will be handled by ashr_7
+ * rcx(offset of rsi) rax(offset of rdi) relative offset corresponding case
+ * n(9~15) n - 9 6(15 +(n - 9) - n) ashr_7
+ */
+ .p2align 4
+L(ashr_7):
+ pxor %xmm0, %xmm0
+ movdqa (%rdi), %xmm2
+ movdqa (%rsi), %xmm1
+ pcmpeqb %xmm1, %xmm0
+ pslldq $9, %xmm2
+ pcmpeqb %xmm1, %xmm2
+ psubb %xmm0, %xmm2
+ pmovmskb %xmm2, %r9d
+ shr %cl, %edx
+ shr %cl, %r9d
+ sub %r9d, %edx
+ jnz L(less32bytes)
+ movdqa (%rdi), %xmm3
+
+ UPDATE_STRNCMP_COUNTER
+
+ pxor %xmm0, %xmm0
+ mov $16, %rcx /* index for loads */
+ mov $7, %r9d /* byte position left over from less32bytes case */
+ /*
+ * Setup %r10 value allows us to detect crossing a page boundary.
+ * When %r10 goes positive we have crossed a page boundary and
+ * need to do a nibble.
+ */
+ lea 7(%rdi), %r10
+ and $0xfff, %r10 /* offset into 4K page */
+ sub $0x1000, %r10 /* subtract 4K pagesize */
+
+ .p2align 4
+L(loop_ashr_7):
+ add $16, %r10
+ jg L(nibble_ashr_7)
+
+L(gobble_ashr_7):
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $7, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+
+ add $16, %r10
+ jg L(nibble_ashr_7) /* cross page boundary */
+
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $7, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+ jmp L(loop_ashr_7)
+
+ .p2align 4
+L(nibble_ashr_7):
+ pcmpeqb %xmm3, %xmm0 /* check nibble for null char */
+ pmovmskb %xmm0, %edx
+ test $0xff80, %edx
+ jnz L(ashr_7_exittail)
+
+#ifdef USE_AS_STRNCMP
+ cmp $8, %r11
+ jbe L(ashr_7_exittail)
+#endif
+
+ pxor %xmm0, %xmm0
+ sub $0x1000, %r10
+ jmp L(gobble_ashr_7)
+
+ .p2align 4
+L(ashr_7_exittail):
+ movdqa (%rsi, %rcx), %xmm1
+ psrldq $7, %xmm0
+ psrldq $7, %xmm3
+ jmp L(aftertail)
+
+/*
+ * The following cases will be handled by ashr_8
+ * rcx(offset of rsi) rax(offset of rdi) relative offset corresponding case
+ * n(8~15) n - 8 7(15 +(n - 8) - n) ashr_8
+ */
+ .p2align 4
+L(ashr_8):
+ pxor %xmm0, %xmm0
+ movdqa (%rdi), %xmm2
+ movdqa (%rsi), %xmm1
+ pcmpeqb %xmm1, %xmm0
+ pslldq $8, %xmm2
+ pcmpeqb %xmm1, %xmm2
+ psubb %xmm0, %xmm2
+ pmovmskb %xmm2, %r9d
+ shr %cl, %edx
+ shr %cl, %r9d
+ sub %r9d, %edx
+ jnz L(less32bytes)
+ movdqa (%rdi), %xmm3
+
+ UPDATE_STRNCMP_COUNTER
+
+ pxor %xmm0, %xmm0
+ mov $16, %rcx /* index for loads */
+ mov $8, %r9d /* byte position left over from less32bytes case */
+ /*
+ * Setup %r10 value allows us to detect crossing a page boundary.
+ * When %r10 goes positive we have crossed a page boundary and
+ * need to do a nibble.
+ */
+ lea 8(%rdi), %r10
+ and $0xfff, %r10 /* offset into 4K page */
+ sub $0x1000, %r10 /* subtract 4K pagesize */
+
+ .p2align 4
+L(loop_ashr_8):
+ add $16, %r10
+ jg L(nibble_ashr_8)
+
+L(gobble_ashr_8):
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $8, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+
+ add $16, %r10
+ jg L(nibble_ashr_8) /* cross page boundary */
+
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $8, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+ jmp L(loop_ashr_8)
+
+ .p2align 4
+L(nibble_ashr_8):
+ pcmpeqb %xmm3, %xmm0 /* check nibble for null char */
+ pmovmskb %xmm0, %edx
+ test $0xff00, %edx
+ jnz L(ashr_8_exittail)
+
+#ifdef USE_AS_STRNCMP
+ cmp $7, %r11
+ jbe L(ashr_8_exittail)
+#endif
+
+ pxor %xmm0, %xmm0
+ sub $0x1000, %r10
+ jmp L(gobble_ashr_8)
+
+ .p2align 4
+L(ashr_8_exittail):
+ movdqa (%rsi, %rcx), %xmm1
+ psrldq $8, %xmm0
+ psrldq $8, %xmm3
+ jmp L(aftertail)
+
+/*
+ * The following cases will be handled by ashr_9
+ * rcx(offset of rsi) rax(offset of rdi) relative offset corresponding case
+ * n(7~15) n - 7 8(15 +(n - 7) - n) ashr_9
+ */
+ .p2align 4
+L(ashr_9):
+ pxor %xmm0, %xmm0
+ movdqa (%rdi), %xmm2
+ movdqa (%rsi), %xmm1
+ pcmpeqb %xmm1, %xmm0
+ pslldq $7, %xmm2
+ pcmpeqb %xmm1, %xmm2
+ psubb %xmm0, %xmm2
+ pmovmskb %xmm2, %r9d
+ shr %cl, %edx
+ shr %cl, %r9d
+ sub %r9d, %edx
+ jnz L(less32bytes)
+ movdqa (%rdi), %xmm3
+
+ UPDATE_STRNCMP_COUNTER
+
+ pxor %xmm0, %xmm0
+ mov $16, %rcx /* index for loads */
+ mov $9, %r9d /* byte position left over from less32bytes case */
+ /*
+ * Setup %r10 value allows us to detect crossing a page boundary.
+ * When %r10 goes positive we have crossed a page boundary and
+ * need to do a nibble.
+ */
+ lea 9(%rdi), %r10
+ and $0xfff, %r10 /* offset into 4K page */
+ sub $0x1000, %r10 /* subtract 4K pagesize */
+
+ .p2align 4
+L(loop_ashr_9):
+ add $16, %r10
+ jg L(nibble_ashr_9)
+
+L(gobble_ashr_9):
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $9, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+
+ add $16, %r10
+ jg L(nibble_ashr_9) /* cross page boundary */
+
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $9, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3 /* store for next cycle */
+ jmp L(loop_ashr_9)
+
+ .p2align 4
+L(nibble_ashr_9):
+ pcmpeqb %xmm3, %xmm0 /* check nibble for null char */
+ pmovmskb %xmm0, %edx
+ test $0xfe00, %edx
+ jnz L(ashr_9_exittail)
+
+#ifdef USE_AS_STRNCMP
+ cmp $6, %r11
+ jbe L(ashr_9_exittail)
+#endif
+
+ pxor %xmm0, %xmm0
+ sub $0x1000, %r10
+ jmp L(gobble_ashr_9)
+
+ .p2align 4
+L(ashr_9_exittail):
+ movdqa (%rsi, %rcx), %xmm1
+ psrldq $9, %xmm0
+ psrldq $9, %xmm3
+ jmp L(aftertail)
+
+/*
+ * The following cases will be handled by ashr_10
+ * rcx(offset of rsi) rax(offset of rdi) relative offset corresponding case
+ * n(6~15) n - 6 9(15 +(n - 6) - n) ashr_10
+ */
+ .p2align 4
+L(ashr_10):
+ pxor %xmm0, %xmm0
+ movdqa (%rdi), %xmm2
+ movdqa (%rsi), %xmm1
+ pcmpeqb %xmm1, %xmm0
+ pslldq $6, %xmm2
+ pcmpeqb %xmm1, %xmm2
+ psubb %xmm0, %xmm2
+ pmovmskb %xmm2, %r9d
+ shr %cl, %edx
+ shr %cl, %r9d
+ sub %r9d, %edx
+ jnz L(less32bytes)
+ movdqa (%rdi), %xmm3
+
+ UPDATE_STRNCMP_COUNTER
+
+ pxor %xmm0, %xmm0
+ mov $16, %rcx /* index for loads */
+ mov $10, %r9d /* byte position left over from less32bytes case */
+ /*
+ * Setup %r10 value allows us to detect crossing a page boundary.
+ * When %r10 goes positive we have crossed a page boundary and
+ * need to do a nibble.
+ */
+ lea 10(%rdi), %r10
+ and $0xfff, %r10 /* offset into 4K page */
+ sub $0x1000, %r10 /* subtract 4K pagesize */
+
+ .p2align 4
+L(loop_ashr_10):
+ add $16, %r10
+ jg L(nibble_ashr_10)
+
+L(gobble_ashr_10):
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $10, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+
+ add $16, %r10
+ jg L(nibble_ashr_10) /* cross page boundary */
+
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $10, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+ jmp L(loop_ashr_10)
+
+ .p2align 4
+L(nibble_ashr_10):
+ pcmpeqb %xmm3, %xmm0 /* check nibble for null char */
+ pmovmskb %xmm0, %edx
+ test $0xfc00, %edx
+ jnz L(ashr_10_exittail)
+
+#ifdef USE_AS_STRNCMP
+ cmp $5, %r11
+ jbe L(ashr_10_exittail)
+#endif
+
+ pxor %xmm0, %xmm0
+ sub $0x1000, %r10
+ jmp L(gobble_ashr_10)
+
+ .p2align 4
+L(ashr_10_exittail):
+ movdqa (%rsi, %rcx), %xmm1
+ psrldq $10, %xmm0
+ psrldq $10, %xmm3
+ jmp L(aftertail)
+
+/*
+ * The following cases will be handled by ashr_11
+ * rcx(offset of rsi) rax(offset of rdi) relative offset corresponding case
+ * n(5~15) n - 5 10(15 +(n - 5) - n) ashr_11
+ */
+ .p2align 4
+L(ashr_11):
+ pxor %xmm0, %xmm0
+ movdqa (%rdi), %xmm2
+ movdqa (%rsi), %xmm1
+ pcmpeqb %xmm1, %xmm0
+ pslldq $5, %xmm2
+ pcmpeqb %xmm1, %xmm2
+ psubb %xmm0, %xmm2
+ pmovmskb %xmm2, %r9d
+ shr %cl, %edx
+ shr %cl, %r9d
+ sub %r9d, %edx
+ jnz L(less32bytes)
+ movdqa (%rdi), %xmm3
+
+ UPDATE_STRNCMP_COUNTER
+
+ pxor %xmm0, %xmm0
+ mov $16, %rcx /* index for loads */
+ mov $11, %r9d /* byte position left over from less32bytes case */
+ /*
+ * Setup %r10 value allows us to detect crossing a page boundary.
+ * When %r10 goes positive we have crossed a page boundary and
+ * need to do a nibble.
+ */
+ lea 11(%rdi), %r10
+ and $0xfff, %r10 /* offset into 4K page */
+ sub $0x1000, %r10 /* subtract 4K pagesize */
+
+ .p2align 4
+L(loop_ashr_11):
+ add $16, %r10
+ jg L(nibble_ashr_11)
+
+L(gobble_ashr_11):
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $11, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+
+ add $16, %r10
+ jg L(nibble_ashr_11) /* cross page boundary */
+
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $11, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+ jmp L(loop_ashr_11)
+
+ .p2align 4
+L(nibble_ashr_11):
+ pcmpeqb %xmm3, %xmm0 /* check nibble for null char */
+ pmovmskb %xmm0, %edx
+ test $0xf800, %edx
+ jnz L(ashr_11_exittail)
+
+#ifdef USE_AS_STRNCMP
+ cmp $4, %r11
+ jbe L(ashr_11_exittail)
+#endif
+
+ pxor %xmm0, %xmm0
+ sub $0x1000, %r10
+ jmp L(gobble_ashr_11)
+
+ .p2align 4
+L(ashr_11_exittail):
+ movdqa (%rsi, %rcx), %xmm1
+ psrldq $11, %xmm0
+ psrldq $11, %xmm3
+ jmp L(aftertail)
+
+/*
+ * The following cases will be handled by ashr_12
+ * rcx(offset of rsi) rax(offset of rdi) relative offset corresponding case
+ * n(4~15) n - 4 11(15 +(n - 4) - n) ashr_12
+ */
+ .p2align 4
+L(ashr_12):
+ pxor %xmm0, %xmm0
+ movdqa (%rdi), %xmm2
+ movdqa (%rsi), %xmm1
+ pcmpeqb %xmm1, %xmm0
+ pslldq $4, %xmm2
+ pcmpeqb %xmm1, %xmm2
+ psubb %xmm0, %xmm2
+ pmovmskb %xmm2, %r9d
+ shr %cl, %edx
+ shr %cl, %r9d
+ sub %r9d, %edx
+ jnz L(less32bytes)
+ movdqa (%rdi), %xmm3
+
+ UPDATE_STRNCMP_COUNTER
+
+ pxor %xmm0, %xmm0
+ mov $16, %rcx /* index for loads */
+ mov $12, %r9d /* byte position left over from less32bytes case */
+ /*
+ * Setup %r10 value allows us to detect crossing a page boundary.
+ * When %r10 goes positive we have crossed a page boundary and
+ * need to do a nibble.
+ */
+ lea 12(%rdi), %r10
+ and $0xfff, %r10 /* offset into 4K page */
+ sub $0x1000, %r10 /* subtract 4K pagesize */
+
+ .p2align 4
+L(loop_ashr_12):
+ add $16, %r10
+ jg L(nibble_ashr_12)
+
+L(gobble_ashr_12):
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $12, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+
+ add $16, %r10
+ jg L(nibble_ashr_12) /* cross page boundary */
+
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $12, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+ jmp L(loop_ashr_12)
+
+ .p2align 4
+L(nibble_ashr_12):
+ pcmpeqb %xmm3, %xmm0 /* check nibble for null char */
+ pmovmskb %xmm0, %edx
+ test $0xf000, %edx
+ jnz L(ashr_12_exittail)
+
+#ifdef USE_AS_STRNCMP
+ cmp $3, %r11
+ jbe L(ashr_12_exittail)
+#endif
+
+ pxor %xmm0, %xmm0
+ sub $0x1000, %r10
+ jmp L(gobble_ashr_12)
+
+ .p2align 4
+L(ashr_12_exittail):
+ movdqa (%rsi, %rcx), %xmm1
+ psrldq $12, %xmm0
+ psrldq $12, %xmm3
+ jmp L(aftertail)
+
+/*
+ * The following cases will be handled by ashr_13
+ * rcx(offset of rsi) rax(offset of rdi) relative offset corresponding case
+ * n(3~15) n - 3 12(15 +(n - 3) - n) ashr_13
+ */
+ .p2align 4
+L(ashr_13):
+ pxor %xmm0, %xmm0
+ movdqa (%rdi), %xmm2
+ movdqa (%rsi), %xmm1
+ pcmpeqb %xmm1, %xmm0
+ pslldq $3, %xmm2
+ pcmpeqb %xmm1, %xmm2
+ psubb %xmm0, %xmm2
+ pmovmskb %xmm2, %r9d
+ shr %cl, %edx
+ shr %cl, %r9d
+ sub %r9d, %edx
+ jnz L(less32bytes)
+ movdqa (%rdi), %xmm3
+
+ UPDATE_STRNCMP_COUNTER
+
+ pxor %xmm0, %xmm0
+ mov $16, %rcx /* index for loads */
+ mov $13, %r9d /* byte position left over from less32bytes case */
+ /*
+ * Setup %r10 value allows us to detect crossing a page boundary.
+ * When %r10 goes positive we have crossed a page boundary and
+ * need to do a nibble.
+ */
+ lea 13(%rdi), %r10
+ and $0xfff, %r10 /* offset into 4K page */
+ sub $0x1000, %r10 /* subtract 4K pagesize */
+
+ .p2align 4
+L(loop_ashr_13):
+ add $16, %r10
+ jg L(nibble_ashr_13)
+
+L(gobble_ashr_13):
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $13, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+
+ add $16, %r10
+ jg L(nibble_ashr_13) /* cross page boundary */
+
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $13, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+ jmp L(loop_ashr_13)
+
+ .p2align 4
+L(nibble_ashr_13):
+ pcmpeqb %xmm3, %xmm0 /* check nibble for null char */
+ pmovmskb %xmm0, %edx
+ test $0xe000, %edx
+ jnz L(ashr_13_exittail)
+
+#ifdef USE_AS_STRNCMP
+ cmp $2, %r11
+ jbe L(ashr_13_exittail)
+#endif
+
+ pxor %xmm0, %xmm0
+ sub $0x1000, %r10
+ jmp L(gobble_ashr_13)
+
+ .p2align 4
+L(ashr_13_exittail):
+ movdqa (%rsi, %rcx), %xmm1
+ psrldq $13, %xmm0
+ psrldq $13, %xmm3
+ jmp L(aftertail)
+
+/*
+ * The following cases will be handled by ashr_14
+ * rcx(offset of rsi) rax(offset of rdi) relative offset corresponding case
+ * n(2~15) n - 2 13(15 +(n - 2) - n) ashr_14
+ */
+ .p2align 4
+L(ashr_14):
+ pxor %xmm0, %xmm0
+ movdqa (%rdi), %xmm2
+ movdqa (%rsi), %xmm1
+ pcmpeqb %xmm1, %xmm0
+ pslldq $2, %xmm2
+ pcmpeqb %xmm1, %xmm2
+ psubb %xmm0, %xmm2
+ pmovmskb %xmm2, %r9d
+ shr %cl, %edx
+ shr %cl, %r9d
+ sub %r9d, %edx
+ jnz L(less32bytes)
+ movdqa (%rdi), %xmm3
+
+ UPDATE_STRNCMP_COUNTER
+
+ pxor %xmm0, %xmm0
+ mov $16, %rcx /* index for loads */
+ mov $14, %r9d /* byte position left over from less32bytes case */
+ /*
+ * Setup %r10 value allows us to detect crossing a page boundary.
+ * When %r10 goes positive we have crossed a page boundary and
+ * need to do a nibble.
+ */
+ lea 14(%rdi), %r10
+ and $0xfff, %r10 /* offset into 4K page */
+ sub $0x1000, %r10 /* subtract 4K pagesize */
+
+ .p2align 4
+L(loop_ashr_14):
+ add $16, %r10
+ jg L(nibble_ashr_14)
+
+L(gobble_ashr_14):
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $14, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+
+ add $16, %r10
+ jg L(nibble_ashr_14) /* cross page boundary */
+
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $14, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+ jmp L(loop_ashr_14)
+
+ .p2align 4
+L(nibble_ashr_14):
+ pcmpeqb %xmm3, %xmm0 /* check nibble for null char */
+ pmovmskb %xmm0, %edx
+ test $0xc000, %edx
+ jnz L(ashr_14_exittail)
+
+#ifdef USE_AS_STRNCMP
+ cmp $1, %r11
+ jbe L(ashr_14_exittail)
+#endif
+
+ pxor %xmm0, %xmm0
+ sub $0x1000, %r10
+ jmp L(gobble_ashr_14)
+
+ .p2align 4
+L(ashr_14_exittail):
+ movdqa (%rsi, %rcx), %xmm1
+ psrldq $14, %xmm0
+ psrldq $14, %xmm3
+ jmp L(aftertail)
+
+/*
+ * The following cases will be handled by ashr_15
+ * rcx(offset of rsi) rax(offset of rdi) relative offset corresponding case
+ * n(1~15) n - 1 14(15 +(n - 1) - n) ashr_15
+ */
+ .p2align 4
+L(ashr_15):
+ pxor %xmm0, %xmm0
+ movdqa (%rdi), %xmm2
+ movdqa (%rsi), %xmm1
+ pcmpeqb %xmm1, %xmm0
+ pslldq $1, %xmm2
+ pcmpeqb %xmm1, %xmm2
+ psubb %xmm0, %xmm2
+ pmovmskb %xmm2, %r9d
+ shr %cl, %edx
+ shr %cl, %r9d
+ sub %r9d, %edx
+ jnz L(less32bytes)
+
+ movdqa (%rdi), %xmm3
+
+ UPDATE_STRNCMP_COUNTER
+
+ pxor %xmm0, %xmm0
+ mov $16, %rcx /* index for loads */
+ mov $15, %r9d /* byte position left over from less32bytes case */
+ /*
+ * Setup %r10 value allows us to detect crossing a page boundary.
+ * When %r10 goes positive we have crossed a page boundary and
+ * need to do a nibble.
+ */
+ lea 15(%rdi), %r10
+ and $0xfff, %r10 /* offset into 4K page */
+
+ sub $0x1000, %r10 /* subtract 4K pagesize */
+
+ .p2align 4
+L(loop_ashr_15):
+ add $16, %r10
+ jg L(nibble_ashr_15)
+
+L(gobble_ashr_15):
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $15, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+
+ add $16, %r10
+ jg L(nibble_ashr_15) /* cross page boundary */
+
+ movdqa (%rsi, %rcx), %xmm1
+ movdqa (%rdi, %rcx), %xmm2
+ movdqa %xmm2, %xmm4
+
+ palignr $15, %xmm3, %xmm2 /* merge into one 16byte value */
+
+ pcmpeqb %xmm1, %xmm0
+ pcmpeqb %xmm2, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ sub $0xffff, %edx
+ jnz L(exit)
+
+#ifdef USE_AS_STRNCMP
+ sub $16, %r11
+ jbe L(strcmp_exitz)
+#endif
+
+ add $16, %rcx
+ movdqa %xmm4, %xmm3
+ jmp L(loop_ashr_15)
+
+ .p2align 4
+L(nibble_ashr_15):
+ pcmpeqb %xmm3, %xmm0 /* check nibble for null char */
+ pmovmskb %xmm0, %edx
+ test $0x8000, %edx
+ jnz L(ashr_15_exittail)
+
+#ifdef USE_AS_STRNCMP
+ test %r11, %r11
+ je L(ashr_15_exittail)
+#endif
+
+ pxor %xmm0, %xmm0
+ sub $0x1000, %r10
+ jmp L(gobble_ashr_15)
+
+ .p2align 4
+L(ashr_15_exittail):
+ movdqa (%rsi, %rcx), %xmm1
+ psrldq $15, %xmm3
+ psrldq $15, %xmm0
+
+ .p2align 4
+L(aftertail):
+ pcmpeqb %xmm3, %xmm1
+ psubb %xmm0, %xmm1
+ pmovmskb %xmm1, %edx
+ not %edx
+
+ .p2align 4
+L(exit):
+ lea -16(%r9, %rcx), %rax /* locate the exact offset for rdi */
+L(less32bytes):
+ lea (%rdi, %rax), %rdi /* locate the exact address for first operand(rdi) */
+ lea (%rsi, %rcx), %rsi /* locate the exact address for second operand(rsi) */
+ test %r8d, %r8d
+ jz L(ret)
+ xchg %rsi, %rdi /* recover original order according to flag(%r8d) */
+
+ .p2align 4
+L(ret):
+L(less16bytes):
+ bsf %rdx, %rdx /* find and store bit index in %rdx */
+
+#ifdef USE_AS_STRNCMP
+ sub %rdx, %r11
+ jbe L(strcmp_exitz)
+#endif
+ movzbl (%rsi, %rdx), %ecx
+ movzbl (%rdi, %rdx), %eax
+
+ sub %ecx, %eax
+ ret
+
+L(strcmp_exitz):
+ xor %eax, %eax
+ ret
+
+ .p2align 4
+L(Byte0):
+ movzbl (%rsi), %ecx
+ movzbl (%rdi), %eax
+
+ sub %ecx, %eax
+ ret
+END (STRCMP)
+
+ .section .rodata,"a",@progbits
+ .p2align 3
+L(unaligned_table):
+ .int L(ashr_1) - L(unaligned_table)
+ .int L(ashr_2) - L(unaligned_table)
+ .int L(ashr_3) - L(unaligned_table)
+ .int L(ashr_4) - L(unaligned_table)
+ .int L(ashr_5) - L(unaligned_table)
+ .int L(ashr_6) - L(unaligned_table)
+ .int L(ashr_7) - L(unaligned_table)
+ .int L(ashr_8) - L(unaligned_table)
+ .int L(ashr_9) - L(unaligned_table)
+ .int L(ashr_10) - L(unaligned_table)
+ .int L(ashr_11) - L(unaligned_table)
+ .int L(ashr_12) - L(unaligned_table)
+ .int L(ashr_13) - L(unaligned_table)
+ .int L(ashr_14) - L(unaligned_table)
+ .int L(ashr_15) - L(unaligned_table)
+ .int L(ashr_0) - L(unaligned_table)
diff --git a/contrib/bionic-x86_64-string/ssse3-strncmp-slm.S b/contrib/bionic-x86_64-string/ssse3-strncmp-slm.S
new file mode 100644
index 000000000000..0e407751714f
--- /dev/null
+++ b/contrib/bionic-x86_64-string/ssse3-strncmp-slm.S
@@ -0,0 +1,33 @@
+/*
+Copyright (c) 2014, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#define USE_AS_STRNCMP
+#define STRCMP strncmp
+#include "ssse3-strcmp-slm.S"
diff --git a/contrib/blacklist/bin/blacklistctl.c b/contrib/blacklist/bin/blacklistctl.c
index aebbf72acc5e..89b72921caf5 100644
--- a/contrib/blacklist/bin/blacklistctl.c
+++ b/contrib/blacklist/bin/blacklistctl.c
@@ -61,7 +61,7 @@ usage(int c)
{
if (c == 0)
warnx("Missing/unknown command");
- else
+ else if (c != '?')
warnx("Unknown option `%c'", (char)c);
fprintf(stderr, "Usage: %s dump [-abdnrw]\n", getprogname());
exit(EXIT_FAILURE);
@@ -123,7 +123,6 @@ main(int argc, char *argv[])
break;
default:
usage(o);
- break;
}
db = state_open(dbname, O_RDONLY, 0);
diff --git a/contrib/blacklist/bin/blacklistd.8 b/contrib/blacklist/bin/blacklistd.8
index ec7f8b429d9d..82e1f15f61c9 100644
--- a/contrib/blacklist/bin/blacklistd.8
+++ b/contrib/blacklist/bin/blacklistd.8
@@ -1,4 +1,4 @@
-.\" $NetBSD: blacklistd.8,v 1.18 2016/07/30 06:09:29 dholland Exp $
+.\" $NetBSD: blacklistd.8,v 1.23 2020/04/21 13:57:12 christos Exp $
.\"
.\" Copyright (c) 2015 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -27,7 +27,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd October 5, 2018
+.Dd April 21, 2020
.Dt BLACKLISTD 8
.Os
.Sh NAME
@@ -65,6 +65,42 @@ with syntax specified in
If an entry is matched, a state entry is created for that tuple.
Each entry contains a number of tries limit and a duration.
.Pp
+The way
+.Nm
+does configuration entry matching is by having the client side pass the
+file descriptor associated with the connection the client wants to blacklist
+as well as passing socket credentials.
+.Pp
+The file descriptor is used to retrieve information (address and port)
+about the remote side with
+.Xr getpeername 2
+and the local side with
+.Xr getsockname 2 .
+.Pp
+By examining the port of the local side,
+.Nm
+can determine if the client program
+.Dq owns
+the port.
+By examining the optional address portion on the local side, it can match
+interfaces.
+By examining the remote address, it can match specific allow or deny rules.
+.Pp
+Finally
+.Nm
+can examine the socket credentials to match the user in the configuration file.
+.Pp
+While this works well for TCP sockets, it cannot be relied on for unbound
+UDP sockets.
+It is also less meaningful when it comes to connections using non-privileged
+ports.
+On the other hand, if we receive a request that has a local endpoint indicating
+a UDP privileged port, we can presume that the client was privileged to be
+able to acquire that port.
+.Pp
+Once an entry is matched
+.Nm
+can perform various actions.
If the action is
.Dq add
and the number of tries limit is reached, then a
@@ -87,10 +123,10 @@ that is not required as all information to remove the rule is
kept.
.Pp
If the action is
-.Dq remove
+.Dq rem
Then the same control script is invoked as:
.Bd -literal -offset indent
-control remove <rulename> <proto> <address> <mask> <port> <id>
+control rem <rulename> <proto> <address> <mask> <port> <id>
.Ed
.Pp
where
@@ -202,19 +238,19 @@ instead of
.Nm
deals with the following signals:
.Bl -tag -width "USR2"
-.It HUP
+.It Dv HUP
Receipt of this signal causes
.Nm
to re-read the configuration file.
-.It INT, TERM & QUIT
+.It Dv INT , Dv TERM & Dv QUIT
These signals tell
.Nm
to exit in an orderly fashion.
-.It USR1
+.It Dv USR1
This signal tells
.Nm
to increase the internal debugging level by 1.
-.It USR2
+.It Dv USR2
This signal tells
.Nm
to decrease the internal debugging level by 1.
diff --git a/contrib/blacklist/bin/blacklistd.c b/contrib/blacklist/bin/blacklistd.c
index e880eb457df0..714abcbcaf0e 100644
--- a/contrib/blacklist/bin/blacklistd.c
+++ b/contrib/blacklist/bin/blacklistd.c
@@ -105,7 +105,7 @@ sigdone(int n __unused)
static __dead void
usage(int c)
{
- if (c)
+ if (c != '?')
warnx("Unknown option `%c'", (char)c);
fprintf(stderr, "Usage: %s [-vdfr] [-c <config>] [-R <rulename>] "
"[-P <sockpathsfile>] [-C <controlprog>] [-D <dbfile>] "
@@ -123,7 +123,7 @@ getremoteaddress(bl_info_t *bi, struct sockaddr_storage *rss, socklen_t *rsl)
return 0;
if (errno != ENOTCONN) {
- (*lfun)(LOG_ERR, "getpeername failed (%m)");
+ (*lfun)(LOG_ERR, "getpeername failed (%m)");
return -1;
}
@@ -141,13 +141,13 @@ getremoteaddress(bl_info_t *bi, struct sockaddr_storage *rss, socklen_t *rsl)
break;
default:
(*lfun)(LOG_ERR, "bad client passed socket family %u",
- (unsigned)bi->bi_ss.ss_family);
+ (unsigned)bi->bi_ss.ss_family);
return -1;
}
if (*rsl != bi->bi_slen) {
(*lfun)(LOG_ERR, "bad client passed socket length %u != %u",
- (unsigned)*rsl, (unsigned)bi->bi_slen);
+ (unsigned)*rsl, (unsigned)bi->bi_slen);
return -1;
}
@@ -157,7 +157,7 @@ getremoteaddress(bl_info_t *bi, struct sockaddr_storage *rss, socklen_t *rsl)
if (*rsl != rss->ss_len) {
(*lfun)(LOG_ERR,
"bad client passed socket internal length %u != %u",
- (unsigned)*rsl, (unsigned)rss->ss_len);
+ (unsigned)*rsl, (unsigned)rss->ss_len);
return -1;
}
#endif
@@ -176,12 +176,12 @@ process(bl_t bl)
struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
- (*lfun)(LOG_ERR, "clock_gettime failed (%m)");
+ (*lfun)(LOG_ERR, "clock_gettime failed (%m)");
return;
}
if ((bi = bl_recv(bl)) == NULL) {
- (*lfun)(LOG_ERR, "no message (%m)");
+ (*lfun)(LOG_ERR, "no message (%m)");
return;
}
@@ -228,30 +228,24 @@ process(bl_t bl)
case BL_ADD:
dbi.count++;
dbi.last = ts.tv_sec;
- if (dbi.id[0]) {
+ if (c.c_nfail != -1 && dbi.count >= c.c_nfail) {
/*
- * We should not be getting this since the rule
- * should have blocked the address. A possible
- * explanation is that someone removed that rule,
- * and another would be that we got another attempt
- * before we added the rule. In anycase, we remove
- * and re-add the rule because we don't want to add
- * it twice, because then we'd lose track of it.
+ * No point in re-adding the rule.
+ * It might exist already due to latency in processing
+ * and removing the rule is the wrong thing to do as
+ * it allows a window to attack again.
*/
- (*lfun)(LOG_DEBUG, "rule exists %s", dbi.id);
- (void)run_change("rem", &c, dbi.id, 0);
- dbi.id[0] = '\0';
- }
- if (c.c_nfail != -1 && dbi.count >= c.c_nfail) {
- int res = run_change("add", &c, dbi.id, sizeof(dbi.id));
- if (res == -1)
- goto out;
+ if (dbi.id[0] == '\0') {
+ int res = run_change("add", &c,
+ dbi.id, sizeof(dbi.id));
+ if (res == -1)
+ goto out;
+ }
sockaddr_snprintf(rbuf, sizeof(rbuf), "%a",
(void *)&rss);
(*lfun)(LOG_INFO,
"blocked %s/%d:%d for %d seconds",
rbuf, c.c_lmask, c.c_port, c.c_duration);
-
}
break;
case BL_DELETE:
@@ -264,7 +258,7 @@ process(bl_t bl)
/* ignore for now */
break;
default:
- (*lfun)(LOG_ERR, "unknown message %d", bi->bi_type);
+ (*lfun)(LOG_ERR, "unknown message %d", bi->bi_type);
}
state_put(state, &c, &dbi);
@@ -306,7 +300,7 @@ update(void)
void *ss = &c.c_ss;
if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
- (*lfun)(LOG_ERR, "clock_gettime failed (%m)");
+ (*lfun)(LOG_ERR, "clock_gettime failed (%m)");
return;
}
@@ -480,7 +474,7 @@ main(int argc, char *argv[])
argc -= optind;
if (argc)
- usage(0);
+ usage('?');
signal(SIGHUP, sighup);
signal(SIGINT, sigdone);
diff --git a/contrib/blacklist/bin/blacklistd.conf.5 b/contrib/blacklist/bin/blacklistd.conf.5
index c0e1a2b87380..3a7ecd9be171 100644
--- a/contrib/blacklist/bin/blacklistd.conf.5
+++ b/contrib/blacklist/bin/blacklistd.conf.5
@@ -1,4 +1,4 @@
-.\" $NetBSD: blacklistd.conf.5,v 1.7 2017/06/07 13:50:57 wiz Exp $
+.\" $NetBSD: blacklistd.conf.5,v 1.9 2019/11/06 20:33:30 para Exp $
.\"
.\" Copyright (c) 2015 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -27,7 +27,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd June 5, 2017
+.Dd May 18, 2020
.Dt BLACKLISTD.CONF 5
.Os
.Sh NAME
@@ -192,7 +192,7 @@ rule that matched.
.Pp
The
.Va remote
-rules can be used for whitelisting specific addresses, changing the mask
+rules can be used for allowing specific addresses, changing the mask
size, the rule that the packet filter uses, the number of failed attempts,
or the block duration.
.Sh FILES
diff --git a/contrib/blacklist/bin/conf.c b/contrib/blacklist/bin/conf.c
index e2a45f80d787..f872b3de787a 100644
--- a/contrib/blacklist/bin/conf.c
+++ b/contrib/blacklist/bin/conf.c
@@ -173,9 +173,9 @@ again:
}
break;
}
- } else
+ } else
tot = im;
-
+
if (e == 0) {
c->c_duration = (int)tot;
return 0;
@@ -214,7 +214,7 @@ static int
getmask(const char *f, size_t l, bool local, const char **p, int *mask)
{
char *d;
- const char *s = *p;
+ const char *s = *p;
if ((d = strchr(s, ':')) != NULL) {
*d++ = '\0';
@@ -264,7 +264,7 @@ gethostport(const char *f, size_t l, bool local, struct conf *c, const char *p)
sin6->sin6_len = sizeof(*sin6);
#endif
port = &sin6->sin6_port;
- }
+ }
} else if (pstr != p || strchr(p, '.') || conf_is_interface(p)) {
if (pstr == p)
pstr = "*";
@@ -366,11 +366,12 @@ getname(const char *f, size_t l, bool local, struct conf *c,
{
if (getmask(f, l, local, &p, &c->c_rmask) == -1)
return -1;
-
+
if (strcmp(p, "*") == 0) {
strlcpy(c->c_name, rulename, CONFNAMESZ);
return 0;
}
+
if (strcmp(p, "=") == 0) {
if (local)
goto out;
@@ -473,7 +474,6 @@ conf_amask_eq(const void *v1, const void *v2, size_t len, int mask)
return 1;
goto out;
case FEQUAL:
-
(*lfun)(LOG_CRIT, "%s: Internal error: bad mask %d", __func__,
mask);
abort();
@@ -687,7 +687,7 @@ conf_addr_eq(const struct sockaddr_storage *s1,
static int
conf_eq(const struct conf *c1, const struct conf *c2)
{
-
+
if (!conf_addr_eq(&c1->c_ss, &c2->c_ss, c2->c_lmask))
return 0;
@@ -744,7 +744,7 @@ fmtport(char *b, size_t l, int port)
if (port == FSTAR)
return;
- if (b[0] == '\0' || strcmp(b, "*") == 0)
+ if (b[0] == '\0' || strcmp(b, "*") == 0)
snprintf(b, l, "%d", port);
else {
snprintf(buf, sizeof(buf), ":%d", port);
@@ -820,7 +820,7 @@ conf_print(char *buf, size_t len, const char *pref, const char *delim,
fmtmask(ha, sizeof(ha), c->c_family, c->c_lmask);
fmtport(ha, sizeof(ha), c->c_port);
-
+
sp = *delim == '\t' ? 20 : -1;
hb[0] = '\0';
if (*delim)
@@ -878,7 +878,7 @@ conf_merge(struct conf *c, const struct conf *sc)
(*lfun)(LOG_DEBUG, "%s: %s", __func__,
conf_print(buf, sizeof(buf), "to:\t", "", c));
}
-
+
if (sc->c_name[0])
memcpy(c->c_name, sc->c_name, CONFNAMESZ);
if (sc->c_uid != FEQUAL)
@@ -1012,13 +1012,13 @@ conf_find(int fd, uid_t uid, const struct sockaddr_storage *rss,
slen = sizeof(lss);
memset(&lss, 0, slen);
if (getsockname(fd, (void *)&lss, &slen) == -1) {
- (*lfun)(LOG_ERR, "getsockname failed (%m)");
+ (*lfun)(LOG_ERR, "getsockname failed (%m)");
return NULL;
}
slen = sizeof(proto);
if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &proto, &slen) == -1) {
- (*lfun)(LOG_ERR, "getsockopt failed (%m)");
+ (*lfun)(LOG_ERR, "getsockopt failed (%m)");
return NULL;
}
@@ -1035,7 +1035,7 @@ conf_find(int fd, uid_t uid, const struct sockaddr_storage *rss,
cr->c_proto = IPPROTO_UDP;
break;
default:
- (*lfun)(LOG_ERR, "unsupported protocol %d", proto);
+ (*lfun)(LOG_ERR, "unsupported protocol %d", proto);
return NULL;
}
@@ -1047,7 +1047,7 @@ conf_find(int fd, uid_t uid, const struct sockaddr_storage *rss,
cr->c_port = ntohs(((struct sockaddr_in6 *)&lss)->sin6_port);
break;
default:
- (*lfun)(LOG_ERR, "unsupported family %d", lss.ss_family);
+ (*lfun)(LOG_ERR, "unsupported family %d", lss.ss_family);
return NULL;
}
@@ -1132,7 +1132,7 @@ conf_parse(const char *f)
fclose(fp);
confset_sort(&lc);
confset_sort(&rc);
-
+
confset_replace(&rconf, &rc);
confset_replace(&lconf, &lc);
diff --git a/contrib/blacklist/bin/run.c b/contrib/blacklist/bin/run.c
index 8499edd3d9c2..5588f0198c04 100644
--- a/contrib/blacklist/bin/run.c
+++ b/contrib/blacklist/bin/run.c
@@ -75,7 +75,7 @@ run(const char *cmd, const char *name, ...)
(argv[i] = va_arg(ap, char *)) != NULL; i++)
continue;
va_end(ap);
-
+
if (debug) {
size_t z;
int r;
diff --git a/contrib/blacklist/bin/support.c b/contrib/blacklist/bin/support.c
index 79a1c6ee93ac..d560d2303223 100644
--- a/contrib/blacklist/bin/support.c
+++ b/contrib/blacklist/bin/support.c
@@ -46,7 +46,7 @@ __RCSID("$NetBSD: support.c,v 1.9 2018/09/18 22:12:19 christos Exp $");
#include "support.h"
static __attribute__((__format_arg__(3))) const char *
-expandm(char *buf, size_t len, const char *fmt)
+expandm(char *buf, size_t len, const char *fmt)
{
char *p;
size_t r;
diff --git a/contrib/blacklist/diff/proftpd.diff b/contrib/blacklist/diff/proftpd.diff
index c811c9cf50bc..455b7cd60c64 100644
--- a/contrib/blacklist/diff/proftpd.diff
+++ b/contrib/blacklist/diff/proftpd.diff
@@ -1,7 +1,7 @@
--- Make.rules.in.orig 2015-05-27 20:25:54.000000000 -0400
+++ Make.rules.in 2016-01-25 21:48:47.000000000 -0500
@@ -110,3 +110,8 @@
-
+
FTPWHO_OBJS=ftpwho.o scoreboard.o misc.o
BUILD_FTPWHO_OBJS=utils/ftpwho.o utils/scoreboard.o utils/misc.o
+
diff --git a/contrib/blacklist/lib/bl.c b/contrib/blacklist/lib/bl.c
index ab2bd7c43ebe..409317bc3fc0 100644
--- a/contrib/blacklist/lib/bl.c
+++ b/contrib/blacklist/lib/bl.c
@@ -496,12 +496,11 @@ bl_recv(bl_t b)
}
if (got != (GOT_CRED|GOT_FD)) {
- bl_log(b->b_fun, LOG_ERR, "message missing %s %s",
+ bl_log(b->b_fun, LOG_ERR, "message missing %s %s",
#if GOT_CRED != 0
(got & GOT_CRED) == 0 ? "cred" :
#endif
"", (got & GOT_FD) == 0 ? "fd" : "");
-
return NULL;
}
diff --git a/contrib/blacklist/lib/blacklist.c b/contrib/blacklist/lib/blacklist.c
index 913753f11101..ba376c3daf0d 100644
--- a/contrib/blacklist/lib/blacklist.c
+++ b/contrib/blacklist/lib/blacklist.c
@@ -61,7 +61,7 @@ int
blacklist_sa_r(struct blacklist *bl, int action, int rfd,
const struct sockaddr *sa, socklen_t slen, const char *msg)
{
- int internal_action;
+ bl_type_t internal_action;
/* internal values are not the same as user application values */
switch (action) {
diff --git a/contrib/blacklist/lib/libblacklist.3 b/contrib/blacklist/lib/libblacklist.3
index aaf809469e6a..146915c8dc31 100644
--- a/contrib/blacklist/lib/libblacklist.3
+++ b/contrib/blacklist/lib/libblacklist.3
@@ -1,4 +1,4 @@
-.\" $NetBSD: libblacklist.3,v 1.8 2017/10/22 10:31:57 abhinav Exp $
+.\" $NetBSD: libblacklist.3,v 1.10 2020/03/30 15:47:15 christos Exp $
.\"
.\" Copyright (c) 2015 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -27,7 +27,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd May 5, 2017
+.Dd March 30, 2020
.Dt LIBBLACKLIST 3
.Os
.Sh NAME
@@ -96,11 +96,13 @@ There was an unsuccessful authentication attempt.
A user successfully authenticated.
.It Va BLACKLIST_ABUSIVE_BEHAVIOR
The sending daemon has detected abusive behavior
-from the remote system. The remote address should
+from the remote system.
+The remote address should
be blocked as soon as possible.
.It Va BLACKLIST_BAD_USER
The sending daemon has determined the username
-presented for authentication is invalid. The
+presented for authentication is invalid.
+The
.Xr blacklistd 8
daemon compares the username to a configured list of forbidden
usernames and
@@ -122,6 +124,14 @@ functions can be used with unconnected sockets, where
.Xr getpeername 2
will not work, the server will pass the peer name in the message.
.Pp
+In all cases the file descriptor passed in the
+.Fa fd
+argument must be pointing to a valid socket so that
+.Xr blacklistd 8
+can establish ownership of the local endpoint
+using
+.Xr getsockname 2 .
+.Pp
By default,
.Xr syslogd 8
is used for message logging.
diff --git a/contrib/blacklist/libexec/blacklistd-helper b/contrib/blacklist/libexec/blacklistd-helper
index 1af320d426b0..f92eab8b29bd 100644
--- a/contrib/blacklist/libexec/blacklistd-helper
+++ b/contrib/blacklist/libexec/blacklistd-helper
@@ -81,7 +81,7 @@ add)
/sbin/pfctl -a "$2/$6" -f -
# insert $ip/$mask into per-protocol/port anchored table
/sbin/pfctl -qa "$2/$6" -t "port$6" -T add "$addr/$mask" && \
- /sbin/pfctl -q -k $addr && echo OK
+ /sbin/pfctl -qk "$addr" && echo OK
;;
esac
;;
@@ -119,8 +119,7 @@ flush)
;;
pf)
# dynamically determine which anchors exist
- anchors=$(/sbin/pfctl -a $2 -s Anchors)
- for anchor in $anchors; do
+ for anchor in $(/sbin/pfctl -a "$2" -s Anchors); do
/sbin/pfctl -a $anchor -t "port${anchor##*/}" -T flush
/sbin/pfctl -a $anchor -F rules
done
diff --git a/contrib/bsddialog/.gitignore b/contrib/bsddialog/.gitignore
index 62f7b594a708..8b8ec9d4ae0b 100644
--- a/contrib/bsddialog/.gitignore
+++ b/contrib/bsddialog/.gitignore
@@ -1,27 +1,24 @@
bsddialog
+.depend*
*.o
-*~
+*.so*
*.a
-examples_library/buildlist
+*.gz
+*.core
+*~
+BSDDIALOG.geany
+BSDDIALOG.tags
+examples_library/calendar
examples_library/checklist
examples_library/datebox
examples_library/form
-examples_library/formw
+examples_library/infobox
examples_library/menu
examples_library/mixedlist
-examples_library/radiolist
-examples_library/theme
-examples_library/treeview
-examples_library/infobox
examples_library/msgbox
examples_library/pause
+examples_library/radiolist
examples_library/rangebox
-examples_library/sade
+examples_library/theme
examples_library/timebox
examples_library/yesno
-*.gz
-lib/libbsddialog.so*
-BSDDIALOG.geany
-BSDDIALOG.tags
-*.core
-freebsd-lab/
diff --git a/contrib/bsddialog/CHANGELOG b/contrib/bsddialog/CHANGELOG
index 22eb3342cfe2..883fe1016d01 100644
--- a/contrib/bsddialog/CHANGELOG
+++ b/contrib/bsddialog/CHANGELOG
@@ -1,4 +1,128 @@
-2022-03-02 version 0.2
+2022-09-24 Version 0.4
+
+ Utility:
+ * add: --normal-screen to set normal mode.
+ * add: --alternate-screen to set alternate mode.
+ * add: --keep-tite as --alternate-screen alias.
+ * add: --and-dialog to build other dialogs.
+ * add: --and-widget as --and-dialog alias.
+ * add: --no-names (--no-tags becames its alias).
+ * add: --no-descriptions (--no-items becames its alias).
+ * add: --help-print-name (--help-tags becames its alias).
+ * add: --item-bottom-desc (--item-help becames its alias).
+ * add: --cr-wrap (was partially implemented) to keep '\n' with "\n".
+ * add: --text-unchanged to avoid default modification.
+ * add: --tab-escape enables "\t" in text.
+ * add: --clear-screen to clear the screen.
+ * add: --clear-dialog to clear the dialog (was --clear).
+ * add: --calendar dialog to select a date.
+ * add: DIAGNOSTICS messages for bad arguments number.
+ * add: DIAGNOSTICS messages for missing and unexpected options.
+ * change: --clear becames alias for --clear-screen.
+ * change: --print-maxsize format output.
+ * change: --menu, --radiolist, --checklist and --treeview output.
+ - no printed items with Cancel or ESC.
+ - --separator prints <sepstr> before each item except HELP.
+ - --separator and --separate-output print <sepstr> after each item.
+ - quoted item name/desc only when needed.
+ - --menu avoids to print selected item after focused HELP item.
+ * change: text default modification.
+ - without a "\n": '\t' -> space, '\n' -> '\n', trim spaces.
+ - with a "\n": '\t' -> space, '\n' -> space, "\n" -> '\n', no trim.
+ - delete '\n' after "\n" (also with --cr-wrap).
+ * change: --datebox input and output format yy/mm/dd -> dd/mm/yy.
+ * delete: --no-collapse (partially implemented).
+ * delete: --no-nl-expand (partially implemented).
+ * delete: --trim (partially implemented).
+
+ Library:
+ * add: bsddialog_msgbox() HOME, END, PPAGE and NPAGE keys.
+ * add: bsddialog_yesno() HOME, END, PPAGE and NPAGE keys.
+ * add: bsddialog_menu() SPACE key (equivalent to ENTER).
+ * add: bsddialog_calendar() to select a date.
+ * change: rename enum bsddialog_grouptype -> enum bsddialog_menutype.
+ * change: fixed-menurows becames at most menurows (depending on text).
+ * change: fixed-rows becames at most rows, min(rows, screenH - shadow).
+ * change: fixed-cols becames at most cols, min(cols, screenW - shadow).
+ * delete: undocumented internal bsddialog_menuitem.depth factor (was 2).
+
+
+2022-08-29 Version 0.3
+
+ Utility:
+ * add: --textbox accepts options for the first button.
+ * add: --columns-per-row for text autosizing.
+ * add: --load-theme to read and set a custom theme at runtime.
+ * add: --save-theme to save current theme.
+ * add: --bikeshed for random settings.
+ * add: --switch-buttons enables focus switching: buttons / input
+ components. Available for: --form, --inputbox, --mixedform,
+ --passwordform, --passwordbox, --timebox and --datebox.
+ * change: rename --esc-cancelvalue to --esc-return-cancel.
+ * change: form field value is printed like multibyte charachter string,
+ previously widechar string.
+ * change: --timebox output with zero padding.
+ * change: --datebox output mm and dd with zero padding.
+ * fix: --hline with empty string.
+ * fix: avoid to overlay the backtitle by setting a top margin.
+ * fix: avoid to overlay down shadow with menus and forms bottomdesc
+ by setting a down margin.
+ * fix: --form read-only flag with multiple fields.
+
+ Library:
+ * add: conf.auto_topmargin and conf.auto_downmargin.
+ * add: bsddialog_textbox() accepts conf.button.* for the first button.
+ * add: bsddialog_textbox() arrows and percentage.
+ * add: conf.text.cols_per_row to set a ratio for text autosizing.
+ * add: timebox and datebox arrows and focus background for boxes.
+ * add: timebox and datebox UP key to switch focus.
+ * add: bsddialog_init_notheme() in bsddialog.h.
+ * add: bsddialog_hascolors() in bsddialog_theme.h.
+ * add: theme.form.bottomdesccolor and theme.menu.bottomdesccolor.
+ * add: conf.button.always_active to disable buttons/input-boxes switch.
+ * add: dynamic buttons margin.
+ - add: theme.button.minmargin and theme.button.maxmargin.
+ - delete: theme.button.hmargin.
+ * add: Unicode.
+ - UI handles multicolumn charachters: backtitle, title,
+ text (word wrapping, autosizing), menus (shortcuts, name, desc),
+ forms (label, field), textbox, mixedgauge (minilabel),
+ buttons (label, shortcuts), bottomtitle.
+ - API handles char* arguments like multibyte charachter string,
+ depending on the current locale.
+ - Internally wide charachters are used to get input from keyboard
+ and to adapt word wrapping and dynamic text autosizing to
+ muticolumn charachters.
+ * refactoring: (rewrite) form.c.
+ - delete: libformw dep implementing its features from scratch.
+ - delete: maxvaluelen >= valuelen constraint.
+ - delete: conf.form.enable_wchar, get always unicode (wchar) input.
+ - add: KEY_HOME, KEY_END, KEY_PPAGE, KEY_NPAGE keys in field.
+ - add: KEY_UP can move focus from buttons to fields.
+ - add: KEY_DOWN can move focus from item to buttons, if nitem is 1.
+ - add: conf.form.securembch secure multibyte charachter.
+ - add: BSDDIALOG_FIELDNOCOLOR for formitem.flags.
+ - add: BSDDIALOG_FIELDCURSOREND for formitem.flags.
+ - add: BSDDIALOG_FIELDEXTEND for formitem.flags.
+ - add: BSDDIALOG_FIELDSINGLEBYTE for formitem.flags.
+ - add: resizing and refresh after KEY_RESIZE (SIGWINCH).
+ - add: items scrolling.
+ - add: conf.form.value_wchar, value is wchar_t* instead of MB-char*.
+ - add: formheight autosizing.
+ - add: dynamic item position.
+ * fix: bsddialog_gauge() with fd < 0.
+ * fix: bsddialog_gauge() refresh new text.
+ * fix: internal segmentation fault with disabled shadow.
+ * fix: center position without shadow.
+ * fix: bsddialog_infobox() with zero text length.
+ * fix: text wrapping with more than 1024 words.
+ * fix: rename theme.shadow.h to theme.shadow.y.
+ * fix: rename theme.shadow.w to theme.shadow.x.
+ * fix: menurows autosize with fixed rows improving text_size().
+ * fix: messagebox.c scrolling and checksize without text.
+
+
+2022-03-02 Version 0.2
Utility:
* add: (this) CHANGELOG.
@@ -19,7 +143,7 @@
* change: theme.button.[left|right]ch -> theme.button.[left|right]delim.
* change: theme.button.space -> theme.button.hmargin.
* change: theme.menu.arrowcolor -> theme.dialog.arrowcolor.
- * change: default menu item depth 4 -> 2.
+ * change: internal bsddialog_menuitem.depth factor 4 -> 2.
* fix: disable HOME, PPAGE, END and NPAGE keys in bsddialog_form().
* fix: visible cursor for timebox.c and form.c in VM VirtualBox.
* fix: mixedlist, center position of separator with big pad.
@@ -31,9 +155,9 @@
* improve: "menus" colors for accessibility.
-2022-01-27 version 0.1
+2022-01-27 Version 0.1
- * Common-Options: --ascii-lines, --backtitle <backtitle>, --begin-x <x>,
+ * Options: --ascii-lines, --backtitle <backtitle>, --begin-x <x>,
--begin-y <y>, --cancel-label <label>, --clear, --colors, --cr-wrap,
--date-format <format>, --defaultno, --default-button <label>,
--default-no, --default-item <name>, --disable-esc,
@@ -58,4 +182,3 @@
--passwordbox, --passwordform, --pause, --radiolist, --rangebox,
--textbox, --timebox, --treeview, --yesno.
* Manuals: bsddialog.1, bsddialog.3.
-
diff --git a/contrib/bsddialog/GNUMakefile b/contrib/bsddialog/GNUMakefile
index ad3d4f55f4a7..7da4d64deecf 100644
--- a/contrib/bsddialog/GNUMakefile
+++ b/contrib/bsddialog/GNUMakefile
@@ -4,12 +4,12 @@
# Written in 2021 by Alfonso Sabato Siciliano
OUTPUT= bsddialog
-SOURCES= bsddialog.c
+SOURCES= bsddialog.c util_theme.c
OBJECTS= $(SOURCES:.c=.o)
LIBPATH= ./lib
LIBBSDDIALOG= $(LIBPATH)/libbsddialog.so
-CFLAGS= -Wall -Wextra -Wno-unused-parameter -I$(LIBPATH)
-LDFLAGS= -Wl,-rpath=$(LIBPATH) -L$(LIBPATH) -lbsddialog
+CFLAGS= -Wall -Wextra -I$(LIBPATH)
+LDFLAGS= -ltinfo -Wl,-rpath=$(LIBPATH) -L$(LIBPATH) -lbsddialog
RM = rm -f
all : $(OUTPUT)
diff --git a/contrib/bsddialog/Makefile b/contrib/bsddialog/Makefile
index 5d5d0cc923a5..28162c5e90b3 100644
--- a/contrib/bsddialog/Makefile
+++ b/contrib/bsddialog/Makefile
@@ -4,18 +4,18 @@
# Written in 2021 by Alfonso Sabato Siciliano
OUTPUT= bsddialog
-SOURCES= bsddialog.c
+SOURCES= bsddialog.c util_theme.c
OBJECTS= ${SOURCES:.c=.o}
LIBPATH= ${.CURDIR}/lib
LIBBSDDIALOG= ${LIBPATH}/libbsddialog.so
-CFLAGS+= -I${LIBPATH} -std=gnu99 -Wall -Wextra -Werror -Wno-unused-parameter
+CFLAGS+= -I${LIBPATH} -std=gnu99 -Wall -Wextra -Werror
# `make -DDEBUG`
.if defined(DEBUG)
CFLAGS= -g -Wall -I${LIBPATH}
LIBDEBUG= -DDEBUG
.endif
-LDFLAGS+= -Wl,-rpath=${LIBPATH} -L${LIBPATH} -lbsddialog
+LDFLAGS+= -ltinfow -Wl,-rpath=${LIBPATH} -L${LIBPATH} -lbsddialog
BINDIR= /usr/local/bin
MAN= ${OUTPUT}.1
diff --git a/contrib/bsddialog/README.md b/contrib/bsddialog/README.md
index 3a814b38ddb4..59af7072e7f5 100644
--- a/contrib/bsddialog/README.md
+++ b/contrib/bsddialog/README.md
@@ -1,23 +1,8 @@
-# BSDDialog 0.2
+# BSDDialog 0.4
-
-This project provides **bsddialog** and **libbsddialog**, an utility and a
-library to build scripts and tools with TUI dialogs and widgets.
-
-
-## Intro
-
-Briefly:
-<https://www.freebsd.org/status/report-2021-04-2021-06/#_bsddialog_tui_widgets>
-
-Utility:
-<https://alfonsosiciliano.gitlab.io/posts/2021-12-07-bsddialog.html>
-
-Library:
-<https://alfonsosiciliano.gitlab.io/posts/2022-01-16-libbsddialog.html>
-
-Screenshots:
-<https://www.flickr.com/photos/alfonsosiciliano/albums/72157720215006074>
+This project provides **bsddialog** and **libbsddialog**, an utility
+and a library to build scripts and tools with TUI dialogs and widgets.
+[Screenshots](https://www.flickr.com/photos/alfonsosiciliano/albums/72157720215006074).
## Getting Started
@@ -31,6 +16,15 @@ FreeBSD:
% ./bsddialog --msgbox "Hello World!" 8 20
```
+Linux:
+
+```
+% git clone https://gitlab.com/alfix/bsddialog.git
+% cd bsddialog
+% make -f GNUMakefile
+% ./bsddialog --msgbox "Hello World!" 8 20
+```
+
Output:
![screenshot](screenshot.png)
@@ -40,9 +34,9 @@ Output:
**Dialogs:**
---checklist, --datebox, --form, --gauge, --inputbox, --menu, --mixedform,
---mixedgauge, --msgbox, --passwordbox, --passwordform, --pause, --radiolist,
---rangebox, --textbox, --timebox, --treeview, --yesno.
+--calendar, --checklist, --datebox, --form, --gauge, --infobox, --inputbox,
+--menu, --mixedform, --mixedgauge, --msgbox, --passwordbox, --passwordform,
+--pause, --radiolist, --rangebox, --textbox, --timebox, --treeview, --yesno.
**Manual**
@@ -64,6 +58,7 @@ Output:
and [Examples](https://gitlab.com/alfix/bsddialog/-/tree/main/examples_utility)
in the _Public Domain_ to build new projects:
```
+% sh ./examples_utility/calendar.sh
% sh ./examples_utility/checklist.sh
% sh ./examples_utility/form.sh
% sh ./examples_utility/gauge.sh
@@ -101,6 +96,8 @@ in the _Public Domain_ to build new projects:
```
% cd examples_library
% sh compile
+% ./calendar
+% ./checklist
% ./datebox
% ./form
% ./infobox
@@ -114,4 +111,10 @@ in the _Public Domain_ to build new projects:
% ./timebox
% ./yesno
```
+
+
+## TODO and Ideas
+ - menubar feature
+ - key callback
+ - Right-To-Left text
diff --git a/contrib/bsddialog/bsddialog.1 b/contrib/bsddialog/bsddialog.1
index c87b760d2ea3..759fe6dc3fff 100644
--- a/contrib/bsddialog/bsddialog.1
+++ b/contrib/bsddialog/bsddialog.1
@@ -1,4 +1,5 @@
.\"
+.\"
.\" Copyright (c) 2021-2022 Alfonso Sabato Siciliano
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -22,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd February 3, 2022
+.Dd September 23, 2022
.Dt BSDDIALOG 1
.Os
.Sh NAME
@@ -34,12 +35,19 @@
.Nm
.Fl Fl version
.Nm
-.Op Fl Fl common-option
+.Op Fl Fl option
.Fl Fl dialog
.Ar text
.Ar rows
.Ar cols
-.Op Ar dialog-parameter
+.Op Ar dialog-argument
+.Nm
+.Fl Fl dialog1
+.Ar ...
+.Oo Fl Fl and-dialog
+.Fl Fl dialog2
+.Ar ...
+.Oc ...
.Sh DESCRIPTION
The
.Nm bsddialog
@@ -51,21 +59,24 @@ The options
and
.Fl Fl version
print the list of options and the version, respectively, then exit.
+.Fl Fl and-dialog
+builds another dialog unless the previous one returns Error, ESC or Cancel.
.Pp
-The following options are available for each dialog.
.Ar text
-is a message printed inside the dialog, except for
-.Fl Fl textbox
-described later.
+is a message printed inside the dialog.
.Ar rows
and
.Ar cols
are the height and width, 0 for autosize and -1 for fullscreen.
+.Pp
The possible input got from the user interface is printed to standard error.
-.Ss Common options
+.Ss Options
The following options can change the default behavior of the utility and are
common to some dialog.
.Bl -tag -width Ds
+.It Fl Fl alternate-screen
+If available set alternate screen mode, see
+.Xr terminfo 5 .
.It Fl Fl ascii-lines
Ascii characters to draw lines.
.It Fl Fl backtitle Ar backtitle
@@ -74,12 +85,21 @@ Title on the top side of the screen.
Dialog horizontal position, 0 is the left screen side, -1 center.
.It Fl Fl begin-y Ar y
Dialog vertical position, 0 is the top screen side, -1 center.
+.It Fl Fl bikeshed
+Random settings.
+Colors.
+Delimiter and margins around the title.
+Buttons always active or TAB to switch focus with input components, see
+.Fl Fl switch-buttons .
+Zero padding with time or date output.
.It Fl Fl cancel-label Ar label
Label for the
.Dq Cancel
button.
-.It Fl Fl clear
+.It Fl Fl clear-dialog
Hide the dialog at exit.
+.It Fl Fl clear-screen
+Clear the screen, after the dialog exit if a dialog is built.
.It Fl Fl colors
Enable highlights for text, the following sequences are considered escapes:
.Bl -column -compact
@@ -100,7 +120,7 @@ cyan.
.It Dq \eZ7
white.
.It Dq \eZr
-reverse foreground and background colors.
+reverse foreground and background.
.It Dq \eZR
disable reverse.
.It Dq \eZb
@@ -112,16 +132,25 @@ underline.
.It Dq \eZU
disable underline.
.It Dq \eZn
-restore to normal text.
+restore normal text.
.El
+.It Fl Fl columns-per-row Ar columns
+Try to set the number of columns for a row of text with autosizing; default
+.Dv 10 .
.It Fl Fl cr-wrap
-Replace new line with a space in
-.Ar text .
+Keep new line in
+.Ar text
+also if it constains a
+.Dq \en ,
+see
+.Fl Fl text-unchanged .
.It Fl Fl date-format Ar format
String accepted by
.Xr strftime 3
to customize the output of
-.Fl Fl datebox .
+.Fl Fl datebox
+and
+.Fl Fl calendar
.It Fl Fl default-button Ar label
Focus on the button with
.Ar label
@@ -136,18 +165,12 @@ Focus on
or
.Dq \&No
button on startup.
-.It Fl Fl defaultno
-Equivalent to
-.Fl Fl default-no .
.It Fl Fl disable-esc
Disable ESC key to quit.
-.It Fl Fl esc-cancelvalue
-Exits with the
+.It Fl Fl esc-return-cancel
+ESC key returns
.Dq Cancel
-button value if the ESC key is pressed.
-.It Fl Fl exit-label Ar label
-Equivalent to
-.Fl Fl ok-label .
+button value.
.It Fl Fl extra-button
Add a button with
.Dq Extra
@@ -174,14 +197,14 @@ Set
for
.Dq Help
button.
+.It Fl Fl help-print-name
+Print the name of the focused item if the Help button is pressed also
+with
+.Fl Fl item-bottom-desc .
.It Fl Fl help-status
Print also the selected items if the
.Dq Help
button is pressed.
-.It Fl Fl help-tags
-Print the name of the focused item if the Help button is pressed also
-with
-.Fl Fl item-help .
.It Fl Fl hfile Ar filename
Open
.Ar filename
@@ -197,18 +220,20 @@ Do not exit with unknown options.
.It Fl Fl insecure
Print
.Sq *
-to hide passwords while typing, default space
-.Sq " " .
+to hide passwords while typing; whitespace otherwise.
+.It Fl Fl item-bottom-desc
+Set a help string for each item of a Checklist, Form, Menu, Mixedform,
+Passwordform, Radiolist and Treeview to display at the bottom screen side.
.It Fl Fl item-depth
Specify a margin for items, available for Checklist, Menu and Radiolist.
-.It Fl Fl item-help
-Set a help string for each element of a Checklist, Form, Menu, Mixedform,
-Passwordform, Radiolist and Treeview to display at the bottom screen side.
.It Fl Fl item-prefix
Set a string to prefix each item of a Checklist, Menu, Radiolist or Treeview.
+.It Fl Fl load-theme Ar file
+Load theme from
+.Ar file .
.It Fl Fl max-input Ar size
Maximum length of the input for
-.Fl Fl input-box
+.Fl Fl inputbox
ans
.Fl Fl passwordbox ,
default 2048.
@@ -216,57 +241,46 @@ default 2048.
Do not show
.Dq Cancel
button.
-.It Fl Fl no-collapse
-Do not replace a TAB character with a space in
-.Ar text .
-.It Fl Fl no-items
+.It Fl Fl no-descriptions
Do not display items desciption, for Checklist, Menu, Radiolist or Treeview.
-.It Fl Fl no-label Ar label
-Equivalent to
-.Fl Fl cancel-label .
.It Fl Fl no-lines
Do not draw borders and lines.
-.It Fl Fl no-nl-expand
-do not consider the sequence
-.Dq \en
-like new line.
+.It Fl Fl no-names
+Do not display items name, for Checklist, Menu and Radiolist.
.It Fl Fl no-ok
Do not draw
.Dq OK
button.
.It Fl Fl no-shadow
No not draw the shadow of the dialog.
-.It Fl Fl no-tags
-Do not display items name, for Checklist, Menu and Radiolist.
-.It Fl Fl nocancel
-Equivalent to
-.Fl Fl no-cancel .
-.It Fl Fl nook
-Equivalent to
-.Fl Fl no-ok .
.It Fl Fl ok-label Ar label
Set
.Ar label
for
.Dq OK
button.
+.It Fl Fl normal-screen
+If available set normal screen mode, see
+.Xr terminfo 5 .
.It Fl Fl output-fd Ar fd
Print input from user interface to the specified file descriptor.
.It Fl Fl output-separator Ar sep
Set a sepator for the items in output, default whitespace.
.It Fl Fl print-maxsize
Screen size.
+This option can be used without a dialog.
.It Fl Fl print-size
Print Dialog height and widget at exit.
.It Fl Fl print-version
Print version.
+This option can be used without a dialog.
.It Fl Fl quoted
Quote items in output, default only when necessary.
+.It Fl Fl save-theme Ar file
+Save the current theme.
+This option can be used without a dialog.
.It Fl Fl separate-output
Separate selected items with a new line and avoid to quote.
-.It Fl Fl separator Ar sep
-Equivalent to
-.Fl Fl output-separator .
.It Fl Fl shadow
Show a pseudo shadow for the dialog, enabled by default.
.It Fl Fl single-quoted
@@ -279,9 +293,38 @@ seconds to close the dialog.
Print input from user interface to standand error, default.
.It Fl Fl stdout
Print input from user interface to standard output.
+.It Fl Fl switch-buttons
+enables focus switching between buttons and input components pressing TAB,
+otherwise buttons are always active and ENTER key closes the dialog.
+Suitable for:
+.Fl Fl form ,
+.Fl Fl inputbox ,
+.Fl Fl mixedform ,
+.Fl Fl passwordbox ,
+.Fl Fl passwordform ,
+.Fl Fl timebox ,
+.Fl Fl calendar
+and
+.Fl Fl datebox .
+.It Fl Fl tab-escape
+Replace
+.Dq \et
+with a tab in
+.Ar text .
.It Fl Fl tab-len Ar spaces
Number of spaces to print a TAB in
.Ar text .
+.It Fl Fl text-unchanged
+By default the
+.Ar text
+is changed before to be printed.
+If it contains at least a
+.Dq \en
+each new line and TAB is converted to a space, subsequent spaces are merged.
+Otherwise new line characters are preserved and a TAB becomes a space.
+This option disable the
+.Ar text
+modification.
.It Fl Fl theme Ar theme
Set a graphical style: blackwhite, bsddialog, flat or dialog.
.It Fl Fl time-format Ar format
@@ -291,16 +334,12 @@ to customize the output of
.Fl Fl timebox .
.It Fl Fl title Ar title
Dialog title.
-.It Fl Fl trim
-remove consecutive spaces in
-.Ar text .
-.It Fl Fl yes-label Ar label
-Equivalent to
-.Fl Fl ok-label .
.El
.Ss Dialogs
The following dialogs are available:
.Bl -tag -width Ds
+.It Fl Fl calendar Ar text Ar rows Ar cols Op Ar day Ar month Ar year
+Dialog to select a date.
.It Fl Fl checklist Ar text Ar rows Ar cols Ar menurows Oo Ar name Ar desc \
Ar status Oc ...
Checklist to select some item from a list via the SPACE key.
@@ -316,10 +355,10 @@ or
The names of the selected items are printed to standard error.
.Ar menurows
is the graphical height of the list, 0 for autosize.
-.It Fl Fl datebox Ar text Ar rows Ar cols Op Ar year Ar month Ar day
+.It Fl Fl datebox Ar text Ar rows Ar cols Op Ar day Ar month Ar year
Dialog to select a date.
.It Fl Fl form Ar text Ar rows Ar cols Ar formrows Oo Ar label Ar ylabel \
-Ar xlabel Ar init Ar yfield Ar xfield Ar fieldlen Ar maxvaluelen Oc ...
+Ar xlabel Ar init Ar yfield Ar xfield Ar fieldlen Ar maxletters Oc ...
Dialog to get a list of strings via forms.
A form has a
.Ar label
@@ -333,19 +372,21 @@ and
.Ar xfield
with graphical length
.Ar fieldlen ,
-.Ar maxvaluelen
+.Ar maxletters
is the maximum input length.
The field can be customized, if
.Ar fieldlen
-is 0 its length is the absolute value of
-.Ar maxvaluelen ,
-if
-.Ar maxvaluelen
-is negative the field is read only,
+is negative the field is read only and its absolute value is the field length.
+If
+.Ar maxletters
+is 0 it is the absolute value of
+.Ar fieldlen .
.Ar init
is a default value.
.Ar formrows
-is the graphical height of the list, has to be at least the number of forms.
+is the graphical height of the list,
+.Dv 0
+for autosize.
.It Fl Fl gauge Ar text Ar rows Ar cols Op Ar percentage
Dialog with a bar to shows
.Ar percentage ,
@@ -365,7 +406,7 @@ Dialog to get a string in input,
.Ar init
is the default value.
.It Fl Fl menu Ar text Ar rows Ar cols Ar menurows Oo Ar name desc Oc ...
-Builds a menu to select an item from a list.
+Builds a menu to select an item from a list, Space key is equivalent to Enter.
An item has a
.Ar name
and a
@@ -374,7 +415,7 @@ The name of the selected item is printed to standard error.
.Ar menurows
is the graphical height of the list, 0 for autosize.
.It Fl Fl mixedform Ar text Ar rows Ar cols Ar formrows Oo Ar label Ar ylabel \
-Ar xlabel Ar init Ar yfield Ar xfield Ar fieldlen Ar maxvaluelen Ar flag Oc ...
+Ar xlabel Ar init Ar yfield Ar xfield Ar fieldlen Ar maxletters Ar flag Oc ...
Dialog to get a list of strings via forms.
A form has a
.Ar label
@@ -388,7 +429,7 @@ at the position
.Ar yfield
and
.Ar xfield ,
-.Ar maxvaluelen
+.Ar maxletters
is the maximum input length,
.Ar init
is a default value,
@@ -396,7 +437,9 @@ is a default value,
can be 0 for normal field, 1 to hide the typed characters and 2 to set the
field read only.
.Ar formrows
-is the graphical height of the list, has to be at least the number of forms.
+is the graphical height of the list,
+.Dv 0
+for autosize.
.It Fl Fl mixedgauge Ar text Ar rows Ar cols Ar mainperc Oo Ar minilabel \
Ar miniperc Oc ...
Dialog to show a main bar to represent
@@ -431,12 +474,14 @@ a blank line,
Dialog to diplay a message without the
.Dq Cancel
button.
+UP, DOWN, HOME, END, PAGEUP and PAGEDOWN keys are availble to navigate the text.
.It Fl Fl passwordbox Ar text Ar rows Ar cols Op Ar init
Dialog to get a password,
.Ar init
is the default value.
.It Fl Fl passwordform Ar text Ar rows Ar cols Ar formrows Oo Ar label \
-Ar ylabel Ar xlabel Ar init Ar yfield Ar xfield Ar fieldlen Ar valuelen Oc ...
+Ar ylabel Ar xlabel Ar init Ar yfield Ar xfield Ar fieldlen Ar maxletters \
+Oc ...
Dialog to get a list of passwords, equivalent to
.Fl Fl form
except typed characters are hidden.
@@ -491,6 +536,7 @@ buttons are renamed
.Dq Yes
and
.Dq \&No .
+UP, DOWN, HOME, END, PAGEUP and PAGEDOWN keys are availble to navigate the text.
.El
.Sh EXIT STATUS
The
@@ -531,14 +577,43 @@ Backtitle, title and message:
Yes-No Question and theme:
.Dl bsddialog --theme blackwhite --yesno Question 10 30
.Pp
+Save a custom theme:
+.Dl bsddialog --save-theme mytheme.txt --infobox \*qSaving theme...\*q 0 0
+.Pp
+Load a custom theme:
+.Dl bsddialog --load-theme mytheme.txt --infobox \*qCustom theme\*q 0 0
+.Pp
Checklist:
.Dl bsddialog --checklist Checklist 0 0 3 N1 \&D1 off N2 D2 on N3 D3 off
.Pp
+Form:
+.Dl bsddialog --form Form 0 0 0 L1: 0 0 X 0 4 20 25 L2: 1 0 Y 1 4 20 25
+.Pp
+Multi-dialog:
+.Dl bsddialog --normal-screen --begin-y 1 --yesno Continue? 0 0 \e \
+--and-dialog --begin-y 10 --infobox Yes 0 0
+.Pp
+Bikeshed:
+.Dl bsddialog --bikeshed --inputbox Example 0 0
+.Pp
Mixedgauge:
-.Dl bsddialog --sleep 3 --mixedgauge Example 10 30 60 L1 "\(dq" -1" L2 30
+.Dl bsddialog --sleep 3 --mixedgauge Example 10 30 60 L1 \*q -1\*q L2 30
.Pp
-Form:
-.Dl bsddialog --form Form 0 0 2 L1: 1 1 X 1 5 20 25 L2: 2 1 X 2 5 20 25
+Mixedgauge script:
+.Bd -literal -offset indent -compact
+perc=0
+while [ $perc -le 100 ]
+do
+ bsddialog --sleep 1 --title Mixedgauge \e
+ --mixedgauge "\enExample...\en" 0 0 $perc \e
+ "Hidden" " -9" \e
+ "Label 1" " -4" \e
+ "Label 2" " -4" \e
+ "Label 3" $perc
+
+ perc=`expr $perc + 20`
+done
+.Ed
.Pp
Gauge script:
.Bd -literal -offset indent -compact
@@ -558,21 +633,26 @@ do
i=`expr $i + 1`
done | bsddialog --title Gauge --gauge "Starting..." 10 70
.Ed
-.Pp
-Mixedgauge script:
+.Sh COMPATIBILITY
+Outdated options are retained for compatibility, properly equivalent options are
+used:
.Bd -literal -offset indent -compact
-perc=0
-while [ $perc -le 100 ]
-do
- bsddialog --sleep 1 --title Mixedgauge \e
- --mixedgauge "\enExample...\en" 0 0 $perc \e
- "Hidden" " -9" \e
- "Label 1" " -4" \e
- "Label 2" " -4" \e
- "Label 3" $perc
-
- perc=`expr $perc + 20`
-done
+Obsolete Equivalent
+--and-widget --and-dialog
+--calendar <text> 2 <cols> --calendar <text> 0 <cols>
+--clear --clear-screen
+--defaultno --default-no
+--exit-label --ok-label
+--help-tags --help-print-name
+--item-help --item-bottom-desc
+--keep-tite --alternate-screen
+--no-items --no-descriptions
+--no-label --cancel-label
+--no-tags --no-names
+--nocancel --no-cancel
+--nook --no-ok
+--separator --output-separator
+--yes-label --ok-label
.Ed
.Sh SEE ALSO
.Xr bsddialog 3
@@ -584,7 +664,101 @@ utility first appeared in
.Sh AUTHORS
.Nm bsddialog
was written by
-.An Alfonso Sabato Siciliano Aq Mt alf.siciliano@gmail.com .
-.Sh BUGS
-Forms do not resize the dialog after a terminal change and do not provide
-scrolling for items. \ No newline at end of file
+.An Alfonso Sabato Siciliano
+.Aq Mt asiciliano@FreeBSD.org .
+.Pp
+.Nm bsddialog
+provides a subset of the functionality described in the
+.Nm dialog
+manual.
+The following features were reimplemented:
+.Pp
+Options:
+.Fl Fl and-widget ,
+.Fl Fl ascii-lines ,
+.Fl Fl backtitle ,
+.Fl Fl cancel-label ,
+.Fl Fl clear ,
+.Fl Fl colors ,
+.Fl Fl cr-wrap ,
+.Fl Fl date-format ,
+.Fl Fl defaultno ,
+.Fl Fl default-button ,
+.Fl Fl default-no ,
+.Fl Fl default-item ,
+.Fl Fl exit-label ,
+.Fl Fl extra-button ,
+.Fl Fl extra-label ,
+.Fl Fl help ,
+.Fl Fl help-button ,
+.Fl Fl help-label ,
+.Fl Fl help-status ,
+.Fl Fl help-tags ,
+.Fl Fl hfile ,
+.Fl Fl hline ,
+.Fl Fl ignore ,
+.Fl Fl insecure ,
+.Fl Fl item-help ,
+.Fl Fl keep-tite ,
+.Fl Fl max-input ,
+.Fl Fl no-cancel ,
+.Fl Fl nocancel ,
+.Fl Fl no-items ,
+.Fl Fl no-label ,
+.Fl Fl no-lines ,
+.Fl Fl no-ok ,
+.Fl Fl nook ,
+.Fl Fl no-shadow ,
+.Fl Fl no-tags ,
+.Fl Fl ok-label ,
+.Fl Fl output-fd ,
+.Fl Fl output-separator ,
+.Fl Fl print-maxsize ,
+.Fl Fl print-size ,
+.Fl Fl print-version ,
+.Fl Fl quoted ,
+.Fl Fl separate-output ,
+.Fl Fl separator ,
+.Fl Fl shadow ,
+.Fl Fl single-quoted ,
+.Fl Fl sleep ,
+.Fl Fl stderr ,
+.Fl Fl stdout ,
+.Fl Fl tab-len ,
+.Fl Fl time-format ,
+.Fl Fl title ,
+.Fl Fl version ,
+.Fl Fl yes-label .
+.Pp
+Dialogs:
+.Fl Fl calendar ,
+.Fl Fl checklist ,
+.Fl Fl form ,
+.Fl Fl gauge ,
+.Fl Fl infobox ,
+.Fl Fl inputbox ,
+.Fl Fl menu ,
+.Fl Fl mixedform ,
+.Fl Fl mixedgauge ,
+.Fl Fl msgbox ,
+.Fl Fl passwordbox ,
+.Fl Fl passwordform ,
+.Fl Fl pause ,
+.Fl Fl radiolist ,
+.Fl Fl rangebox ,
+.Fl Fl textbox ,
+.Fl Fl timebox ,
+.Fl Fl treeview ,
+.Fl Fl yesno .
+.Pp
+Some feature differs in input, output, or behavior.
+Compatibility is not a priority for future development.
+.Sh THANKS TO
+.An Baptiste Daroussin
+.Aq Mt bapt@FreeBSD.org ,
+.An \&Ed Maste
+.Aq Mt emaste@FreeBSD.org
+and
+.An Juraj Lutter
+.Aq Mt otis@FreeBSD.org
+for suggestions, help, and testing.
diff --git a/contrib/bsddialog/bsddialog.c b/contrib/bsddialog/bsddialog.c
index d84df4b494d9..b9b2810dc62f 100644
--- a/contrib/bsddialog/bsddialog.c
+++ b/contrib/bsddialog/bsddialog.c
@@ -33,57 +33,62 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <term.h>
#include <time.h>
#include <unistd.h>
#include <bsddialog.h>
#include <bsddialog_theme.h>
-#define BSDDIALOG_VERSION "0.2"
+#include "util_theme.h"
enum OPTS {
- /* Common options */
- ASCII_LINES = '?' + 1,
+ /* Options */
+ ALTERNATE_SCREEN = '?' + 1,
+ AND_DIALOG,
+ ASCII_LINES,
BACKTITLE,
BEGIN_X,
BEGIN_Y,
+ BIKESHED,
CANCEL_LABEL,
- CLEAR,
+ CLEAR_DIALOG,
+ CLEAR_SCREEN,
COLORS,
+ COLUMNS_PER_ROW,
CR_WRAP,
DATE_FORMAT,
DEFAULT_BUTTON,
DEFAULT_ITEM,
DEFAULT_NO,
DISABLE_ESC,
- ESC_CANCELVALUE,
+ ESC_RETURNCANCEL,
EXIT_LABEL,
EXTRA_BUTTON,
EXTRA_LABEL,
GENERIC_BUTTON1,
GENERIC_BUTTON2,
- HELP,
HELP_BUTTON,
HELP_LABEL,
+ HELP_PRINT_NAME,
HELP_STATUS,
- HELP_TAGS,
HFILE,
HLINE,
HMSG,
IGNORE,
INSECURE,
+ ITEM_BOTTOM_DESC,
ITEM_DEPTH,
- ITEM_HELP,
ITEM_PREFIX,
+ LOAD_THEME,
MAX_INPUT,
NO_CANCEL,
- NO_COLLAPSE,
- NO_ITEMS,
+ NO_DESCRIPTIONS,
NO_LINES,
- NO_NL_EXPAND,
+ NO_NAMES,
NO_OK,
NO_SHADOW,
- NO_TAGS,
+ NORMAL_SCREEN,
OK_LABEL,
OUTPUT_FD,
OUTPUT_SEPARATOR,
@@ -91,19 +96,22 @@ enum OPTS {
PRINT_SIZE,
PRINT_VERSION,
QUOTED,
+ SAVE_THEME,
SEPARATE_OUTPUT,
SHADOW,
SINGLE_QUOTED,
SLEEP,
STDERR,
STDOUT,
+ SWITCH_BUTTONS,
+ TAB_ESCAPE,
TAB_LEN,
+ TEXT_UNCHANGED,
THEME,
TIME_FORMAT,
TITLE,
- TRIM,
- VERSION,
/* Dialogs */
+ CALENDAR,
CHECKLIST,
DATEBOX,
FORM,
@@ -125,27 +133,156 @@ enum OPTS {
YESNO
};
+/* options descriptor */
+static struct option longopts[] = {
+ /* Options */
+ {"alternate-screen", no_argument, NULL, ALTERNATE_SCREEN},
+ {"and-dialog", no_argument, NULL, AND_DIALOG},
+ {"and-widget", no_argument, NULL, AND_DIALOG},
+ {"ascii-lines", no_argument, NULL, ASCII_LINES},
+ {"backtitle", required_argument, NULL, BACKTITLE},
+ {"begin-x", required_argument, NULL, BEGIN_X},
+ {"begin-y", required_argument, NULL, BEGIN_Y},
+ {"bikeshed", no_argument, NULL, BIKESHED},
+ {"cancel-label", required_argument, NULL, CANCEL_LABEL},
+ {"clear", no_argument, NULL, CLEAR_SCREEN},
+ {"clear-dialog", no_argument, NULL, CLEAR_DIALOG},
+ {"clear-screen", no_argument, NULL, CLEAR_SCREEN},
+ {"colors", no_argument, NULL, COLORS},
+ {"columns-per-row", required_argument, NULL, COLUMNS_PER_ROW},
+ {"cr-wrap", no_argument, NULL, CR_WRAP},
+ {"date-format", required_argument, NULL, DATE_FORMAT},
+ {"defaultno", no_argument, NULL, DEFAULT_NO},
+ {"default-button", required_argument, NULL, DEFAULT_BUTTON},
+ {"default-item", required_argument, NULL, DEFAULT_ITEM},
+ {"default-no", no_argument, NULL, DEFAULT_NO},
+ {"disable-esc", no_argument, NULL, DISABLE_ESC},
+ {"esc-return-cancel", no_argument, NULL, ESC_RETURNCANCEL},
+ {"exit-label", required_argument, NULL, EXIT_LABEL},
+ {"extra-button", no_argument, NULL, EXTRA_BUTTON},
+ {"extra-label", required_argument, NULL, EXTRA_LABEL},
+ {"generic-button1", required_argument, NULL, GENERIC_BUTTON1},
+ {"generic-button2", required_argument, NULL, GENERIC_BUTTON2},
+ {"help-button", no_argument, NULL, HELP_BUTTON},
+ {"help-label", required_argument, NULL, HELP_LABEL},
+ {"help-print-name", no_argument, NULL, HELP_PRINT_NAME},
+ {"help-status", no_argument, NULL, HELP_STATUS},
+ {"help-tags", no_argument, NULL, HELP_PRINT_NAME},
+ {"hfile", required_argument, NULL, HFILE},
+ {"hline", required_argument, NULL, HLINE},
+ {"hmsg", required_argument, NULL, HMSG},
+ {"ignore", no_argument, NULL, IGNORE},
+ {"insecure", no_argument, NULL, INSECURE},
+ {"item-bottom-desc", no_argument, NULL, ITEM_BOTTOM_DESC},
+ {"item-depth", no_argument, NULL, ITEM_DEPTH},
+ {"item-help", no_argument, NULL, ITEM_BOTTOM_DESC},
+ {"item-prefix", no_argument, NULL, ITEM_PREFIX},
+ {"keep-tite", no_argument, NULL, ALTERNATE_SCREEN},
+ {"load-theme", required_argument, NULL, LOAD_THEME},
+ {"max-input", required_argument, NULL, MAX_INPUT},
+ {"no-cancel", no_argument, NULL, NO_CANCEL},
+ {"nocancel", no_argument, NULL, NO_CANCEL},
+ {"no-descriptions", no_argument, NULL, NO_DESCRIPTIONS},
+ {"no-items", no_argument, NULL, NO_DESCRIPTIONS},
+ {"no-label", required_argument, NULL, CANCEL_LABEL},
+ {"no-lines", no_argument, NULL, NO_LINES},
+ {"no-names", no_argument, NULL, NO_NAMES},
+ {"no-ok", no_argument, NULL, NO_OK},
+ {"nook ", no_argument, NULL, NO_OK},
+ {"no-shadow", no_argument, NULL, NO_SHADOW},
+ {"no-tags", no_argument, NULL, NO_NAMES},
+ {"normal-screen", no_argument, NULL, NORMAL_SCREEN},
+ {"ok-label", required_argument, NULL, OK_LABEL},
+ {"output-fd", required_argument, NULL, OUTPUT_FD},
+ {"output-separator", required_argument, NULL, OUTPUT_SEPARATOR},
+ {"print-maxsize", no_argument, NULL, PRINT_MAXSIZE},
+ {"print-size", no_argument, NULL, PRINT_SIZE},
+ {"print-version", no_argument, NULL, PRINT_VERSION},
+ {"quoted", no_argument, NULL, QUOTED},
+ {"save-theme", required_argument, NULL, SAVE_THEME},
+ {"separate-output", no_argument, NULL, SEPARATE_OUTPUT},
+ {"separator", required_argument, NULL, OUTPUT_SEPARATOR},
+ {"shadow", no_argument, NULL, SHADOW},
+ {"single-quoted", no_argument, NULL, SINGLE_QUOTED},
+ {"sleep", required_argument, NULL, SLEEP},
+ {"stderr", no_argument, NULL, STDERR},
+ {"stdout", no_argument, NULL, STDOUT},
+ {"switch-buttons", no_argument, NULL, SWITCH_BUTTONS},
+ {"tab-escape", no_argument, NULL, TAB_ESCAPE},
+ {"tab-len", required_argument, NULL, TAB_LEN},
+ {"text-unchanged", no_argument, NULL, TEXT_UNCHANGED},
+ {"theme", required_argument, NULL, THEME},
+ {"time-format", required_argument, NULL, TIME_FORMAT},
+ {"title", required_argument, NULL, TITLE},
+ {"yes-label", required_argument, NULL, OK_LABEL},
+ /* Dialogs */
+ {"calendar", no_argument, NULL, CALENDAR},
+ {"checklist", no_argument, NULL, CHECKLIST},
+ {"datebox", no_argument, NULL, DATEBOX},
+ {"form", no_argument, NULL, FORM},
+ {"gauge", no_argument, NULL, GAUGE},
+ {"infobox", no_argument, NULL, INFOBOX},
+ {"inputbox", no_argument, NULL, INPUTBOX},
+ {"menu", no_argument, NULL, MENU},
+ {"mixedform", no_argument, NULL, MIXEDFORM},
+ {"mixedgauge", no_argument, NULL, MIXEDGAUGE},
+ {"msgbox", no_argument, NULL, MSGBOX},
+ {"passwordbox", no_argument, NULL, PASSWORDBOX},
+ {"passwordform", no_argument, NULL, PASSWORDFORM},
+ {"pause", no_argument, NULL, PAUSE},
+ {"radiolist", no_argument, NULL, RADIOLIST},
+ {"rangebox", no_argument, NULL, RANGEBOX},
+ {"textbox", no_argument, NULL, TEXTBOX},
+ {"timebox", no_argument, NULL, TIMEBOX},
+ {"treeview", no_argument, NULL, TREEVIEW},
+ {"yesno", no_argument, NULL, YESNO},
+ /* END */
+ { NULL, 0, NULL, 0}
+};
+
/* Menus options */
-static bool item_prefix_opt, item_bottomdesc_opt, item_output_sepnl_opt;
-static bool item_singlequote_opt, list_items_on_opt, item_tag_help_opt;
-static bool item_always_quote_opt, item_depth_opt;
-static char *item_output_sep_opt, *item_default_opt;
+static bool item_prefix_opt;
+static bool item_bottomdesc_opt;
+static bool item_output_sepnl_opt;
+static bool item_singlequote_opt;
+static bool list_items_on_opt;
+static bool item_help_print_name_opt;
+static bool item_always_quote_opt;
+static bool item_depth_opt;
+static char *item_output_sep_opt;
+static char *item_default_opt;
/* Date and Time options */
-static char *date_fmt_opt, *time_fmt_opt;
+static char *date_fmt_opt;
+static char *time_fmt_opt;
/* Forms options */
static int unsigned max_input_form_opt;
/* General options */
+static bool esc_return_cancel_opt;
+static bool ignore_opt;
static int output_fd_opt;
-
-static void
-custom_text(bool cr_wrap, bool no_collapse, bool no_nl_expand, bool trim,
- char *text, char *buf);
-
-static void sigint_handler(int sig);
-
+static int getH_opt;
+static int getW_opt;
+/* Text option */
+static bool cr_wrap_opt;
+static bool tab_escape_opt;
+static bool text_unchanged_opt;
+/* Theme and Screen options*/
+static bool bikeshed_opt;
+static enum bsddialog_default_theme theme_opt;
+static char *backtitle_opt;
+static bool clear_screen_opt;
+static char *loadthemefile;
+static char *savethemefile;
+static const char *screen_mode_opt;
+
+/* Functions */
+#define UNUSED_PAR(x) UNUSED_ ## x __attribute__((__unused__))
+static void custom_text(char *text, char *buf);
+static void usage(void);
/* Dialogs */
-#define BUILDER_ARGS struct bsddialog_conf conf, char* text, int rows, \
- int cols, int argc, char **argv, char *errbuf
+#define BUILDER_ARGS struct bsddialog_conf *conf, char* text, int rows, \
+ int cols, int argc, char **argv
+static int calendar_builder(BUILDER_ARGS);
static int checklist_builder(BUILDER_ARGS);
static int datebox_builder(BUILDER_ARGS);
static int form_builder(BUILDER_ARGS);
@@ -166,238 +303,234 @@ static int timebox_builder(BUILDER_ARGS);
static int treeview_builder(BUILDER_ARGS);
static int yesno_builder(BUILDER_ARGS);
+/* init, exit and internals */
+static bool in_bsddialog_mode;
+static bool mandatory_dialog;
+static int (*dialogbuilder)(BUILDER_ARGS);
+
+static void exit_error(const char *errstr, bool with_usage)
+{
+ if (in_bsddialog_mode)
+ bsddialog_end();
+
+ printf("Error: %s.\n\n", errstr);
+ if (with_usage) {
+ printf("See \'bsddialog --help\' or \'man 1 bsddialog\' ");
+ printf("for more information.\n");
+ }
+
+ exit (255);
+}
+
+static void sigint_handler(int UNUSED_PAR(sig))
+{
+ bsddialog_end();
+
+ exit(255);
+}
+
+static void start_bsddialog_mode(void)
+{
+ if (in_bsddialog_mode)
+ return;
+
+ if (bsddialog_init() != BSDDIALOG_OK)
+ exit_error(bsddialog_geterror(), false);
+
+ in_bsddialog_mode = true;
+ signal(SIGINT, sigint_handler);
+}
+
+static void error_args(const char *dialog, int argc, char **argv)
+{
+ int i;
+
+ if (in_bsddialog_mode)
+ bsddialog_end();
+
+ printf("Error: %s unexpected argument%s:", dialog,
+ argc > 1 ? "s" : "");
+ for (i = 0; i < argc; i++)
+ printf(" \"%s\"", argv[i]);
+ printf(".\n\n");
+ printf("See \'bsddialog --help\' or \'man 1 bsddialog\' ");
+ printf("for more information.\n");
+
+ exit (255);
+}
+
static void usage(void)
{
printf("usage: bsddialog --help\n");
printf(" bsddialog --version\n");
- printf(" bsddialog [--<common-opts>] --<dialog> <text> <rows> "
- "<cols> [--<dialog-opts>]\n");
+ printf(" bsddialog [--<opt>] --<dialog> <text> <rows> <cols> "
+ "[<arg>]\n");
+ printf(" bsddialog --<dialog1> ... [--and-dialog --<dialog2> "
+ "...] ...\n");
printf("\n");
- printf("Common Options:\n");
- printf("--ascii-lines, --backtitle <backtitle>, --begin-x <x>, "
- "--begin-y <y>, --cancel-label <label>, --clear, --colors, "
- "--cr-wrap, --date-format <format>, --defaultno, "
- "--default-button <label>, --default-no, --default-item <name>, "
- "--disable-esc, --esc-cancelvalue, --exit-label <label>, "
- "--extra-button, --extra-label <label>, "
- "--generic-button1 <label>, --generic-button2 <label>, --help, "
- "--help-button, --help-label <label>, --help-status, --help-tags, "
- "--hfile <filename>, --hline <string>, --hmsg <string>, --ignore, "
- "--insecure, --item-depth, --item-help, --items-prefix, "
- "--max-input <size>, --no-cancel, --nocancel, --no-collapse, "
- "--no-items, --no-label <label>, --no-lines, --no-nl-expand, "
- "--no-ok, --nook, --no-shadow, --no-tags, --ok-label <label>, "
- "--output-fd <fd>, --output-separator <sep>, --print-maxsize, "
- "--print-size, --print-version, --quoted, --separate-output, "
- "--separator <sep>, --shadow, --single-quoted, --sleep <secs>, "
- "--stderr, --stdout, --tab-len <spaces>, "
- "--theme <blackwhite|bsddialog|flat|dialog>, "
- "--time-format <format>, --title <title>, --trim, --version, "
- "--yes-label <label>.\n");
+ printf("Options:\n");
+ printf(" --alternate-screen, --ascii-lines, --backtitle <backtitle>,"
+ " --begin-x <x>,\n --begin-y <y>, --bikeshed, --calendar,"
+ " --cancel-label <label>, --clear-dialog,\n --clear-screen,"
+ " --colors, --columns-per-row <columns>, --cr-wrap,\n"
+ " --date-format <format>, --default-button <label>,"
+ " --default-item <name>,\n --default-no, --disable-esc,"
+ " --esc-return-cancel, --exit-label <label>,\n --extra-button,"
+ " --extra-label <label>, --generic-button1 <label>,\n"
+ " --generic-button2 <label>, --help-button, --help-label <label>,\n"
+ " --help-print-name, --help-status, --hfile <file>,"
+ " --hline <string>,\n --hmsg <string>, --ignore, --insecure,"
+ " --item-bottom-desc, --item-depth,\n --item-prefix,"
+ " --load-theme <file>, --max-input <size>, --no-cancel,\n"
+ " --no-descriptions, --no-label <label>, --no-lines, --no-names,"
+ " --no-ok,\n --no-shadow, --normal-screen, --ok-label <label>,"
+ " --output-fd <fd>,\n --output-separator <sep>, --print-maxsize,"
+ " --print-size, --print-version,\n --quoted, --save-theme <file>,"
+ " --separate-output, --separator <sep>, --shadow,\n"
+ " --single-quoted, --sleep <secs>, --stderr, --stdout,"
+ " --tab-escape,\n --tab-len <spaces>, --text-unchanged,"
+ " --switch-buttons,\n --theme <blackwhite|bsddialog|flat|dialog>,"
+ " --time-format <format>,\n --title <title>,"
+ " --yes-label <label>.\n");
printf("\n");
printf("Dialogs:\n");
- printf("--checklist <text> <rows> <cols> <menurows> [<name> <desc> "
+ printf(" --calendar <text> <rows> <cols> [<dd> <mm> <yy>]\n");
+ printf(" --checklist <text> <rows> <cols> <menurows> [<name> <desc> "
"<on|off>] ...\n");
- printf("--datebox <text> <rows> <cols> [<yy> <mm> <dd>]\n");
- printf("--form <text> <rows> <cols> <formrows> [<label> <ylabel> "
- "<xlabel> <init> <yfield> <xfield> <fieldlen> <maxvaluelen>] "
+ printf(" --datebox <text> <rows> <cols> [<dd> <mm> <yy>]\n");
+ printf(" --form <text> <rows> <cols> <formrows> [<label> <ylabel> "
+ "<xlabel> <init> <yfield> <xfield> <fieldlen> <maxletters>] "
"...\n");
- printf("--gauge <text> <rows> <cols> [<perc>]\n");
- printf("--infobox <text> <rows> <cols>\n");
- printf("--inputbox <text> <rows> <cols> [init]\n");
- printf("--menu <text> <rows> <cols> <menurows> [<name> <desc>] ...\n");
- printf("--mixedform <text> <rows> <cols> <formrows> [<label> <ylabel> "
- "<xlabel> <init> <yfield> <xfield> <fieldlen> <maxvaluelen> "
+ printf(" --gauge <text> <rows> <cols> [<perc>]\n");
+ printf(" --infobox <text> <rows> <cols>\n");
+ printf(" --inputbox <text> <rows> <cols> [init]\n");
+ printf(" --menu <text> <rows> <cols> <menurows> [<name> <desc>] ...\n");
+ printf(" --mixedform <text> <rows> <cols> <formrows> [<label> <ylabel> "
+ "<xlabel> <init> <yfield> <xfield> <fieldlen> <maxletters> "
"<0|1|2>] ...\n");
- printf("--mixedgauge <text> <rows> <cols> <mainperc> [<minilabel> "
+ printf(" --mixedgauge <text> <rows> <cols> <mainperc> [<minilabel> "
"<miniperc>] ...\n");
- printf("--msgbox <text> <rows> <cols>\n");
- printf("--passwordbox <text> <rows> <cols> [init]\n");
- printf("--passwordform <text> <rows> <cols> <formrows> [<label> "
+ printf(" --msgbox <text> <rows> <cols>\n");
+ printf(" --passwordbox <text> <rows> <cols> [init]\n");
+ printf(" --passwordform <text> <rows> <cols> <formrows> [<label> "
"<ylabel> <xlabel> <init> <yfield> <xfield> <fieldlen> "
- "<maxvaluelen>] ...\n");
- printf("--pause <text> <rows> <cols> <secs>\n");
- printf("--radiolist <text> <rows> <cols> <menurows> [<name> <desc> "
+ "<maxletters>] ...\n");
+ printf(" --pause <text> <rows> <cols> <secs>\n");
+ printf(" --radiolist <text> <rows> <cols> <menurows> [<name> <desc> "
"<on|off>] ...\n");
- printf("--rangebox <text> <rows> <cols> <min> <max> [<init>]\n");
- printf("--textbox <file> <rows> <cols>\n");
- printf("--timebox <text> <rows> <cols> [<hh> <mm> <ss>]\n");
- printf("--treeview <text> <rows> <cols> <menurows> [<depth> <name> "
+ printf(" --rangebox <text> <rows> <cols> <min> <max> [<init>]\n");
+ printf(" --textbox <file> <rows> <cols>\n");
+ printf(" --timebox <text> <rows> <cols> [<hh> <mm> <ss>]\n");
+ printf(" --treeview <text> <rows> <cols> <menurows> [<depth> <name> "
"<desc> <on|off>] ...\n");
- printf("--yesno <text> <rows> <cols>\n");
+ printf(" --yesno <text> <rows> <cols>\n");
printf("\n");
printf("See 'man 1 bsddialog' for more information.\n");
}
-int main(int argc, char *argv[argc])
+static int parseargs(int argc, char **argv, struct bsddialog_conf *conf)
{
- bool cr_wrap_opt, no_collapse_opt, no_nl_expand_opt, trim_opt;
- bool esc_cancelvalue_opt, ignore_opt, print_maxsize_opt;;
- int input, rows, cols, output, getH, getW;
- int (*dialogbuilder)(BUILDER_ARGS) = NULL;
- enum bsddialog_default_theme theme_opt;
- char *text, *backtitle_opt;
- char errorbuilder[1024];
+ int arg, parsed, i;
struct winsize ws;
- struct bsddialog_conf conf;
- setlocale(LC_ALL, "");
+ bsddialog_initconf(conf);
+ conf->key.enable_esc = true;
+ conf->menu.on_without_ok = true;
+ conf->form.value_without_ok = true;
+ conf->button.always_active = true;
- bsddialog_initconf(&conf);
- conf.key.enable_esc = true;
- conf.menu.on_without_ok = true;
- conf.form.value_without_ok = true;
- conf.form.enable_wchar = true;
+ dialogbuilder = NULL;
backtitle_opt = NULL;
- theme_opt = BSDDIALOG_THEME_FLAT;
+ theme_opt = -1;
output_fd_opt = STDERR_FILENO;
- print_maxsize_opt = false;
ignore_opt = false;
- cr_wrap_opt = no_collapse_opt = no_nl_expand_opt = trim_opt = false;
- esc_cancelvalue_opt = false;
- errorbuilder[0] = '\0';
-
- item_output_sepnl_opt = item_singlequote_opt = false;
- item_prefix_opt = item_bottomdesc_opt = item_depth_opt = false;
- list_items_on_opt = item_tag_help_opt = false;
+ cr_wrap_opt = false;
+ tab_escape_opt = false;
+ text_unchanged_opt = false;
+ esc_return_cancel_opt = false;
+ bikeshed_opt = false;
+ savethemefile = NULL;
+ loadthemefile = NULL;
+ clear_screen_opt = false;
+ screen_mode_opt = NULL;
+
+ item_output_sepnl_opt = false;
+ item_singlequote_opt = false;
+ item_prefix_opt = false;
+ item_bottomdesc_opt = false;
+ item_depth_opt = false;
+ list_items_on_opt = false;
+ item_help_print_name_opt = false;
item_always_quote_opt = false;
item_output_sep_opt = NULL;
item_default_opt = NULL;
- date_fmt_opt = time_fmt_opt = NULL;
-
- max_input_form_opt = 0;
-
- /* options descriptor */
- struct option longopts[] = {
- /* common options */
- {"ascii-lines", no_argument, NULL, ASCII_LINES},
- {"backtitle", required_argument, NULL, BACKTITLE},
- {"begin-x", required_argument, NULL, BEGIN_X},
- {"begin-y", required_argument, NULL, BEGIN_Y},
- {"cancel-label", required_argument, NULL, CANCEL_LABEL},
- {"clear", no_argument, NULL, CLEAR},
- {"colors", no_argument, NULL, COLORS},
- {"cr-wrap", no_argument, NULL, CR_WRAP},
- {"date-format", required_argument, NULL, DATE_FORMAT},
- {"defaultno", no_argument, NULL, DEFAULT_NO},
- {"default-button", required_argument, NULL, DEFAULT_BUTTON},
- {"default-item", required_argument, NULL, DEFAULT_ITEM},
- {"default-no", no_argument, NULL, DEFAULT_NO},
- {"disable-esc", no_argument, NULL, DISABLE_ESC},
- {"esc-cancelvalue", no_argument, NULL, ESC_CANCELVALUE},
- {"exit-label", required_argument, NULL, EXIT_LABEL},
- {"extra-button", no_argument, NULL, EXTRA_BUTTON},
- {"extra-label", required_argument, NULL, EXTRA_LABEL},
- {"generic-button1", required_argument, NULL, GENERIC_BUTTON1},
- {"generic-button2", required_argument, NULL, GENERIC_BUTTON2},
- {"help", no_argument, NULL, HELP},
- {"help-button", no_argument, NULL, HELP_BUTTON},
- {"help-label", required_argument, NULL, HELP_LABEL},
- {"help-status", no_argument, NULL, HELP_STATUS},
- {"help-tags", no_argument, NULL, HELP_TAGS},
- {"hfile", required_argument, NULL, HFILE},
- {"hline", required_argument, NULL, HLINE},
- {"hmsg", required_argument, NULL, HMSG},
- {"ignore", no_argument, NULL, IGNORE},
- {"insecure", no_argument, NULL, INSECURE},
- {"item-depth", no_argument, NULL, ITEM_DEPTH},
- {"item-help", no_argument, NULL, ITEM_HELP},
- {"item-prefix", no_argument, NULL, ITEM_PREFIX},
- {"max-input", required_argument, NULL, MAX_INPUT},
- {"no-cancel", no_argument, NULL, NO_CANCEL},
- {"nocancel", no_argument, NULL, NO_CANCEL},
- {"no-collapse", no_argument, NULL, NO_COLLAPSE},
- {"no-items", no_argument, NULL, NO_ITEMS},
- {"no-label", required_argument, NULL, CANCEL_LABEL},
- {"no-lines", no_argument, NULL, NO_LINES},
- {"no-nl-expand", no_argument, NULL, NO_NL_EXPAND},
- {"no-ok", no_argument, NULL, NO_OK},
- {"nook ", no_argument, NULL, NO_OK},
- {"no-shadow", no_argument, NULL, NO_SHADOW},
- {"no-tags", no_argument, NULL, NO_TAGS},
- {"ok-label", required_argument, NULL, OK_LABEL},
- {"output-fd", required_argument, NULL, OUTPUT_FD},
- {"output-separator", required_argument, NULL, OUTPUT_SEPARATOR},
- {"print-maxsize", no_argument, NULL, PRINT_MAXSIZE},
- {"print-size", no_argument, NULL, PRINT_SIZE},
- {"print-version", no_argument, NULL, PRINT_VERSION},
- {"quoted", no_argument, NULL, QUOTED},
- {"separate-output", no_argument, NULL, SEPARATE_OUTPUT},
- {"separator", required_argument, NULL, OUTPUT_SEPARATOR},
- {"shadow", no_argument, NULL, SHADOW},
- {"single-quoted", no_argument, NULL, SINGLE_QUOTED},
- {"sleep", required_argument, NULL, SLEEP},
- {"stderr", no_argument, NULL, STDERR},
- {"stdout", no_argument, NULL, STDOUT},
- {"tab-len", required_argument, NULL, TAB_LEN},
- {"theme", required_argument, NULL, THEME},
- {"time-format", required_argument, NULL, TIME_FORMAT},
- {"title", required_argument, NULL, TITLE},
- {"trim", no_argument, NULL, TRIM},
- {"version", no_argument, NULL, VERSION},
- {"yes-label", required_argument, NULL, OK_LABEL},
- /* Dialogs */
- {"checklist", no_argument, NULL, CHECKLIST},
- {"datebox", no_argument, NULL, DATEBOX},
- {"form", no_argument, NULL, FORM},
- {"gauge", no_argument, NULL, GAUGE},
- {"infobox", no_argument, NULL, INFOBOX},
- {"inputbox", no_argument, NULL, INPUTBOX},
- {"menu", no_argument, NULL, MENU},
- {"mixedform", no_argument, NULL, MIXEDFORM},
- {"mixedgauge", no_argument, NULL, MIXEDGAUGE},
- {"msgbox", no_argument, NULL, MSGBOX},
- {"passwordbox", no_argument, NULL, PASSWORDBOX},
- {"passwordform", no_argument, NULL, PASSWORDFORM},
- {"pause", no_argument, NULL, PAUSE},
- {"radiolist", no_argument, NULL, RADIOLIST},
- {"rangebox", no_argument, NULL, RANGEBOX},
- {"textbox", no_argument, NULL, TEXTBOX},
- {"timebox", no_argument, NULL, TIMEBOX},
- {"treeview", no_argument, NULL, TREEVIEW},
- {"yesno", no_argument, NULL, YESNO},
- /* END */
- { NULL, 0, NULL, 0}
- };
-
- while ((input = getopt_long(argc, argv, "", longopts, NULL)) != -1) {
- switch (input) {
- /* Common options */
+ date_fmt_opt = NULL;
+ time_fmt_opt = NULL;
+
+ max_input_form_opt = 2048;
+
+ for (i = 0; i < argc; i++) {
+ if (strcmp(argv[i], "--and-dialog") == 0 ||
+ strcmp(argv[i], "--and-widget") == 0) {
+ argc = i + 1;
+ break;
+ }
+ }
+ parsed = argc;
+ while ((arg = getopt_long(argc, argv, "", longopts, NULL)) != -1) {
+ switch (arg) {
+ /* Options */
+ case ALTERNATE_SCREEN:
+ screen_mode_opt = "smcup";
+ break;
+ case AND_DIALOG:
+ if (dialogbuilder == NULL)
+ exit_error("--and-dialog without previous "
+ "--<dialog>", true);
+ break;
case ASCII_LINES:
- conf.ascii_lines = true;
+ conf->ascii_lines = true;
break;
case BACKTITLE:
backtitle_opt = optarg;
+ if (conf->y == BSDDIALOG_CENTER)
+ conf->auto_topmargin = 2;
break;
case BEGIN_X:
- conf.x = (int)strtol(optarg, NULL, 10);
- if (conf.x < BSDDIALOG_CENTER) {
- printf("Error: --begin-x %d < %d",
- conf.x, BSDDIALOG_CENTER);
- return (255);
- }
+ conf->x = (int)strtol(optarg, NULL, 10);
+ if (conf->x < BSDDIALOG_CENTER)
+ exit_error("--begin-x < -1", false);
break;
case BEGIN_Y:
- conf.y = (int)strtol(optarg, NULL, 10);
- if (conf.y < BSDDIALOG_CENTER) {
- printf("Error: --begin-y %d < %d",
- conf.y, BSDDIALOG_CENTER);
- return (255);
- }
+ conf->y = (int)strtol(optarg, NULL, 10);
+ if (conf->y < BSDDIALOG_CENTER)
+ exit_error("--begin-y < -1", false);
+ conf->auto_topmargin = 0;
+ break;
+ case BIKESHED:
+ bikeshed_opt = true;
break;
case CANCEL_LABEL:
- conf.button.cancel_label = optarg;
+ conf->button.cancel_label = optarg;
+ break;
+ case CLEAR_DIALOG:
+ conf->clear = true;
break;
- case CLEAR:
- conf.clear = true;
+ case CLEAR_SCREEN:
+ mandatory_dialog = false;
+ clear_screen_opt = true;
break;
case COLORS:
- conf.text.highlight = true;
+ conf->text.highlight = true;
+ break;
+ case COLUMNS_PER_ROW:
+ conf->text.cols_per_row =
+ (u_int)strtoul(optarg, NULL, 10);
break;
case CR_WRAP:
cr_wrap_opt = true;
@@ -406,104 +539,101 @@ int main(int argc, char *argv[argc])
date_fmt_opt = optarg;
break;
case DEFAULT_BUTTON:
- conf.button.default_label = optarg;
+ conf->button.default_label = optarg;
break;
case DEFAULT_ITEM:
item_default_opt = optarg;
break;
case DEFAULT_NO:
- conf.button.default_cancel = true;
+ conf->button.default_cancel = true;
break;
case DISABLE_ESC:
- conf.key.enable_esc = false;
+ conf->key.enable_esc = false;
break;
- case ESC_CANCELVALUE:
- esc_cancelvalue_opt = true;
+ case ESC_RETURNCANCEL:
+ esc_return_cancel_opt = true;
break;
case EXIT_LABEL:
- conf.button.ok_label = optarg;
+ conf->button.ok_label = optarg;
break;
case EXTRA_BUTTON:
- conf.button.with_extra = true;
+ conf->button.with_extra = true;
break;
case EXTRA_LABEL:
- conf.button.extra_label = optarg;
+ conf->button.extra_label = optarg;
break;
case GENERIC_BUTTON1:
- conf.button.generic1_label = optarg;
+ conf->button.generic1_label = optarg;
break;
case GENERIC_BUTTON2:
- conf.button.generic2_label = optarg;
+ conf->button.generic2_label = optarg;
break;
- case HELP:
- usage();
- return (BSDDIALOG_OK);
case HELP_BUTTON:
- conf.button.with_help = true;
+ conf->button.with_help = true;
break;
case HELP_LABEL:
- conf.button.help_label = optarg;
+ conf->button.help_label = optarg;
+ break;
+ case HELP_PRINT_NAME:
+ item_help_print_name_opt = true;
break;
case HELP_STATUS:
list_items_on_opt = true;
break;
- case HELP_TAGS:
- item_tag_help_opt = true;
- break;
case HFILE:
- conf.key.f1_file = optarg;
+ conf->key.f1_file = optarg;
break;
case HLINE:
- if (strlen(optarg) > 0)
- conf.bottomtitle = optarg;
+ if (optarg[0] != '\0')
+ conf->bottomtitle = optarg;
break;
case HMSG:
- conf.key.f1_message = optarg;
+ conf->key.f1_message = optarg;
break;
case IGNORE:
ignore_opt = true;
break;
case INSECURE:
- conf.form.securech = '*';
+ conf->form.securech = '*';
+ break;
+ case ITEM_BOTTOM_DESC:
+ item_bottomdesc_opt = true;
break;
case ITEM_DEPTH:
item_depth_opt = true;
break;
- case ITEM_HELP:
- item_bottomdesc_opt = true;
- break;
case ITEM_PREFIX:
item_prefix_opt = true;
break;
+ case LOAD_THEME:
+ loadthemefile = optarg;
+ break;
case MAX_INPUT:
max_input_form_opt = (u_int)strtoul(optarg, NULL, 10);
break;
- case NO_ITEMS:
- conf.menu.no_desc = true;
- break;
case NO_CANCEL:
- conf.button.without_cancel = true;
+ conf->button.without_cancel = true;
break;
- case NO_COLLAPSE:
- no_collapse_opt = true;
+ case NO_DESCRIPTIONS:
+ conf->menu.no_desc = true;
break;
case NO_LINES:
- conf.no_lines = true;
+ conf->no_lines = true;
break;
- case NO_NL_EXPAND:
- no_nl_expand_opt = true;
+ case NO_NAMES:
+ conf->menu.no_name = true;
break;
case NO_OK:
- conf.button.without_ok = true;
- break;
- case NO_TAGS:
- conf.menu.no_name = true;
+ conf->button.without_ok = true;
break;
case NO_SHADOW:
- conf.shadow = false;
+ conf->shadow = false;
+ break;
+ case NORMAL_SCREEN:
+ screen_mode_opt = "rmcup";
break;
case OK_LABEL:
- conf.button.ok_label = optarg;
+ conf->button.ok_label = optarg;
break;
case OUTPUT_FD:
output_fd_opt = (int)strtol(optarg, NULL, 10);
@@ -515,26 +645,35 @@ int main(int argc, char *argv[argc])
item_always_quote_opt = true;
break;
case PRINT_MAXSIZE:
- print_maxsize_opt = true;
+ mandatory_dialog = false;
+ ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
+ dprintf(output_fd_opt, "MaxSize: %d, %d\n",
+ ws.ws_row, ws.ws_col);
break;
case PRINT_SIZE:
- conf.get_height = &getH;
- conf.get_width = &getW;
+ conf->get_height = &getH_opt;
+ conf->get_width = &getW_opt;
break;
case PRINT_VERSION:
- printf("bsddialog version %s\n", BSDDIALOG_VERSION);
+ mandatory_dialog = false;
+ dprintf(output_fd_opt, "Version: %s\n",
+ LIBBSDDIALOG_VERSION);
+ break;
+ case SAVE_THEME:
+ mandatory_dialog = false;
+ savethemefile = optarg;
break;
case SEPARATE_OUTPUT:
item_output_sepnl_opt = true;
break;
case SHADOW:
- conf.shadow = true;
+ conf->shadow = true;
break;
case SINGLE_QUOTED:
item_singlequote_opt = true;
break;
case SLEEP:
- conf.sleep = (u_int)strtoul(optarg, NULL, 10);
+ conf->sleep = (u_int)strtoul(optarg, NULL, 10);
break;
case STDERR:
output_fd_opt = STDERR_FILENO;
@@ -542,8 +681,17 @@ int main(int argc, char *argv[argc])
case STDOUT:
output_fd_opt = STDOUT_FILENO;
break;
+ case SWITCH_BUTTONS:
+ conf->button.always_active = false;
+ break;
+ case TAB_ESCAPE:
+ tab_escape_opt = true;
+ break;
case TAB_LEN:
- conf.text.tablen = (u_int)strtoul(optarg, NULL, 10);
+ conf->text.tablen = (u_int)strtoul(optarg, NULL, 10);
+ break;
+ case TEXT_UNCHANGED:
+ text_unchanged_opt = true;
break;
case THEME:
if (strcasecmp(optarg, "bsddialog") == 0)
@@ -554,216 +702,313 @@ int main(int argc, char *argv[argc])
theme_opt = BSDDIALOG_THEME_FLAT;
else if (strcasecmp(optarg, "dialog") == 0)
theme_opt = BSDDIALOG_THEME_DIALOG;
- else {
- printf("Error: unknown theme\n");
- return (255);
- }
+ else
+ exit_error("--theme: <unknown> theme", false);
break;
case TIME_FORMAT:
time_fmt_opt = optarg;
break;
case TITLE:
- conf.title = optarg;
+ conf->title = optarg;
break;
- case TRIM:
- trim_opt = true;
- break;
- case VERSION:
- printf("bsddialog %s (libbsddialog %s)\n",
- BSDDIALOG_VERSION, LIBBSDDIALOG_VERSION);
- return (BSDDIALOG_OK);
/* Dialogs */
+ case CALENDAR:
+ if (dialogbuilder != NULL)
+ exit_error("unexpected --calendar", true);
+ dialogbuilder = calendar_builder;
+ break;
case CHECKLIST:
+ if (dialogbuilder != NULL)
+ exit_error("unexpected --checklist", true);
dialogbuilder = checklist_builder;
+ conf->auto_downmargin = 1;
break;
case DATEBOX:
+ if (dialogbuilder != NULL)
+ exit_error("unexpected --datebox", true);
dialogbuilder = datebox_builder;
break;
case FORM:
+ if (dialogbuilder != NULL)
+ exit_error("unexpected --form", true);
dialogbuilder = form_builder;
+ conf->auto_downmargin = 1;
break;
case GAUGE:
+ if (dialogbuilder != NULL)
+ exit_error("unexpected --gauge", true);
dialogbuilder = gauge_builder;
break;
case INFOBOX:
+ if (dialogbuilder != NULL)
+ exit_error("unexpected --infobox", true);
dialogbuilder = infobox_builder;
break;
case INPUTBOX:
+ if (dialogbuilder != NULL)
+ exit_error("unexpected --inputbox", true);
dialogbuilder = inputbox_builder;
+ conf->auto_downmargin = 1;
break;
case MENU:
+ if (dialogbuilder != NULL)
+ exit_error("unexpected --menu", true);
dialogbuilder = menu_builder;
+ conf->auto_downmargin = 1;
break;
case MIXEDFORM:
+ if (dialogbuilder != NULL)
+ exit_error("unexpected --mixedform", true);
dialogbuilder = mixedform_builder;
+ conf->auto_downmargin = 1;
break;
case MIXEDGAUGE:
+ if (dialogbuilder != NULL)
+ exit_error("unexpected --mixedgauge", true);
dialogbuilder = mixedgauge_builder;
break;
case MSGBOX:
+ if (dialogbuilder != NULL)
+ exit_error("unexpected --msgbox", true);
dialogbuilder = msgbox_builder;
break;
case PAUSE:
+ if (dialogbuilder != NULL)
+ exit_error("unexpected --pause", true);
dialogbuilder = pause_builder;
break;
case PASSWORDBOX:
+ if (dialogbuilder != NULL)
+ exit_error("unexpected --passwordbox", true);
dialogbuilder = passwordbox_builder;
+ conf->auto_downmargin = 1;
break;
case PASSWORDFORM:
+ if (dialogbuilder != NULL)
+ exit_error("unexpected --passwordform", true);
dialogbuilder = passwordform_builder;
+ conf->auto_downmargin = 1;
break;
case RADIOLIST:
+ if (dialogbuilder != NULL)
+ exit_error("unexpected --radiolist", true);
dialogbuilder = radiolist_builder;
+ conf->auto_downmargin = 1;
break;
case RANGEBOX:
+ if (dialogbuilder != NULL)
+ exit_error("unexpected --rangebox", true);
dialogbuilder = rangebox_builder;
break;
case TEXTBOX:
+ if (dialogbuilder != NULL)
+ exit_error("unexpected --textbox", true);
dialogbuilder = textbox_builder;
break;
case TIMEBOX:
+ if (dialogbuilder != NULL)
+ exit_error("unexpected --timebox", true);
dialogbuilder = timebox_builder;
break;
case TREEVIEW:
+ if (dialogbuilder != NULL)
+ exit_error("unexpected --treeview", true);
dialogbuilder = treeview_builder;
+ conf->auto_downmargin = 1;
break;
case YESNO:
+ if (dialogbuilder != NULL)
+ exit_error("unexpected --yesno", true);
dialogbuilder = yesno_builder;
break;
- /* Error */
- default:
+ default: /* Error */
if (ignore_opt == true)
break;
- usage();
- return (255);
+ exit_error("--ignore to continue", true);
}
}
- argc -= optind;
- argv += optind;
-
- if (print_maxsize_opt) {
- ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
- dprintf(output_fd_opt, "Screen size: (%d - %d)\n",
- ws.ws_row, ws.ws_col);
- if (argc == 0)
- return (BSDDIALOG_OK);
- }
- if (argc < 3) {
- usage();
- return (255);
- }
- if (dialogbuilder == textbox_builder)
- text = argv[0];
- else {
- if ((text = malloc(strlen(argv[0]) + 1)) == NULL) {
- printf("Error: cannot allocate memory for text\n");
- return (255);
- }
- custom_text(cr_wrap_opt, no_collapse_opt, no_nl_expand_opt,
- trim_opt, argv[0], text);
- }
- rows = (int)strtol(argv[1], NULL, 10);
- cols = (int)strtol(argv[2], NULL, 10);
- argc -= 3;
- argv += 3;
-
- /* bsddialog terminal mode */
- if (bsddialog_init() != 0) {
- printf("Error: %s\n", bsddialog_geterror());
- return (BSDDIALOG_ERROR);
- }
+ return (parsed);
+}
- signal(SIGINT, sigint_handler);
+int main(int argc, char *argv[argc])
+{
+ int i, rows, cols, retval, parsed, nargc, firstoptind;
+ char *text, **nargv, *pn;
+ struct bsddialog_conf conf;
- if (theme_opt != BSDDIALOG_THEME_FLAT)
- bsddialog_set_default_theme(theme_opt);
+ setlocale(LC_ALL, "");
- if (backtitle_opt != NULL)
- bsddialog_backtitle(&conf, backtitle_opt);
+ in_bsddialog_mode = false;
+ mandatory_dialog = true;
+ firstoptind = optind;
+ pn = argv[0];
+ retval = BSDDIALOG_OK;
- errorbuilder[0] = '\0';
- output = BSDDIALOG_OK;
- if (dialogbuilder != NULL)
- output = dialogbuilder(conf, text, rows, cols, argc, argv,
- errorbuilder);
+ for (i = 0; i < argc; i++) {
+ if (strcmp(argv[i], "--version") == 0) {
+ printf("Version: %s\n", LIBBSDDIALOG_VERSION);
+ return (BSDDIALOG_OK);
+ }
+ if (strcmp(argv[i], "--help") == 0) {
+ usage();
+ return (BSDDIALOG_OK);
+ }
+ }
- if (dialogbuilder != textbox_builder)
- free(text);
+ while (true) {
+ parsed = parseargs(argc, argv, &conf);
+ nargc = argc - parsed;
+ nargv = argv + parsed;
+ argc = parsed - optind;
+ argv += optind;
- bsddialog_end();
- /* end bsddialog terminal mode */
+ if (mandatory_dialog && dialogbuilder == NULL)
+ exit_error("expected a --<dialog>", true);
- if (output == BSDDIALOG_ERROR) {
- if (errorbuilder[0] != '\0')
- printf("Error: %s\n", errorbuilder);
- else
- printf("Error: %s\n", bsddialog_geterror());
- return (255);
- }
+ if (dialogbuilder == NULL && argc > 0)
+ error_args("(no --<dialog>)", argc, argv);
- if (conf.get_height != NULL && conf.get_width != NULL)
- dprintf(output_fd_opt, "Dialog size: (%d - %d)\n",
- *conf.get_height, *conf.get_width);
+ /* --print-maxsize or --print-version */
+ if (mandatory_dialog == false && savethemefile == NULL &&
+ clear_screen_opt == false)
+ return (BSDDIALOG_OK);
- if (output == BSDDIALOG_ESC && esc_cancelvalue_opt)
- output = BSDDIALOG_CANCEL;
+ /* --<dialog>, --save-theme or clear-screen */
+ if (dialogbuilder != NULL) {
+ if (argc < 3)
+ exit_error("expected <text> <rows> <cols>",
+ true);
+ if ((text = strdup(argv[0])) == NULL)
+ exit_error("cannot allocate text", false);
+ if (dialogbuilder != textbox_builder)
+ custom_text(argv[0], text);
+ rows = (int)strtol(argv[1], NULL, 10);
+ cols = (int)strtol(argv[2], NULL, 10);
+ argc -= 3;
+ argv += 3;
+ }
- return (output);
-}
+ /* bsddialog terminal mode (first iteration) */
+ start_bsddialog_mode();
+
+ if (screen_mode_opt != NULL) {
+ screen_mode_opt = tigetstr(screen_mode_opt);
+ if (screen_mode_opt != NULL &&
+ screen_mode_opt != (char*)-1) {
+ tputs(screen_mode_opt, 1, putchar);
+ fflush(stdout);
+ /* only to refresh, useless in the library */
+ bsddialog_clearterminal();
+ }
+ }
-void sigint_handler(int sig)
-{
- bsddialog_end();
+ /* theme */
+ if (theme_opt >= 0)
+ bsddialog_set_default_theme(theme_opt);
+ if (loadthemefile != NULL)
+ loadtheme(loadthemefile);
+ if (bikeshed_opt)
+ bikeshed(&conf);
+ if (savethemefile != NULL)
+ savetheme(savethemefile, LIBBSDDIALOG_VERSION);
+
+ /* backtitle and dialog */
+ if (dialogbuilder == NULL)
+ break;
+ if (backtitle_opt != NULL)
+ if(bsddialog_backtitle(&conf, backtitle_opt))
+ exit_error(bsddialog_geterror(), false);
+ retval = dialogbuilder(&conf, text, rows, cols, argc, argv);
+ free(text);
+ if (retval == BSDDIALOG_ERROR)
+ exit_error(bsddialog_geterror(), false);
+ if (retval == BSDDIALOG_ESC && esc_return_cancel_opt)
+ retval = BSDDIALOG_CANCEL;
+ if (conf.get_height != NULL && conf.get_width != NULL)
+ dprintf(output_fd_opt, "DialogSize: %d, %d\n",
+ *conf.get_height, *conf.get_width);
+ if (clear_screen_opt)
+ bsddialog_clearterminal();
+ clear_screen_opt = false;
+ /* --and-dialog ends loop with Cancel or ESC */
+ if (retval == BSDDIALOG_CANCEL || retval == BSDDIALOG_ESC)
+ break;
+ argc = nargc;
+ argv = nargv;
+ if (argc <= 0)
+ break;
+ /* prepare next parseargs() call */
+ argc++;
+ argv--;
+ argv[0] = pn;
+ optind = firstoptind;
+ }
- exit(255);
+ if (in_bsddialog_mode) {
+ /* --clear-screen can be a single option */
+ if (clear_screen_opt)
+ bsddialog_clearterminal();
+ bsddialog_end();
+ }
+ /* end bsddialog terminal mode */
+
+ return (retval);
}
-void
-custom_text(bool cr_wrap, bool no_collapse, bool no_nl_expand, bool trim,
- char *text, char *buf)
+void custom_text(char *text, char *buf)
{
+ bool trim, crwrap;
int i, j;
+ if (strstr(text, "\\n") == NULL) {
+ /* "hasnl" mode */
+ trim = true;
+ crwrap = true;
+ } else {
+ trim = false;
+ crwrap = cr_wrap_opt;
+ }
+ if (text_unchanged_opt) {
+ trim = false;
+ crwrap = true;
+ }
+
i = j = 0;
while (text[i] != '\0') {
switch (text[i]) {
case '\\':
buf[j] = '\\';
switch (text[i+1]) {
- case '\\':
- i++;
- break;
- case 'n':
- if (no_nl_expand) {
- j++;
- buf[j] = 'n';
- } else
- buf[j] = '\n';
+ case 'n': /* implicitly in "hasnl" mode */
+ buf[j] = '\n';
i++;
+ if (text[i+1] == '\n')
+ i++;
break;
case 't':
- if (no_collapse) {
+ if (tab_escape_opt) {
+ buf[j] = '\t';
+ } else {
j++;
buf[j] = 't';
- } else
- buf[j] = '\t';
+ }
i++;
break;
}
break;
case '\n':
- buf[j] = cr_wrap ? ' ' : '\n';
+ buf[j] = crwrap ? '\n' : ' ';
break;
case '\t':
- buf[j] = no_collapse ? '\t' : ' ';
+ buf[j] = text_unchanged_opt ? '\t' : ' ';
break;
default:
buf[j] = text[i];
}
i++;
- j += (buf[j] == ' ' && trim && j > 0 && buf[j-1] == ' ') ?
- 0 : 1;
+ if (!trim || buf[j] != ' ' || j == 0 || buf[j-1] != ' ')
+ j++;
}
buf[j] = '\0';
}
@@ -774,14 +1019,15 @@ int gauge_builder(BUILDER_ARGS)
int output;
unsigned int perc;
- if (argc > 0) {
- perc = argc > 0 ? (u_int)strtoul(argv[0], NULL, 10) : 0;
+ perc = 0;
+ if (argc == 1) {
+ perc = (u_int)strtoul(argv[0], NULL, 10);
perc = perc > 100 ? 100 : perc;
+ } else if (argc > 1) {
+ error_args("--gauge", argc - 1, argv + 1);
}
- else
- perc = 0;
- output = bsddialog_gauge(&conf, text, rows, cols, perc, STDIN_FILENO,
+ output = bsddialog_gauge(conf, text, rows, cols, perc, STDIN_FILENO,
"XXX");
return (output);
@@ -789,11 +1035,10 @@ int gauge_builder(BUILDER_ARGS)
int infobox_builder(BUILDER_ARGS)
{
- int output;
+ if (argc > 0)
+ error_args("--infobox", argc, argv);
- output = bsddialog_infobox(&conf, text, rows, cols);
-
- return (output);
+ return (bsddialog_infobox(conf, text, rows, cols));
}
int mixedgauge_builder(BUILDER_ARGS)
@@ -802,10 +1047,8 @@ int mixedgauge_builder(BUILDER_ARGS)
unsigned int i, mainperc, nminibars;
const char **minilabels;
- if (argc < 1 || (((argc-1) % 2) != 0) ) {
- strcpy(errbuf, "bad --mixedgauge arguments\n");
- return (BSDDIALOG_ERROR);
- }
+ if (argc < 1 || (((argc-1) % 2) != 0) )
+ exit_error("bad --mixedgauge arguments", true);
mainperc = (u_int)strtoul(argv[0], NULL, 10);
mainperc = mainperc > 100 ? 100 : mainperc;
@@ -813,21 +1056,17 @@ int mixedgauge_builder(BUILDER_ARGS)
argv++;
nminibars = argc / 2;
- if ((minilabels = calloc(nminibars, sizeof(char*))) == NULL) {
- strcpy(errbuf, "Cannot allocate memory for minilabels\n");
- return BSDDIALOG_ERROR;
- }
- if ((minipercs = calloc(nminibars, sizeof(int))) == NULL) {
- strcpy(errbuf, "Cannot allocate memory for minipercs\n");
- return BSDDIALOG_ERROR;
- }
+ if ((minilabels = calloc(nminibars, sizeof(char*))) == NULL)
+ exit_error("Cannot allocate memory for minilabels", false);
+ if ((minipercs = calloc(nminibars, sizeof(int))) == NULL)
+ exit_error("Cannot allocate memory for minipercs", false);
for (i = 0; i < nminibars; i++) {
minilabels[i] = argv[i * 2];
minipercs[i] = (int)strtol(argv[i * 2 + 1], NULL, 10);
}
- output = bsddialog_mixedgauge(&conf, text, rows, cols, mainperc,
+ output = bsddialog_mixedgauge(conf, text, rows, cols, mainperc,
nminibars, minilabels, minipercs);
return (output);
@@ -835,11 +1074,10 @@ int mixedgauge_builder(BUILDER_ARGS)
int msgbox_builder(BUILDER_ARGS)
{
- int output;
-
- output = bsddialog_msgbox(&conf, text, rows, cols);
+ if (argc > 0)
+ error_args("--msgbox", argc, argv);
- return (output);
+ return (bsddialog_msgbox(conf, text, rows, cols));
}
int pause_builder(BUILDER_ARGS)
@@ -847,13 +1085,13 @@ int pause_builder(BUILDER_ARGS)
int output;
unsigned int secs;
- if (argc < 1) {
- strcpy(errbuf, "missing <seconds> for --pause\n");
- return (BSDDIALOG_ERROR);
- }
+ if (argc == 0)
+ exit_error("--pause missing <seconds>", true);
+ if (argc > 1)
+ error_args("--pause", argc - 1, argv + 1);
secs = (u_int)strtoul(argv[0], NULL, 10);
- output = bsddialog_pause(&conf, text, rows, cols, secs);
+ output = bsddialog_pause(conf, text, rows, cols, secs);
return (output);
}
@@ -862,25 +1100,22 @@ int rangebox_builder(BUILDER_ARGS)
{
int output, min, max, value;
- if (argc < 2) {
- strcpy(errbuf, "usage --rangebox <text> <rows> <cols> "
- "<min> <max> [<init>]\n");
- return (BSDDIALOG_ERROR);
- }
+ if (argc < 2)
+ exit_error("--rangebox missing <min> <max> [<init>]", true);
+ if (argc > 3)
+ error_args("--rangebox", argc - 3, argv + 3);
min = (int)strtol(argv[0], NULL, 10);
max = (int)strtol(argv[1], NULL, 10);
- if (argc > 2) {
+ if (argc == 3) {
value = (int)strtol(argv[2], NULL, 10);
value = value < min ? min : value;
value = value > max ? max : value;
- }
- else
+ } else
value = min;
- output = bsddialog_rangebox(&conf, text, rows, cols, min, max, &value);
-
+ output = bsddialog_rangebox(conf, text, rows, cols, min, max, &value);
dprintf(output_fd_opt, "%d", value);
return (output);
@@ -888,50 +1123,56 @@ int rangebox_builder(BUILDER_ARGS)
int textbox_builder(BUILDER_ARGS)
{
- int output;
-
- output = bsddialog_textbox(&conf, text, rows, cols);
+ if (argc > 0)
+ error_args("--textbox", argc, argv);
- return (output);
+ return (bsddialog_textbox(conf, text, rows, cols));
}
int yesno_builder(BUILDER_ARGS)
{
- int output;
-
- output = bsddialog_yesno(&conf, text, rows, cols);
+ if (argc > 0)
+ error_args("--yesno", argc, argv);
- return (output);
+ return (bsddialog_yesno(conf, text, rows, cols));
}
-/* DATE and TIME */
-int datebox_builder(BUILDER_ARGS)
+/* CALENDAR, DATE and TIME */
+static int date(BUILDER_ARGS, bool is_datebox)
{
- int output;
+ int ret;
unsigned int yy, mm, dd;
time_t cal;
struct tm *localtm;
char stringdate[1024];
+ const char *name;
+ name = is_datebox ? "--datebox" : "--calendar";
time(&cal);
localtm = localtime(&cal);
yy = localtm->tm_year + 1900;
mm = localtm->tm_mon + 1;
dd = localtm->tm_mday;
- if (argc == 3) {
- yy = (u_int)strtoul(argv[0], NULL, 10);
+ if (argc > 3) {
+ error_args(name, argc - 3, argv + 3);
+ } else if (argc == 3) {
+ dd = (u_int)strtoul(argv[0], NULL, 10);
mm = (u_int)strtoul(argv[1], NULL, 10);
- dd = (u_int)strtoul(argv[2], NULL, 10);
+ yy = (u_int)strtoul(argv[2], NULL, 10);
+ if (yy < 1900)
+ yy = 1900;
+ /* max yy check is in lib */
}
- output = bsddialog_datebox(&conf, text, rows, cols, &yy, &mm, &dd);
- if (output != BSDDIALOG_OK)
- return (output);
+ if (is_datebox)
+ ret = bsddialog_datebox(conf, text, rows, cols, &yy, &mm, &dd);
+ else
+ ret = bsddialog_calendar(conf, text, rows, cols, &yy, &mm, &dd);
+ if (ret != BSDDIALOG_OK)
+ return (ret);
- if (date_fmt_opt == NULL) {
- dprintf(output_fd_opt, "%u/%u/%u", yy, mm, dd);
- } else {
+ if (date_fmt_opt != NULL) {
time(&cal);
localtm = localtime(&cal);
localtm->tm_year = yy - 1900;
@@ -939,9 +1180,37 @@ int datebox_builder(BUILDER_ARGS)
localtm->tm_mday = dd;
strftime(stringdate, 1024, date_fmt_opt, localtm);
dprintf(output_fd_opt, "%s", stringdate);
+ } else if (bikeshed_opt && (dd % 2 == 0)) {
+ dprintf(output_fd_opt, "%u/%u/%u", dd, mm, yy);
+ } else {
+ dprintf(output_fd_opt, "%02u/%02u/%u", dd, mm, yy);
}
- return (output);
+ return (ret);
+}
+
+int calendar_builder(BUILDER_ARGS)
+{
+ if (rows == 2) {
+ /*
+ * (bsdconfig/share/dialog.subr:1352) f_dialog_calendar_size()
+ * computes height 2 for `dialog --calendar' in
+ * (bsdconfig/usermgmt/share/user_input.subr:517)
+ * f_dialog_input_expire_password() and
+ * (bsdconfig/usermgmt/share/user_input.subr:660)
+ * f_dialog_input_expire_account().
+ * Use height auto-sizing that is min height like dialog,
+ * documented in bsddialog(1).
+ */
+ rows = 0;
+ }
+
+ return (date(conf, text, rows, cols, argc, argv, false));
+}
+
+int datebox_builder(BUILDER_ARGS)
+{
+ return (date(conf, text, rows, cols, argc, argv, true));
}
int timebox_builder(BUILDER_ARGS)
@@ -958,19 +1227,19 @@ int timebox_builder(BUILDER_ARGS)
mm = localtm->tm_min;
ss = localtm->tm_sec;
- if (argc == 3) {
+ if (argc > 3) {
+ error_args("--timebox", argc - 3, argv + 3);
+ } else if (argc == 3) {
hh = (u_int)strtoul(argv[0], NULL, 10);
mm = (u_int)strtoul(argv[1], NULL, 10);
ss = (u_int)strtoul(argv[2], NULL, 10);
}
- output = bsddialog_timebox(&conf, text, rows, cols, &hh, &mm, &ss);
+ output = bsddialog_timebox(conf, text, rows, cols, &hh, &mm, &ss);
if (output != BSDDIALOG_OK)
return (output);
- if (time_fmt_opt == NULL) {
- dprintf(output_fd_opt, "%u:%u:%u", hh, mm, ss);
- } else {
+ if (time_fmt_opt != NULL) {
time(&clock);
localtm = localtime(&clock);
localtm->tm_hour = hh;
@@ -978,15 +1247,19 @@ int timebox_builder(BUILDER_ARGS)
localtm->tm_sec = ss;
strftime(stringtime, 1024, time_fmt_opt, localtm);
dprintf(output_fd_opt, "%s", stringtime);
+ } else if (bikeshed_opt && (ss % 2 == 0)) {
+ dprintf(output_fd_opt, "%u:%u:%u", hh, mm, ss);
+ } else {
+ dprintf(output_fd_opt, "%02u:%02u:%02u", hh, mm, ss);
}
return (output);
}
/* MENU */
-static int
-get_menu_items(char *errbuf, int argc, char **argv, bool setprefix,
- bool setdepth, bool setname, bool setdesc, bool setstatus, bool sethelp,
+static void
+get_menu_items(int argc, char **argv, bool setprefix, bool setdepth,
+ bool setname, bool setdesc, bool setstatus, bool sethelp,
unsigned int *nitems, struct bsddialog_menuitem **items, int *focusitem)
{
unsigned int i, j, sizeitem;
@@ -1000,17 +1273,14 @@ get_menu_items(char *errbuf, int argc, char **argv, bool setprefix,
sizeitem += setdesc ? 1 : 0;
sizeitem += setstatus ? 1 : 0;
sizeitem += sethelp ? 1 : 0;
- if ((argc % sizeitem) != 0) {
- strcpy(errbuf, "bad number of arguments for this menu\n");
- return (BSDDIALOG_ERROR);
- }
+ if ((argc % sizeitem) != 0)
+ exit_error("\"menu\" bad arguments items number", true);
+
*nitems = argc / sizeitem;
*items = calloc(*nitems, sizeof(struct bsddialog_menuitem));
- if (items == NULL) {
- strcpy(errbuf, "cannot allocate memory menu items\n");
- return (BSDDIALOG_ERROR);
- }
+ if (items == NULL)
+ exit_error("cannot allocate memory \"menu\" items", false);
j = 0;
for (i = 0; i < *nitems; i++) {
@@ -1030,71 +1300,86 @@ get_menu_items(char *errbuf, int argc, char **argv, bool setprefix,
if (strcmp((*items)[i].name, item_default_opt) == 0)
*focusitem = i;
}
-
- return (BSDDIALOG_OK);
}
static void
print_menu_items(int output, int nitems, struct bsddialog_menuitem *items,
- int focusitem)
+ int focusitem, bool ismenu)
{
- bool sep, toquote;
+ bool sep, sepfirst, seplast, toquote;
int i;
- char *sepstr, quotech;
- const char *focusname;
+ char quotech;
+ const char *focusname, *sepstr;
sep = false;
quotech = item_singlequote_opt ? '\'' : '"';
- sepstr = item_output_sep_opt != NULL ? item_output_sep_opt : " ";
- if (output != BSDDIALOG_OK && output != BSDDIALOG_ERROR &&
- focusitem >= 0) {
- focusname = items[focusitem].name;
+ if (output == BSDDIALOG_ERROR || output == BSDDIALOG_CANCEL ||
+ output == BSDDIALOG_ESC)
+ return;
- if (output == BSDDIALOG_HELP) {
- dprintf(output_fd_opt, "HELP ");
+ if (output == BSDDIALOG_HELP) {
+ dprintf(output_fd_opt, "HELP ");
- if (item_bottomdesc_opt && item_tag_help_opt == false)
+ if (focusitem >= 0) {
+ focusname = items[focusitem].name;
+ if (item_bottomdesc_opt &&
+ item_help_print_name_opt == false)
focusname = items[focusitem].bottomdesc;
- }
- toquote = item_always_quote_opt ||
- (item_output_sepnl_opt == false &&
- strchr(focusname, ' ') != NULL);
-
- if (toquote)
- dprintf(output_fd_opt, "%c", quotech);
- dprintf(output_fd_opt, "%s", focusname);
- if (toquote)
- dprintf(output_fd_opt, "%c", quotech);
+ toquote = false;
+ if (strchr(focusname, ' ') != NULL) {
+ toquote = item_always_quote_opt;
+ if (ismenu == false &&
+ item_output_sepnl_opt == false)
+ toquote = true;
+ }
+ if (toquote) {
+ dprintf(output_fd_opt, "%c%s%c",
+ quotech, focusname, quotech);
+ } else
+ dprintf(output_fd_opt, "%s", focusname);
+ }
+ if (ismenu || list_items_on_opt == false)
+ return;
sep = true;
}
- if (output != BSDDIALOG_OK &&
- !(output == BSDDIALOG_HELP && list_items_on_opt))
- return;
+ sepfirst = false;
+ if ((sepstr = item_output_sep_opt) == NULL)
+ sepstr = item_output_sepnl_opt ? "\n" : " ";
+ else
+ sepfirst = true;
+
+ seplast = false;
+ if (item_output_sepnl_opt) {
+ sepfirst = false;
+ seplast = true;
+ }
for (i = 0; i < nitems; i++) {
if (items[i].on == false)
continue;
- if (sep == true) {
+ if (sep || sepfirst)
dprintf(output_fd_opt, "%s", sepstr);
- if (item_output_sepnl_opt)
- dprintf(output_fd_opt, "\n");
- }
- sep = true;
-
- toquote = item_always_quote_opt ||
- (item_output_sepnl_opt == false &&
- strchr(items[i].name, ' ') != NULL);
+ sep = false;
+ toquote = false;
+ if (strchr(items[i].name, ' ') != NULL) {
+ toquote = item_always_quote_opt;
+ if (ismenu == false && item_output_sepnl_opt == false)
+ toquote = true;
+ }
if (toquote)
- dprintf(output_fd_opt, "%c", quotech);
- dprintf(output_fd_opt, "%s", items[i].name);
- if (toquote)
- dprintf(output_fd_opt, "%c", quotech);
+ dprintf(output_fd_opt, "%c%s%c",
+ quotech, items[i].name, quotech);
+ else
+ dprintf(output_fd_opt, "%s", items[i].name);
+
+ if (seplast)
+ dprintf(output_fd_opt, "%s", sepstr);
}
}
@@ -1104,23 +1389,17 @@ int checklist_builder(BUILDER_ARGS)
unsigned int menurows, nitems;
struct bsddialog_menuitem *items;
- if (argc < 1) {
- strcpy(errbuf, "<menurows> not provided");
- return (BSDDIALOG_ERROR);
- }
-
+ if (argc < 1)
+ exit_error("--checklist missing <menurows>", true);
menurows = (u_int)strtoul(argv[0], NULL, 10);
- output = get_menu_items(errbuf, argc-1, argv+1, item_prefix_opt,
- item_depth_opt, true, true, true, item_bottomdesc_opt, &nitems,
- &items, &focusitem);
- if (output != 0)
- return (output);
+ get_menu_items(argc-1, argv+1, item_prefix_opt, item_depth_opt, true,
+ true, true, item_bottomdesc_opt, &nitems, &items, &focusitem);
- output = bsddialog_checklist(&conf, text, rows, cols, menurows, nitems,
+ output = bsddialog_checklist(conf, text, rows, cols, menurows, nitems,
items, &focusitem);
- print_menu_items(output, nitems, items, focusitem);
+ print_menu_items(output, nitems, items, focusitem, false);
free(items);
@@ -1133,23 +1412,17 @@ int menu_builder(BUILDER_ARGS)
unsigned int menurows, nitems;
struct bsddialog_menuitem *items;
- if (argc < 1) {
- strcpy(errbuf, "<menurows> not provided");
- return (BSDDIALOG_ERROR);
- }
-
+ if (argc < 1)
+ exit_error("--menu missing <menurows>", true);
menurows = (u_int)strtoul(argv[0], NULL, 10);
- output = get_menu_items(errbuf, argc-1, argv+1, item_prefix_opt,
- item_depth_opt, true, true, false, item_bottomdesc_opt, &nitems,
- &items, &focusitem);
- if (output != 0)
- return (output);
+ get_menu_items(argc-1, argv+1, item_prefix_opt, item_depth_opt, true,
+ true, false, item_bottomdesc_opt, &nitems, &items, &focusitem);
- output = bsddialog_menu(&conf, text, rows, cols, menurows, nitems,
+ output = bsddialog_menu(conf, text, rows, cols, menurows, nitems,
items, &focusitem);
- print_menu_items(output, nitems, items, focusitem);
+ print_menu_items(output, nitems, items, focusitem, true);
free(items);
@@ -1162,23 +1435,17 @@ int radiolist_builder(BUILDER_ARGS)
unsigned int menurows, nitems;
struct bsddialog_menuitem *items;
- if (argc < 1) {
- strcpy(errbuf, "<menurows> not provided");
- return (BSDDIALOG_ERROR);
- }
-
+ if (argc < 1)
+ exit_error("--radiolist missing <menurows>", true);
menurows = (u_int)strtoul(argv[0], NULL, 10);
- output = get_menu_items(errbuf, argc-1, argv+1, item_prefix_opt,
- item_depth_opt, true, true, true, item_bottomdesc_opt, &nitems,
- &items, &focusitem);
- if (output != 0)
- return (output);
+ get_menu_items(argc-1, argv+1, item_prefix_opt, item_depth_opt, true,
+ true, true, item_bottomdesc_opt, &nitems, &items, &focusitem);
- output = bsddialog_radiolist(&conf, text, rows, cols, menurows, nitems,
+ output = bsddialog_radiolist(conf, text, rows, cols, menurows, nitems,
items, &focusitem);
- print_menu_items(output, nitems, items, focusitem);
+ print_menu_items(output, nitems, items, focusitem, false);
free(items);
@@ -1191,26 +1458,20 @@ int treeview_builder(BUILDER_ARGS)
unsigned int menurows, nitems;
struct bsddialog_menuitem *items;
- if (argc < 1) {
- strcpy(errbuf, "<menurows> not provided");
- return (BSDDIALOG_ERROR);
- }
-
+ if (argc < 1)
+ exit_error("--treeview missing <menurows>", true);
menurows = (u_int)strtoul(argv[0], NULL, 10);
- output = get_menu_items(errbuf, argc-1, argv+1, item_prefix_opt,
- true, true, true, true, item_bottomdesc_opt, &nitems, &items,
- &focusitem);
- if (output != 0)
- return (output);
+ get_menu_items(argc-1, argv+1, item_prefix_opt, true, true, true, true,
+ item_bottomdesc_opt, &nitems, &items, &focusitem);
- conf.menu.no_name = true;
- conf.menu.align_left = true;
+ conf->menu.no_name = true;
+ conf->menu.align_left = true;
- output = bsddialog_radiolist(&conf, text, rows, cols, menurows, nitems,
+ output = bsddialog_radiolist(conf, text, rows, cols, menurows, nitems,
items, &focusitem);
- print_menu_items(output, nitems, items, focusitem);
+ print_menu_items(output, nitems, items, focusitem, false);
free(items);
@@ -1218,18 +1479,6 @@ int treeview_builder(BUILDER_ARGS)
}
/* FORM */
-static int
-alloc_formitems(int nitems, struct bsddialog_formitem **items, char *errbuf)
-{
- *items = calloc(nitems, sizeof(struct bsddialog_formitem));
- if (items == NULL) {
- strcpy(errbuf, "cannot allocate memory for form items\n");
- return (BSDDIALOG_ERROR);
- }
-
- return (BSDDIALOG_OK);
-}
-
static void
print_form_items(int output, int nitems, struct bsddialog_formitem *items)
{
@@ -1239,7 +1488,7 @@ print_form_items(int output, int nitems, struct bsddialog_formitem *items)
return;
for (i = 0; i < nitems; i++) {
- dprintf(output_fd_opt, "%ls\n", (wchar_t*)items[i].value);
+ dprintf(output_fd_opt, "%s\n", items[i].value);
free(items[i].value);
}
}
@@ -1250,21 +1499,19 @@ int form_builder(BUILDER_ARGS)
unsigned int i, j, flags, formheight, nitems, sizeitem;
struct bsddialog_formitem *items;
- sizeitem = item_bottomdesc_opt ? 9 : 8;
- if (argc < 1 || (argc - 1) % sizeitem != 0) {
- strcpy(errbuf, "bad number of arguments for this form\n");
- return (BSDDIALOG_ERROR);
- }
-
+ if (argc < 1)
+ exit_error("--form missing <formheight>", true);
formheight = (u_int)strtoul(argv[0], NULL, 10);
- flags = 0;
argc--;
argv++;
+ sizeitem = item_bottomdesc_opt ? 9 : 8;
+ if (argc % sizeitem != 0)
+ exit_error("--form bad number of arguments items", true);
nitems = argc / sizeitem;
- if (alloc_formitems(nitems, &items, errbuf) != BSDDIALOG_OK)
- return (BSDDIALOG_ERROR);
+ if ((items = calloc(nitems, sizeof(struct bsddialog_formitem))) == NULL)
+ exit_error("cannot allocate memory for form items", false);
j = 0;
for (i = 0; i < nitems; i++) {
items[i].label = argv[j++];
@@ -1280,13 +1527,13 @@ int form_builder(BUILDER_ARGS)
valuelen = (int)strtol(argv[j++], NULL, 10);
items[i].maxvaluelen = valuelen == 0 ? abs(fieldlen) : valuelen;
- flags |= (fieldlen < 0 ? BSDDIALOG_FIELDREADONLY : 0);
+ flags = (fieldlen < 0 ? BSDDIALOG_FIELDREADONLY : 0);
items[i].flags = flags;
items[i].bottomdesc = item_bottomdesc_opt ? argv[j++] : "";
}
- output = bsddialog_form(&conf, text, rows, cols, formheight, nitems,
+ output = bsddialog_form(conf, text, rows, cols, formheight, nitems,
items);
print_form_items(output, nitems, items);
free(items);
@@ -1299,18 +1546,23 @@ int inputbox_builder(BUILDER_ARGS)
int output;
struct bsddialog_formitem item;
+ if (argc > 1)
+ error_args("--inputbox", argc - 1, argv + 1);
+
item.label = "";
item.ylabel = 0;
item.xlabel = 0;
item.init = argc > 0 ? argv[0] : "";
- item.yfield = 1;
- item.xfield = 1;
- item.fieldlen = cols > 4 ? cols-4 : 25;
- item.maxvaluelen = max_input_form_opt > 0 ? max_input_form_opt : 2048;
- item.flags = 0;
+ item.yfield = 0;
+ item.xfield = 0;
+ item.fieldlen = 1;
+ item.maxvaluelen = max_input_form_opt;
+ item.flags = BSDDIALOG_FIELDNOCOLOR;
+ item.flags |= BSDDIALOG_FIELDCURSOREND;
+ item.flags |= BSDDIALOG_FIELDEXTEND;
item.bottomdesc = "";
- output = bsddialog_form(&conf, text, rows, cols, 1, 1, &item);
+ output = bsddialog_form(conf, text, rows, cols, 1, 1, &item);
print_form_items(output, 1, &item);
return (output);
@@ -1322,20 +1574,19 @@ int mixedform_builder(BUILDER_ARGS)
unsigned int i, j, formheight, nitems, sizeitem;
struct bsddialog_formitem *items;
- sizeitem = item_bottomdesc_opt ? 10 : 9;
- if (argc < 1 || (argc-1) % sizeitem != 0) {
- strcpy(errbuf, "bad number of arguments for this form\n");
- return (BSDDIALOG_ERROR);
- }
-
+ if (argc < 1)
+ exit_error("--mixedform missing <formheight>", true);
formheight = (u_int)strtoul(argv[0], NULL, 10);
argc--;
argv++;
+ sizeitem = item_bottomdesc_opt ? 10 : 9;
+ if (argc % sizeitem != 0)
+ exit_error("--mixedform bad number of arguments items", true);
nitems = argc / sizeitem;
- if (alloc_formitems(nitems, &items, errbuf) != BSDDIALOG_OK)
- return (BSDDIALOG_ERROR);
+ if ((items = calloc(nitems, sizeof(struct bsddialog_formitem))) == NULL)
+ exit_error("cannot allocate memory for form items", false);
j = 0;
for (i = 0; i < nitems; i++) {
items[i].label = argv[j++];
@@ -1350,7 +1601,7 @@ int mixedform_builder(BUILDER_ARGS)
items[i].bottomdesc = item_bottomdesc_opt ? argv[j++] : "";
}
- output = bsddialog_form(&conf, text, rows, cols, formheight, nitems,
+ output = bsddialog_form(conf, text, rows, cols, formheight, nitems,
items);
print_form_items(output, nitems, items);
free(items);
@@ -1363,18 +1614,24 @@ int passwordbox_builder(BUILDER_ARGS)
int output;
struct bsddialog_formitem item;
+ if (argc > 1)
+ error_args("--passwordbox", argc - 1, argv + 1);
+
item.label = "";
item.ylabel = 0;
item.xlabel = 0;
item.init = argc > 0 ? argv[0] : "";
- item.yfield = 1;
- item.xfield = 1;
- item.fieldlen = cols > 4 ? cols-4 : 25;
- item.maxvaluelen = max_input_form_opt > 0 ? max_input_form_opt : 2048;
+ item.yfield = 0;
+ item.xfield = 0;
+ item.fieldlen = 1;
+ item.maxvaluelen = max_input_form_opt;
item.flags = BSDDIALOG_FIELDHIDDEN;
+ item.flags |= BSDDIALOG_FIELDNOCOLOR;
+ item.flags |= BSDDIALOG_FIELDCURSOREND;
+ item.flags |= BSDDIALOG_FIELDEXTEND;
item.bottomdesc = "";
- output = bsddialog_form(&conf, text, rows, cols, 1, 1, &item);
+ output = bsddialog_form(conf, text, rows, cols, 1, 1, &item);
print_form_items(output, 1, &item);
return (output);
@@ -1386,21 +1643,20 @@ int passwordform_builder(BUILDER_ARGS)
unsigned int i, j, flags, formheight, nitems, sizeitem;
struct bsddialog_formitem *items;
- sizeitem = item_bottomdesc_opt ? 9 : 8;
- if (argc < 1 || (argc - 1) % sizeitem != 0) {
- strcpy(errbuf, "bad number of arguments for this form\n");
- return (BSDDIALOG_ERROR);
- }
-
+ if (argc < 1)
+ exit_error("--passwordform missing <formheight>", true);
formheight = (u_int)strtoul(argv[0], NULL, 10);
- flags = BSDDIALOG_FIELDHIDDEN;
argc--;
argv++;
+ sizeitem = item_bottomdesc_opt ? 9 : 8;
+ if (argc % sizeitem != 0)
+ exit_error("--passwordform bad arguments items number", true);
+ flags = BSDDIALOG_FIELDHIDDEN;
nitems = argc / sizeitem;
- if (alloc_formitems(nitems, &items, errbuf) != BSDDIALOG_OK)
- return (BSDDIALOG_ERROR);
+ if ((items = calloc(nitems, sizeof(struct bsddialog_formitem))) == NULL)
+ exit_error("cannot allocate memory for form items", false);
j = 0;
for (i = 0; i < nitems; i++) {
items[i].label = argv[j++];
@@ -1422,7 +1678,7 @@ int passwordform_builder(BUILDER_ARGS)
items[i].bottomdesc = item_bottomdesc_opt ? argv[j++] : "";
}
- output = bsddialog_form(&conf, text, rows, cols, formheight, nitems,
+ output = bsddialog_form(conf, text, rows, cols, formheight, nitems,
items);
print_form_items(output, nitems, items);
free(items);
diff --git a/contrib/bsddialog/examples_library/calendar.c b/contrib/bsddialog/examples_library/calendar.c
new file mode 100644
index 000000000000..33e38c69a81b
--- /dev/null
+++ b/contrib/bsddialog/examples_library/calendar.c
@@ -0,0 +1,55 @@
+/*-
+ * SPDX-License-Identifier: CC0-1.0
+ *
+ * Written in 2022 by Alfonso Sabato Siciliano.
+ * To the extent possible under law, the author has dedicated all copyright
+ * and related and neighboring rights to this software to the public domain
+ * worldwide. This software is distributed without any warranty, see:
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include <bsddialog.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+int main()
+{
+ int output;
+ unsigned int yy, mm, dd;
+ struct bsddialog_conf conf;
+ time_t cal;
+ struct tm *localtm;
+
+ time(&cal);
+ localtm = localtime(&cal);
+ yy = localtm->tm_year + 1900;
+ mm = localtm->tm_mon + 1;
+ dd = localtm->tm_mday;
+
+ if (bsddialog_init() == BSDDIALOG_ERROR) {
+ printf("Error: %s\n", bsddialog_geterror());
+ return (1);
+ }
+
+ bsddialog_initconf(&conf);
+ conf.title = "calendar";
+ output = bsddialog_calendar(&conf, "Example", 18, 40, &yy, &mm, &dd);
+
+ bsddialog_end();
+
+ switch (output) {
+ case BSDDIALOG_OK:
+ printf("Date: %u/%u/%u", yy, mm, dd);
+ break;
+ case BSDDIALOG_CANCEL:
+ printf("Cancel");
+ break;
+ case BSDDIALOG_ERROR:
+ printf("Error: %s", bsddialog_geterror());
+ break;
+ }
+ printf("\n");
+
+ return (output);
+} \ No newline at end of file
diff --git a/contrib/bsddialog/examples_library/compile b/contrib/bsddialog/examples_library/compile
index 3c3961d06baf..4cb6d23bd6a6 100755
--- a/contrib/bsddialog/examples_library/compile
+++ b/contrib/bsddialog/examples_library/compile
@@ -10,7 +10,9 @@
libpath=../lib
examples="menu checklist radiolist mixedlist theme infobox yesno msgbox \
- datebox form formw timebox rangebox pause"
+ datebox form timebox rangebox pause calendar"
+
+rm -f $examples
for e in $examples
do
diff --git a/contrib/bsddialog/examples_library/datebox.c b/contrib/bsddialog/examples_library/datebox.c
index a3c8946b7f79..7f0138688d53 100644
--- a/contrib/bsddialog/examples_library/datebox.c
+++ b/contrib/bsddialog/examples_library/datebox.c
@@ -34,9 +34,7 @@ int main()
bsddialog_initconf(&conf);
conf.title = "datebox";
- output = bsddialog_datebox(&conf,
- "TAB / RIGHT / LEFT to move,\nUP / DOWN to select time", 10, 35,
- &yy, &mm, &dd);
+ output = bsddialog_datebox(&conf, "Example", 9, 35, &yy, &mm, &dd);
bsddialog_end();
diff --git a/contrib/bsddialog/examples_library/form.c b/contrib/bsddialog/examples_library/form.c
index 0256975f2023..4780fb68d121 100644
--- a/contrib/bsddialog/examples_library/form.c
+++ b/contrib/bsddialog/examples_library/form.c
@@ -9,6 +9,7 @@
*/
#include <bsddialog.h>
+#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -21,21 +22,22 @@ int main()
int i, output;
struct bsddialog_conf conf;
struct bsddialog_formitem items[3] = {
- {"Input:", 1, 1, "value", 1, 11, 30, 50, NULL, 0, "desc 1"},
- {"Input:", 2, 1, "read only", 2, 11, 30, 50, NULL, RO, "desc 2"},
- {"Password:", 3, 1, "", 3, 11, 30, 50, NULL, H, "desc 3"}
+ {"Input:", 0, 0, "value", 0, 10, 30, 50, NULL, 0, "desc 1"},
+ {"Input:", 1, 0, "read only", 1, 10, 30, 50, NULL, RO, "desc 2"},
+ {"Password:", 2, 0, "", 2, 10, 30, 50, NULL, H, "desc 3"}
};
+ /* Optional, unless for unicode/multi-column characters */
+ setlocale(LC_ALL, "");
+
if (bsddialog_init() == BSDDIALOG_ERROR) {
printf("Error: %s\n", bsddialog_geterror());
return (1);
}
-
bsddialog_initconf(&conf);
conf.title = "form";
conf.form.securech = '*';
output = bsddialog_form(&conf, "Example", 10, 50, 3, 3, items);
-
bsddialog_end();
if (output == BSDDIALOG_ERROR) {
@@ -54,4 +56,4 @@ int main()
}
return (output);
-} \ No newline at end of file
+}
diff --git a/contrib/bsddialog/examples_library/formw.c b/contrib/bsddialog/examples_library/formw.c
deleted file mode 100644
index edbeec98f2a3..000000000000
--- a/contrib/bsddialog/examples_library/formw.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*-
- * SPDX-License-Identifier: CC0-1.0
- *
- * Written in 2022 by Alfonso Sabato Siciliano.
- * To the extent possible under law, the author has dedicated all copyright
- * and related and neighboring rights to this software to the public domain
- * worldwide. This software is distributed without any warranty, see:
- * <http://creativecommons.org/publicdomain/zero/1.0/>.
- */
-
-#include <bsddialog.h>
-#include <locale.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define H BSDDIALOG_FIELDHIDDEN
-#define RO BSDDIALOG_FIELDREADONLY
-
-int main()
-{
- int i, output;
- struct bsddialog_conf conf;
- struct bsddialog_formitem items[3] = {
- {"Input:", 1, 1, "value", 1, 11, 30, 50, NULL, 0, "desc 1"},
- {"Input:", 2, 1, "read only", 2, 11, 30, 50, NULL, RO, "desc 2"},
- {"Password:", 3, 1, "", 3, 11, 30, 50, NULL, H, "desc 3"}
- };
-
- setlocale(LC_ALL, "");
-
- if (bsddialog_init() == BSDDIALOG_ERROR) {
- printf("Error: %s\n", bsddialog_geterror());
- return (1);
- }
-
- bsddialog_initconf(&conf);
- conf.title = "form";
- conf.form.securech = '*';
- conf.form.enable_wchar = true;
- output = bsddialog_form(&conf, "Example", 10, 50, 3, 3, items);
-
- bsddialog_end();
-
- if (output == BSDDIALOG_ERROR) {
- printf("Error: %s", bsddialog_geterror());
- return (1);
- }
-
- if (output == BSDDIALOG_CANCEL) {
- printf("Cancel\n");
- return (0);
- }
-
- for (i = 0; i < 3; i++) {
- printf("%s \"%ls\"\n", items[i].label, (wchar_t*)items[i].value);
- free(items[i].value);
- }
-
- return (output);
-} \ No newline at end of file
diff --git a/contrib/bsddialog/examples_library/timebox.c b/contrib/bsddialog/examples_library/timebox.c
index 0e27f824af11..f06986423558 100644
--- a/contrib/bsddialog/examples_library/timebox.c
+++ b/contrib/bsddialog/examples_library/timebox.c
@@ -34,9 +34,7 @@ int main()
bsddialog_initconf(&conf);
conf.title = "timebox";
- output = bsddialog_timebox(&conf,
- "TAB / RIGHT / LEFT to move,\nUP / DOWN to select time", 10, 35,
- &hh, &mm, &ss);
+ output = bsddialog_timebox(&conf, "Example", 9, 35, &hh, &mm, &ss);
bsddialog_end();
diff --git a/contrib/bsddialog/examples_utility/calendar.sh b/contrib/bsddialog/examples_utility/calendar.sh
new file mode 100644
index 000000000000..a7ce4f1bb1d5
--- /dev/null
+++ b/contrib/bsddialog/examples_utility/calendar.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+#-
+# SPDX-License-Identifier: CC0-1.0
+#
+# Written in 2022 by Alfonso Sabato Siciliano.
+#
+# To the extent possible under law, the author has dedicated all copyright
+# and related and neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty, see:
+# <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+: ${BSDDIALOG_ERROR=255}
+: ${BSDDIALOG_OK=0}
+: ${BSDDIALOG_CANCEL=1}
+: ${BSDDIALOG_ESC=5}
+
+DATE=$(./bsddialog --title " calendar " --date-format "%x" \
+ --calendar "Hello World!" 20 40 \
+3>&1 1>&2 2>&3 3>&-)
+
+case $? in
+ $BSDDIALOG_ERROR )
+ exit 1
+ ;;
+ $BSDDIALOG_ESC )
+ echo "[ESC]"
+ ;;
+ $BSDDIALOG_CANCEL )
+ echo "[Cancel]"
+ ;;
+ $BSDDIALOG_OK )
+ echo "[OK] $DATE"
+ ;;
+esac
diff --git a/contrib/bsddialog/examples_utility/form.sh b/contrib/bsddialog/examples_utility/form.sh
index bd1bac8a3939..783993d3db30 100755
--- a/contrib/bsddialog/examples_utility/form.sh
+++ b/contrib/bsddialog/examples_utility/form.sh
@@ -15,11 +15,11 @@
: ${BSDDIALOG_ESC=5}
FORMS=$(./bsddialog --title " form " --form "Hello World!" 12 40 5 \
- Label1: 1 1 Value1 1 9 18 25 \
- Label2: 2 1 Value2 2 9 18 25 \
- Label3: 3 1 Value3 3 9 18 25 \
- Label4: 4 1 Value4 4 9 18 25 \
- Label5: 5 1 Value5 5 9 18 25 \
+ Label1: 0 0 Value1 0 8 18 25 \
+ Label2: 1 0 Value2 1 8 18 25 \
+ Label3: 2 0 Value3 2 8 18 25 \
+ Label4: 3 0 Value4 3 8 18 25 \
+ Label5: 4 0 Value5 4 8 18 25 \
3>&1 1>&2 2>&3 3>&-)
case $? in
diff --git a/contrib/bsddialog/examples_utility/mixedform.sh b/contrib/bsddialog/examples_utility/mixedform.sh
index 80b7abf93745..8a96fa8d9e72 100755
--- a/contrib/bsddialog/examples_utility/mixedform.sh
+++ b/contrib/bsddialog/examples_utility/mixedform.sh
@@ -16,9 +16,9 @@
FORMS=$(./bsddialog --insecure --title " mixedform " \
--mixedform "Hello World!" 12 40 3 \
- Label: 1 1 Entry 1 11 18 25 0 \
- Label: 2 1 Read-Only 2 11 18 25 2 \
- Password: 3 1 "" 3 11 18 25 1 \
+ Label: 0 0 Entry 0 10 18 25 0 \
+ Label: 1 0 Read-Only 1 10 18 25 2 \
+ Password: 2 0 "" 2 10 18 25 1 \
3>&1 1>&2 2>&3 3>&-)
case $? in
diff --git a/contrib/bsddialog/examples_utility/passwordform.sh b/contrib/bsddialog/examples_utility/passwordform.sh
index 19b3a355b6eb..9bfe11a28645 100755
--- a/contrib/bsddialog/examples_utility/passwordform.sh
+++ b/contrib/bsddialog/examples_utility/passwordform.sh
@@ -16,11 +16,11 @@
FORMS=$(./bsddialog --insecure --title " passwordform " \
--passwordform "Example" 12 40 5 \
- Password1: 1 1 "" 1 12 18 25 \
- Password2: 2 1 "" 2 12 18 25 \
- Password3: 3 1 "" 3 12 18 25 \
- Password4: 4 1 "" 4 12 18 25 \
- Password5: 5 1 "" 5 12 18 25 \
+ Password1: 0 0 "" 0 11 18 25 \
+ Password2: 1 0 "" 1 11 18 25 \
+ Password3: 2 0 "" 2 11 18 25 \
+ Password4: 3 0 "" 3 11 18 25 \
+ Password5: 4 0 "" 4 11 18 25 \
3>&1 1>&2 2>&3 3>&-)
case $? in
diff --git a/contrib/bsddialog/examples_utility/timebox.sh b/contrib/bsddialog/examples_utility/timebox.sh
index 81d24d558dc9..233434b29195 100755
--- a/contrib/bsddialog/examples_utility/timebox.sh
+++ b/contrib/bsddialog/examples_utility/timebox.sh
@@ -14,8 +14,7 @@
: ${BSDDIALOG_CANCEL=1}
: ${BSDDIALOG_ESC=5}
-TIME=$(./bsddialog --title " timebox " \
- --timebox "Tab / Left / Right to move\nUp / Down to select" 10 40 \
+TIME=$(./bsddialog --title " timebox " --timebox "Hello World!" 8 25 \
3>&1 1>&2 2>&3 3>&-)
case $? in
diff --git a/contrib/bsddialog/lib/GNUMakefile b/contrib/bsddialog/lib/GNUMakefile
index 0d724b803be3..3c31c78fdf88 100644
--- a/contrib/bsddialog/lib/GNUMakefile
+++ b/contrib/bsddialog/lib/GNUMakefile
@@ -3,16 +3,16 @@
#
# Written in 2021 by Alfonso Sabato Siciliano
-VERSION = 0.2
+VERSION = 0.4
LIBRARY = bsddialog
LIBRARY_SO = lib${LIBRARY:=.so}
HEADERS = bsddialog.h bsddialog_theme.h bsddialog_progressview.h
-SOURCES = barbox.c formbox.c infobox.c libbsddialog.c lib_util.c menubox.c \
- messagebox.c textbox.c theme.c timebox.c
+SOURCES = barbox.c calendarbox.c formbox.c infobox.c libbsddialog.c \
+ lib_util.c menubox.c messagebox.c textbox.c theme.c timebox.c
OBJECTS = $(SOURCES:.c=.o)
-CFLAGS = -D_XOPEN_SOURCE_EXTENDED -Wall -Wextra -Wno-implicit-fallthrough \
- -Werror -fpic
-LDFLAGS = -lformw -lncursesw -ltinfo
+CFLAGS = -D_XOPEN_SOURCE_EXTENDED -D_XOPEN_SOURCE -D_GNU_SOURCE -Wall -Wextra \
+ -Wno-implicit-fallthrough -Werror -fpic
+LDFLAGS = -lncursesw -ltinfo
LIBFLAG = -shared
RM = rm -f
diff --git a/contrib/bsddialog/lib/Makefile b/contrib/bsddialog/lib/Makefile
index 962b059b3e03..0f536fb38743 100644
--- a/contrib/bsddialog/lib/Makefile
+++ b/contrib/bsddialog/lib/Makefile
@@ -3,18 +3,18 @@
#
# Written in 2021 by Alfonso Sabato Siciliano
-VERSION = 0.2
+VERSION = 0.4
LIBRARY = bsddialog
LIBRARY_SO = lib${LIBRARY:=.so}
LIBRARY_A = lib${LIBRARY:=.a}
HEADERS = bsddialog.h bsddialog_theme.h bsddialog_progressview.h
-SOURCES = barbox.c formbox.c infobox.c libbsddialog.c lib_util.c menubox.c \
- messagebox.c textbox.c theme.c timebox.c
+SOURCES = barbox.c calendarbox.c formbox.c infobox.c libbsddialog.c \
+ lib_util.c menubox.c messagebox.c textbox.c theme.c timebox.c
OBJECTS = ${SOURCES:.c=.o}
CFLAGS += -D_XOPEN_SOURCE_EXTENDED -fPIC -Wall -Wextra
LDFLAGS += -fstack-protector-strong -shared -Wl,-x -Wl,--fatal-warnings \
-Wl,--warn-shared-textrel -Wl,-soname,${LIBRARY_SO}.${VERSION} \
- -L/usr/lib -lformw -lncursesw -ltinfow
+ -L/usr/lib -lncursesw -ltinfow
.if defined(DEBUG)
# `make -DDEBUG`
diff --git a/contrib/bsddialog/lib/barbox.c b/contrib/bsddialog/lib/barbox.c
index 49aa105c1de3..71759839a709 100644
--- a/contrib/bsddialog/lib/barbox.c
+++ b/contrib/bsddialog/lib/barbox.c
@@ -70,7 +70,7 @@ draw_bar(WINDOW *win, int y, int x, int barlen, int perc, bool withlabel,
sprintf(labelstr, "%d", label);
else
sprintf(labelstr, "%3d%%", perc);
- stringlen = (int)strlen(labelstr);
+ stringlen = (int)strlen(labelstr); /* number, always 1-byte-ch string */
wmove(win, y, x + barlen/2 - stringlen/2);
for (i = 0; i < stringlen; i++) {
color = (blue_x + 1 <= barlen/2 - stringlen/2 + i ) ?
@@ -109,7 +109,7 @@ bar_checksize(int rows, int cols, struct buttons *bs)
minwidth = 0;
if (bs != NULL) /* gauge has not buttons */
- minwidth = buttons_width(*bs);
+ minwidth = buttons_min_width(*bs);
minwidth = MAX(minwidth, MINBARWIDTH);
minwidth += VBORDERS;
@@ -151,16 +151,14 @@ bsddialog_gauge(struct bsddialog_conf *conf, const char *text, int rows,
bar = new_boxed_window(conf, y+h-4, x+3, 3, w-6, RAISED);
- mainloop = (fd < 0) ? false : true;
-
- if (mainloop) {
+ input = NULL;
+ if (fd >= 0) {
fd2 = dup(fd);
- input = fdopen(fd2, "r");
- if (input == NULL)
+ if ((input = fdopen(fd2, "r")) == NULL)
RETURN_ERROR("Cannot build FILE* from fd");
- } else
- input = NULL;
+ }
+ mainloop = true;
while (mainloop) {
wrefresh(widget);
prefresh(textpad, 0, 0, y+1, x+1+TEXTHMARGIN, y+h-4,
@@ -168,6 +166,8 @@ bsddialog_gauge(struct bsddialog_conf *conf, const char *text, int rows,
draw_borders(conf, bar, 3, w-6, RAISED);
draw_bar(bar, 1, 1, w-8, perc, false, -1 /*unused*/);
wrefresh(bar);
+ if (input == NULL) /* that is fd < 0 */
+ break;
while (true) {
fscanf(input, "%s", inputbuf);
@@ -193,10 +193,11 @@ bsddialog_gauge(struct bsddialog_conf *conf, const char *text, int rows,
if (strcmp(inputbuf, sep) == 0)
break;
strcpy(pntext, inputbuf);
- pntext += strlen(inputbuf);
+ pntext += strlen(inputbuf); /* end string, no strlen */
pntext[0] = ' ';
pntext++;
}
+ pntext[0] = '\0';
if (update_dialog(conf, shadow, widget, y, x, h, w, textpad,
ntext, NULL, false) != 0)
return (BSDDIALOG_ERROR);
@@ -216,7 +217,7 @@ do_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows, int cols,
unsigned int mainperc, unsigned int nminibars, const char **minilabels,
int *minipercs, bool color)
{
- int i, output, miniperc, y, x, h, w, ypad, max_minbarlen;
+ int i, retval, miniperc, y, x, h, w, ypad, max_minbarlen;
int htextpad, htext, wtext;
int colorperc, red, green;
WINDOW *widget, *textpad, *bar, *shadow;
@@ -240,7 +241,7 @@ do_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows, int cols,
max_minbarlen = 0;
for (i = 0; i < (int)nminibars; i++)
- max_minbarlen = MAX(max_minbarlen, (int)strlen(minilabels[i]));
+ max_minbarlen = MAX(max_minbarlen, (int)strcols(minilabels[i]));
max_minbarlen += 3 + 16; /* seps + [...] */
max_minbarlen = MAX(max_minbarlen, MINMGBARWIDTH); /* mainbar */
@@ -267,10 +268,10 @@ do_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows, int cols,
if (set_widget_position(conf, &y, &x, h, w) != 0)
return (BSDDIALOG_ERROR);
- output = new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text,
+ retval = new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text,
NULL, false);
- if (output == BSDDIALOG_ERROR)
- return (output);
+ if (retval == BSDDIALOG_ERROR)
+ return (retval);
/* mini bars */
for (i = 0; i < (int)nminibars; i++) {
@@ -281,6 +282,7 @@ do_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows, int cols,
if (color && (miniperc >= 0))
wattron(widget, A_BOLD);
mvwaddstr(widget, i+1, 2, minilabels[i]);
+ if (color && (miniperc >= 0))
wattroff(widget, A_BOLD);
/* perc */
if (miniperc < -11)
@@ -325,7 +327,7 @@ do_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows, int cols,
wrefresh(bar);
- /* getch(); port ncurses shows nothing */
+ /* getch(); alternate mode (port devel/ncurses) shows nothing */
delwin(bar);
end_dialog(conf, shadow, widget, textpad);
@@ -338,12 +340,12 @@ bsddialog_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int mainperc, unsigned int nminibars,
const char **minilabels, int *minipercs)
{
- int output;
+ int retval;
- output = do_mixedgauge(conf, text, rows, cols, mainperc, nminibars,
+ retval = do_mixedgauge(conf, text, rows, cols, mainperc, nminibars,
minilabels, minipercs, false);
- return (output);
+ return (retval);
}
int
@@ -352,7 +354,7 @@ bsddialog_progressview (struct bsddialog_conf *conf, const char *text, int rows,
struct bsddialog_fileminibar *minibar)
{
bool update;
- int perc, output, *minipercs;
+ int perc, retval, *minipercs;
unsigned int i, mainperc, totaltodo;
float readforsec;
const char **minilabels;
@@ -371,7 +373,7 @@ bsddialog_progressview (struct bsddialog_conf *conf, const char *text, int rows,
}
refresh = pvconf->refresh == 0 ? 0 : pvconf->refresh - 1;
- output = BSDDIALOG_OK;
+ retval = BSDDIALOG_OK;
i = 0;
update = true;
time(&told);
@@ -384,9 +386,9 @@ bsddialog_progressview (struct bsddialog_conf *conf, const char *text, int rows,
time(&tnew);
if (update || tnew > told + refresh) {
- output = do_mixedgauge(conf, text, rows, cols, mainperc,
+ retval = do_mixedgauge(conf, text, rows, cols, mainperc,
nminibar, minilabels, minipercs, true);
- if (output == BSDDIALOG_ERROR)
+ if (retval == BSDDIALOG_ERROR)
return (BSDDIALOG_ERROR);
move(SCREENLINES - 1, 2);
@@ -421,7 +423,7 @@ bsddialog_progressview (struct bsddialog_conf *conf, const char *text, int rows,
free(minilabels);
free(minipercs);
- return (output);
+ return (retval);
}
int
@@ -430,7 +432,8 @@ bsddialog_rangebox(struct bsddialog_conf *conf, const char *text, int rows,
{
bool loop, buttupdate, barupdate;
int y, x, h, w;
- int input, currvalue, output, sizebar, bigchange, positions;
+ int currvalue, retval, sizebar, bigchange, positions;
+ wint_t input;
float perc;
WINDOW *widget, *textpad, *bar, *shadow;
struct buttons bs;
@@ -483,17 +486,18 @@ bsddialog_rangebox(struct bsddialog_conf *conf, const char *text, int rows,
wrefresh(bar);
}
- input = getch();
+ if (get_wch(&input) == ERR)
+ continue;
switch(input) {
case KEY_ENTER:
case 10: /* Enter */
- output = bs.value[bs.curr];
+ retval = bs.value[bs.curr];
*value = currvalue;
loop = false;
break;
case 27: /* Esc */
if (conf->key.enable_esc) {
- output = BSDDIALOG_ESC;
+ retval = BSDDIALOG_ESC;
loop = false;
}
break;
@@ -587,7 +591,7 @@ bsddialog_rangebox(struct bsddialog_conf *conf, const char *text, int rows,
break;
default:
if (shortcut_buttons(input, &bs)) {
- output = bs.value[bs.curr];
+ retval = bs.value[bs.curr];
loop = false;
}
}
@@ -596,7 +600,7 @@ bsddialog_rangebox(struct bsddialog_conf *conf, const char *text, int rows,
delwin(bar);
end_dialog(conf, shadow, widget, textpad);
- return (output);
+ return (retval);
}
int
@@ -604,7 +608,8 @@ bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int sec)
{
bool loop, buttupdate, barupdate;
- int output, y, x, h, w, input, tout, sizebar;
+ int retval, y, x, h, w, tout, sizebar;
+ wint_t input;
float perc;
WINDOW *widget, *textpad, *bar, *shadow;
struct buttons bs;
@@ -650,11 +655,10 @@ bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
buttupdate = false;
}
- input = getch();
- if (input < 0) { /* timeout */
+ if (get_wch(&input) == ERR) { /* timeout */
tout--;
if (tout < 0) {
- output = BSDDIALOG_TIMEOUT;
+ retval = BSDDIALOG_TIMEOUT;
break;
}
else {
@@ -665,12 +669,12 @@ bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
switch(input) {
case KEY_ENTER:
case 10: /* Enter */
- output = bs.value[bs.curr];
+ retval = bs.value[bs.curr];
loop = false;
break;
case 27: /* Esc */
if (conf->key.enable_esc) {
- output = BSDDIALOG_ESC;
+ retval = BSDDIALOG_ESC;
loop = false;
}
break;
@@ -731,7 +735,7 @@ bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
break;
default:
if (shortcut_buttons(input, &bs)) {
- output = bs.value[bs.curr];
+ retval = bs.value[bs.curr];
loop = false;
}
}
@@ -742,5 +746,5 @@ bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
delwin(bar);
end_dialog(conf, shadow, widget, textpad);
- return (output);
+ return (retval);
} \ No newline at end of file
diff --git a/contrib/bsddialog/lib/bsddialog.3 b/contrib/bsddialog/lib/bsddialog.3
index 38500b4da6ca..9cc68a90ff62 100644
--- a/contrib/bsddialog/lib/bsddialog.3
+++ b/contrib/bsddialog/lib/bsddialog.3
@@ -22,13 +22,15 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd February 9, 2022
+.Dd September 23, 2022
.Dt BSDDIALOG 3
.Os
.Sh NAME
.Nm bsddialog_backtitle ,
+.Nm bsddialog_calendar ,
.Nm bsddialog_clearterminal ,
.Nm bsddialog_color ,
+.Nm bsddialog_color_attrs ,
.Nm bsddialog_checklist ,
.Nm bsddialog_datebox ,
.Nm bsddialog_end ,
@@ -36,8 +38,10 @@
.Nm bsddialog_gauge ,
.Nm bsddialog_geterror ,
.Nm bsddialog_get_theme ,
+.Nm bsddialog_hascolors ,
.Nm bsddialog_infobox ,
.Nm bsddialog_init ,
+.Nm bsddialog_init_notheme ,
.Nm bsddialog_initconf ,
.Nm bsddialog_menu ,
.Nm bsddialog_mixedgauge ,
@@ -59,6 +63,16 @@
.Ft int
.Fn bsddialog_backtitle "struct bsddialog_conf *conf" "const char *backtitle"
.Ft int
+.Fo bsddialog_calendar
+.Fa "struct bsddialog_conf *conf"
+.Fa "const char *text"
+.Fa "int rows"
+.Fa "int cols"
+.Fa "unsigned int *yy"
+.Fa "unsigned int *mm"
+.Fa "unsigned int *dd"
+.Fc
+.Ft int
.Fo bsddialog_checklist
.Fa "struct bsddialog_conf *conf"
.Fa "const char *text"
@@ -72,7 +86,7 @@
.Ft int
.Fn bsddialog_clearterminal "void"
.Ft int
-.Fo bsddialog_datebox"
+.Fo bsddialog_datebox
.Fa "struct bsddialog_conf *conf"
.Fa "const char *text"
.Fa "int rows"
@@ -115,6 +129,8 @@
.Ft int
.Fn bsddialog_init "void"
.Ft int
+.Fn bsddialog_init_notheme "void"
+.Ft int
.Fn bsddialog_initconf "struct bsddialog_conf *conf"
.Ft int
.Fo bsddialog_menu
@@ -218,7 +234,16 @@
.Fa "unsigned int flags"
.Fc
.Ft int
+.Fo bsddialog_color_attrs
+.Fa "int color"
+.Fa "enum bsddialog_color *foreground"
+.Fa "enum bsddialog_color *background"
+.Fa "unsigned int *flags"
+.Fc
+.Ft int
.Fn bsddialog_get_theme "struct bsddialog_theme *theme"
+.Ft bool
+.Fn bsddialog_hascolors "void"
.Ft int
.Fn bsddialog_set_default_theme "enum bsddialog_default_theme theme"
.Ft int
@@ -239,6 +264,12 @@ API.
restores the screen like before
.Fn bsddialog_init ,
then it is not possible to use the library functions.
+.Fn bsddialog_init_notheme
+is equivalent to
+.Fn bsddialog_init
+except it does not set the default graphical theme; see
+.Sx Theme
+subsection to set a theme explicitly.
.Pp
.Fn bsddialog_error
returns a string to describe the last error, it should be called after a
@@ -258,10 +289,9 @@ is described later.
.Pp
Each
.Fa char*
-argument has to be a well terminated string, can be empty
-.Pq Dq
-but not
-.Dv NULL .
+argument has to be a well terminated string, it can be a multibyte character
+string depending on current locale, see
+.Xr setlocale 3 .
.Ss Dialogs
The dialogs have common arguments.
.Fa text
@@ -282,6 +312,8 @@ struct bsddialog_conf {
bool ascii_lines;
unsigned int auto_minheight;
unsigned int auto_minwidth;
+ unsigned int auto_topmargin;
+ unsigned int auto_downmargin;
const char *bottomtitle;
bool clear;
int *get_height;
@@ -298,6 +330,7 @@ struct bsddialog_conf {
const char *f1_message;
} key;
struct {
+ unsigned int cols_per_row;
bool highlight;
unsigned int tablen;
} text;
@@ -309,11 +342,13 @@ struct bsddialog_conf {
bool shortcut_buttons;
} menu;
struct {
- bool enable_wchar;
- int securech;
+ char securech;
+ char *securembch;
+ bool value_wchar;
bool value_without_ok;
} form;
struct {
+ bool always_active;
bool without_ok;
const char *ok_label;
bool with_extra;
@@ -343,6 +378,23 @@ minimum width if
.Fa cols
is
.Dv BSDDIALOG_AUTOSIZE .
+.It Fa conf.auto_topmargin
+top margin if
+.Fa rows
+is
+.Dv BSDDIALOG_AUTOSIZE
+or
+.Dv BSDDIALOG_FULLSCREEN ,
+.Fa conf.y
+has to be
+.Dv BSDDIALOG_CENTER .
+.It Fa conf.auto_downmargin
+down margin if
+.Fa rows
+is
+.Dv BSDDIALOG_AUTOSIZE
+or
+.Dv BSDDIALOG_FULLSCREEN .
.It Fa conf.bottomtitle
subtitle at the dialog bottom side.
.It Fa conf.clear
@@ -382,11 +434,16 @@ file to open if F1 is pressed.
message to display if F1 is pressed.
.El
.Pp
-.Fa conf.text.highlight
+.Bl -column -compact
+.It Fa conf.text.cols_per_row
+Try to set the number of columns for a row of
+.Fa text
+with autosizing; default
+.Dv 10 .
+.It Fa conf.text.highlight
enables highlights for
.Fa text ,
properly the following sequences are considered escapes:
-.Bl -column -compact
.It Dq \eZ0
black.
.It Dq \eZ1
@@ -404,7 +461,7 @@ cyan.
.It Dq \eZ7
white.
.It Dq \eZr
-reverse colors between foreground and background.
+reverse foreground and background.
.It Dq \eZR
disable reverse.
.It Dq \eZb
@@ -417,11 +474,23 @@ underline.
disable underline.
.It Dq \eZn
disable each customization.
+.It Fa conf.text.tablen
+tab length for
+.Fa text
+argument and
+.Fn bsddialog_textbox
+function.
.El
-.Fa conf.text.tablen
-tab length.
.Pp
.Bl -column -compact
+.It Fa conf.button.always_active
+buttons always active, avoidind focus switch between buttons and input fields or
+input boxes in
+.Fn bsddialog_form ,
+.Fn bsddialog_datebox ,
+.Fn bsddialog_calendar
+and
+.Fn bsddialog_timebox .
.It Fa conf.button.without_ok
disable OK button.
.It Fa conf.button.ok_label
@@ -458,7 +527,10 @@ to true,
and
.Fa conf.x
to
-.Dv BSDDIALOG_CENTER .
+.Dv BSDDIALOG_CENTER ,
+.Fa conf.text.cols_per_row
+to
+.Dv 10 .
.Pp
.Fn bsddialog_infobox
builds a dialog without buttons and returns instantly.
@@ -474,8 +546,10 @@ builds a dialog waiting until the timeout in
.Fa seconds
expires or a button is pressed.
.Pp
+.Fn bsddialog_calendar
+and
.Fn bsddialog_datebox
-builds a dialog to select a date,
+build a dialog to select a date,
.Fa yy ,
.Fa mm ,
and
@@ -549,14 +623,14 @@ builds a dialog with collections of checklists, radiolists and separators.
A collection is a set defined like:
.Pp
.Bd -literal -offset indent -compact
-enum bsddialog_grouptype {
+enum bsddialog_menutype {
BSDDIALOG_CHECKLIST,
BSDDIALOG_RADIOLIST,
BSDDIALOG_SEPARATOR,
};
struct bsddialog_menugroup {
- enum bsddialog_grouptype type;
+ enum bsddialog_menutype type;
unsigned int nitems;
struct bsddialog_menuitem *items;
};
@@ -598,8 +672,16 @@ enable shortcut keys on buttons, default on items.
.El
.Pp
.Fn bsddialog_form
-builds a dialog to display a list of items to get strings in input, an item is
-defined like:
+builds a dialog to display an array of
+.Fa items
+of
+.Fa nitems
+elements to get strings in input.
+.Fa formrows
+specifies the graphical height for the box around the items,
+.Dv 0
+for autosizing.
+An item is defined like:
.Pp
.Bd -literal -offset indent -compact
struct bsddialog_formitem {
@@ -621,7 +703,7 @@ struct bsddialog_formitem {
.Ed
.Pp
.Fa label
-describes the request, it is printed at the position
+is a string to describe the request, it is printed at the position
.Fa ylabel
and
.Fa xlabel .
@@ -632,45 +714,43 @@ and
.Fa fieldlen
is its graphical width, while
.Fa maxvalelen
-is the maximum length of the input string,
+is the maximum number of characters of the input string.
.Fa init
-is the default value.
+is the default field value.
If the OK button is pressed
.Fa value
-is the allocated memory with the current field string.
+is the allocated memory with the current field string, its size depends on
+the current locale.
.Fa flags
is an OR value to set the
-.Dv BSDDIALOG_FIELDHIDDEN
+.Dv BSDDIALOG_FIELDHIDDEN ,
+.Dv BSDDIALOG_FIELDREADONLY ,
+.Dv BSDDIALOG_FIELDNOCOLOR ,
+.Dv BSDDIALOG_FIELDCURSOREND ,
+.Dv BSDDIALOG_FIELDEXTEND
and
-.Dv BSDDIALOG_FIELDREADONLY
+.Dv BSDDIALOG_FIELDSINGLEBYTE .
flags for the field.
.Fa bottomdesc
is printed on the bottom side of the screen if the item is focused.
-.Fa items
-is an array of items of
-.Fa nitems
-elements,
-.Fa formrows
-specifies the graphical fixed height for the items list;
-.Fa ylabel
-and
-.Fa yfield
-have to be between 1 and
-.Fa formrows .
.Pp
.Fn bsddialog_form
can be customized by:
.Bl -column -compact
-.It Fa conf.form.enable_wchar
-enables characters greater than 127 in the field,
-.Fa value
-is a pointer to allocated memory for a
-.Em wchar_t
-string.
.It Fa conf.form.securech
-charachter to hide the input
-with
+charachter to hide the input with
.Dv BSDDIALOG_FIELDHIDDEN .
+.It Fa conf.form.securembch
+multibyte charachter to hide the input with
+.Dv BSDDIALOG_FIELDHIDDEN ,
+.Fa conf.form.securech
+is ignored.
+.It Fa conf.form.value_wchar
+the allocated
+.Fa value
+is a
+.Em wchar_t*
+string.
.It Fa conf.form.value_without_ok
allocate memory and set
.Fa value
@@ -747,8 +827,8 @@ struct bsddialog_theme {
} screen;
struct {
int color;
- unsigned int h;
- unsigned int w;
+ unsigned int y;
+ unsigned int x;
} shadow;
struct {
int color;
@@ -770,20 +850,23 @@ struct bsddialog_theme {
int descsepcolor;
int f_shortcutcolor;
int shortcutcolor;
+ int bottomdesccolor;
} menu;
struct {
int f_fieldcolor;
int fieldcolor;
int readonlycolor;
+ int bottomdesccolor;
} form;
struct {
int f_color;
int color;
} bar;
struct {
- unsigned int hmargin;
- int leftdelim;
- int rightdelim;
+ unsigned int minmargin;
+ unsigned int maxmargin;
+ char leftdelim;
+ char rightdelim;
int delimcolor;
int f_delimcolor;
int color;
@@ -825,6 +908,8 @@ specifies OR-flags, possible values:
.Dv BSDDIALOG_REVERSE
and
.Dv BSDDIALOG_UNDERLINE .
+.Fn bsddialog_color_attrs
+gets the properties of a color.
.Pp
.Fn bsddialog_set_theme
sets
@@ -840,6 +925,13 @@ and
.Dv BSDDIALOG_THEME_DIALOG ,
they can be set via
.Fn bsddialog_set_default_theme .
+.Pp
+.Fn bsddialog_hascolors
+returns
+.Dv true
+if the terminal provides colors,
+.Dv false
+otherwise.
.Sh RETURN VALUES
The functions return the value
.Dv BSDDIALOG_ERROR
@@ -938,7 +1030,7 @@ struct bsddialog_menuitem check[2] = {
struct bsddialog_menuitem sep[1] = {
{ "3", true, 0, "Radiolist", "(desc)", "" }
};
-struct bsddialog_menuitem radio[5] = {
+struct bsddialog_menuitem radio[2] = {
{ "4", true, 0, "Name 1", "Desc 1", "Radio Bottom Desc 1" },
{ "5", false, 0, "Name 2", "Desc 2", "Radio Bottom Desc 2" }
};
@@ -975,8 +1067,7 @@ for (i = 0; i < 3; i++) {
.Ed
.Sh SEE ALSO
.Xr bsddialog 1 ,
-.Xr curses 3 ,
-.Xr ncurses 3
+.Xr curses 3
.Sh HISTORY
The
.Nm bsddialog
@@ -985,8 +1076,4 @@ library first appeared in
.Sh AUTHORS
.Nm bsddialog
was written by
-.An Alfonso Sabato Siciliano Aq Mt alf.siciliano@gmail.com .
-.Sh BUGS
-.Fn bsddialog_form
-does not resize the dialog after a terminal resize and does not provide
-scrolling for items. \ No newline at end of file
+.An Alfonso Sabato Siciliano Aq Mt asiciliano@FreeBSD.org .
diff --git a/contrib/bsddialog/lib/bsddialog.h b/contrib/bsddialog/lib/bsddialog.h
index 37f9899141c0..ce6aac6d4632 100644
--- a/contrib/bsddialog/lib/bsddialog.h
+++ b/contrib/bsddialog/lib/bsddialog.h
@@ -30,7 +30,7 @@
#include <stdbool.h>
-#define LIBBSDDIALOG_VERSION "0.2"
+#define LIBBSDDIALOG_VERSION "0.4"
/* Exit status */
#define BSDDIALOG_ERROR -1
@@ -64,13 +64,19 @@
#define BSDDIALOG_MG_PENDING -11
/* Form */
-#define BSDDIALOG_FIELDHIDDEN 1U
-#define BSDDIALOG_FIELDREADONLY 2U
+#define BSDDIALOG_FIELDHIDDEN 1U
+#define BSDDIALOG_FIELDREADONLY 2U
+#define BSDDIALOG_FIELDNOCOLOR 4U
+#define BSDDIALOG_FIELDCURSOREND 8U
+#define BSDDIALOG_FIELDEXTEND 16U
+#define BSDDIALOG_FIELDSINGLEBYTE 32U
struct bsddialog_conf {
bool ascii_lines;
unsigned int auto_minheight;
unsigned int auto_minwidth;
+ unsigned int auto_topmargin;
+ unsigned int auto_downmargin;
const char *bottomtitle;
bool clear;
int *get_height;
@@ -87,6 +93,7 @@ struct bsddialog_conf {
const char *f1_message;
} key;
struct {
+ unsigned int cols_per_row;
bool highlight;
unsigned int tablen;
} text;
@@ -98,11 +105,13 @@ struct bsddialog_conf {
bool shortcut_buttons;
} menu;
struct {
- bool enable_wchar;
- int securech;
+ char securech;
+ char *securembch;
+ bool value_wchar;
bool value_without_ok;
} form;
struct {
+ bool always_active;
bool without_ok;
const char *ok_label;
bool with_extra;
@@ -127,14 +136,14 @@ struct bsddialog_menuitem {
const char *bottomdesc;
};
-enum bsddialog_grouptype {
+enum bsddialog_menutype {
BSDDIALOG_CHECKLIST,
BSDDIALOG_RADIOLIST,
BSDDIALOG_SEPARATOR,
};
struct bsddialog_menugroup {
- enum bsddialog_grouptype type;
+ enum bsddialog_menutype type;
unsigned int nitems;
struct bsddialog_menuitem *items;
};
@@ -156,6 +165,7 @@ struct bsddialog_formitem {
};
int bsddialog_init(void);
+int bsddialog_init_notheme(void);
int bsddialog_end(void);
int bsddialog_backtitle(struct bsddialog_conf *conf, const char *backtitle);
int bsddialog_initconf(struct bsddialog_conf *conf);
@@ -164,6 +174,10 @@ const char *bsddialog_geterror(void);
/* Dialogs */
int
+bsddialog_calendar(struct bsddialog_conf *conf, const char *text, int rows,
+ int cols, unsigned int *yy, unsigned int *mm, unsigned int *dd);
+
+int
bsddialog_checklist(struct bsddialog_conf *conf, const char *text, int rows,
int cols, unsigned int menurows, unsigned int nitems,
struct bsddialog_menuitem *items, int *focusitem);
diff --git a/contrib/bsddialog/lib/bsddialog_theme.h b/contrib/bsddialog/lib/bsddialog_theme.h
index 89381cfe28d5..2f20d7b5a79c 100644
--- a/contrib/bsddialog/lib/bsddialog_theme.h
+++ b/contrib/bsddialog/lib/bsddialog_theme.h
@@ -39,8 +39,8 @@ struct bsddialog_theme {
} screen;
struct {
int color;
- unsigned int h;
- unsigned int w;
+ unsigned int y;
+ unsigned int x;
} shadow;
struct {
int color;
@@ -62,20 +62,23 @@ struct bsddialog_theme {
int descsepcolor;
int f_shortcutcolor;
int shortcutcolor;
+ int bottomdesccolor;
} menu;
struct {
int f_fieldcolor;
int fieldcolor;
int readonlycolor;
+ int bottomdesccolor;
} form;
struct {
int f_color;
int color;
} bar;
struct {
- unsigned int hmargin;
- int leftdelim;
- int rightdelim;
+ unsigned int minmargin;
+ unsigned int maxmargin;
+ char leftdelim;
+ char rightdelim;
int delimcolor;
int f_delimcolor;
int color;
@@ -106,7 +109,11 @@ enum bsddialog_color {
int
bsddialog_color(enum bsddialog_color foreground,
enum bsddialog_color background, unsigned int flags);
+int
+bsddialog_color_attrs(int color, enum bsddialog_color *foreground,
+ enum bsddialog_color *background, unsigned int *flags);
int bsddialog_get_theme(struct bsddialog_theme *theme);
+bool bsddialog_hascolors(void);
int bsddialog_set_default_theme(enum bsddialog_default_theme theme);
int bsddialog_set_theme(struct bsddialog_theme *theme);
diff --git a/contrib/bsddialog/lib/calendarbox.c b/contrib/bsddialog/lib/calendarbox.c
new file mode 100644
index 000000000000..3b55b26a13b8
--- /dev/null
+++ b/contrib/bsddialog/lib/calendarbox.c
@@ -0,0 +1,520 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2022 Alfonso Sabato Siciliano
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+
+#include <curses.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "bsddialog.h"
+#include "bsddialog_theme.h"
+#include "lib_util.h"
+
+#define MINHCAL 13
+#define MINWCAL 36 /* 34 calendar, 1 + 1 margins */
+#define MINYEAR 1900
+#define MAXYEAR 999999999
+
+static int month_days(int yy, int mm)
+{
+ int days;
+
+ if (mm == 2)
+ days = ISLEAP(yy) ? 29 : 28;
+ else if (mm == 4 || mm == 6 || mm == 9 || mm == 11)
+ days = 30;
+ else
+ days = 31;
+
+ return (days);
+}
+
+enum operation {
+ UP_DAY,
+ DOWN_DAY,
+ LEFT_DAY,
+ RIGHT_DAY,
+ UP_MONTH,
+ DOWN_MONTH,
+ UP_YEAR,
+ DOWN_YEAR
+};
+
+static void datectl(enum operation op, int *yy, int *mm, int *dd)
+{
+ int ndays;
+
+ ndays = month_days(*yy, *mm);
+
+ switch (op) {
+ case UP_DAY:
+ if (*dd > 7)
+ *dd -= 7;
+ else {
+ if (*mm == 1) {
+ *yy -= 1;
+ *mm = 12;
+ } else
+ *mm -= 1;
+ ndays = month_days(*yy, *mm);
+ *dd = ndays - abs(7 - *dd);
+ }
+ break;
+ case DOWN_DAY:
+ if (*dd + 7 < ndays)
+ *dd += 7;
+ else {
+ if (*mm == 12) {
+ *yy += 1;
+ *mm = 1;
+ } else
+ *mm += 1;
+ *dd = *dd + 7 - ndays;
+ }
+ break;
+ case LEFT_DAY:
+ if (*dd > 1)
+ *dd -= 1;
+ else {
+ if (*mm == 1) {
+ *yy -= 1;
+ *mm = 12;
+ } else
+ *mm -= 1;
+ *dd = month_days(*yy, *mm);
+ }
+ break;
+ case RIGHT_DAY:
+ if (*dd < ndays)
+ *dd += 1;
+ else {
+ if (*mm == 12) {
+ *yy += 1;
+ *mm = 1;
+ } else
+ *mm += 1;
+ *dd = 1;
+ }
+ break;
+ case UP_MONTH:
+ if (*mm == 1) {
+ *mm = 12;
+ *yy -= 1;
+ } else
+ *mm -= 1;
+ ndays = month_days(*yy, *mm);
+ if (*dd > ndays)
+ *dd = ndays;
+ break;
+ case DOWN_MONTH:
+ if (*mm == 12) {
+ *mm = 1;
+ *yy += 1;
+ } else
+ *mm += 1;
+ ndays = month_days(*yy, *mm);
+ if (*dd > ndays)
+ *dd = ndays;
+ break;
+ case UP_YEAR:
+ *yy -= 1;
+ ndays = month_days(*yy, *mm);
+ if (*dd > ndays)
+ *dd = ndays;
+ break;
+ case DOWN_YEAR:
+ *yy += 1;
+ ndays = month_days(*yy, *mm);
+ if (*dd > ndays)
+ *dd = ndays;
+ break;
+ }
+
+ if (*yy < MINYEAR) {
+ *yy = MINYEAR;
+ *mm = 1;
+ *dd = 1;
+ }
+ if (*yy > MAXYEAR) {
+ *yy = MAXYEAR;
+ *mm = 12;
+ *dd = 31;
+ }
+}
+
+static int week_day(int yy, int mm, int dd)
+{
+ int wd;
+
+ dd += mm < 3 ? yy-- : yy - 2;
+ wd = 23*mm/9 + dd + 4 + yy/4 - yy/100 + yy/400;
+ wd %= 7;
+
+ return (wd);
+}
+
+static void
+print_calendar(struct bsddialog_conf *conf, WINDOW *win, int yy, int mm, int dd,
+ bool active)
+{
+ int ndays, i, y, x, wd, h, w;
+
+ getmaxyx(win, h, w);
+ wclear(win);
+ draw_borders(conf, win, h, w, RAISED);
+ if (active) {
+ wattron(win, t.dialog.arrowcolor);
+ mvwhline(win, 0, 15, conf->ascii_lines ? '^' : ACS_UARROW, 4);
+ mvwhline(win, h-1, 15, conf->ascii_lines ? 'v' : ACS_DARROW, 4);
+ mvwvline(win, 3, 0, conf->ascii_lines ? '<' : ACS_LARROW, 3);
+ mvwvline(win, 3, w-1, conf->ascii_lines ? '>' : ACS_RARROW, 3);
+ wattroff(win, t.dialog.arrowcolor);
+ }
+
+ mvwaddstr(win, 1, 5, "Sun Mon Tue Wed Thu Fri Sat");
+ ndays = month_days(yy, mm);
+ y = 2;
+ wd = week_day(yy, mm, 1);
+ for (i = 1; i <= ndays; i++) {
+ x = 5 + (4 * wd); /* x has to be 6 with week number */
+ wmove(win, y, x);
+ mvwprintw(win, y, x, "%2d", i);
+ if (i == dd) {
+ wattron(win, t.menu.f_namecolor);
+ mvwprintw(win, y, x, "%2d", i);
+ wattroff(win, t.menu.f_namecolor);
+ }
+ wd++;
+ if (wd > 6) {
+ wd = 0;
+ y++;
+ }
+ }
+
+ wrefresh(win);
+}
+
+static void
+drawsquare(struct bsddialog_conf *conf, WINDOW *win, const char *fmt,
+ const void *value, bool focus)
+{
+ int h, w;
+
+ getmaxyx(win, h, w);
+ draw_borders(conf, win, h, w, RAISED);
+ if (focus) {
+ wattron(win, t.dialog.arrowcolor);
+ mvwhline(win, 0, 7, conf->ascii_lines ? '^' : ACS_UARROW, 3);
+ mvwhline(win, 2, 7, conf->ascii_lines ? 'v' : ACS_DARROW, 3);
+ wattroff(win, t.dialog.arrowcolor);
+ }
+
+ if (focus)
+ wattron(win, t.menu.f_namecolor);
+ if (strchr(fmt, 's') != NULL)
+ mvwprintw(win, 1, 1, fmt, (const char*)value);
+ else
+ mvwprintw(win, 1, 1, fmt, *((const int*)value));
+ if (focus)
+ wattroff(win, t.menu.f_namecolor);
+
+ wrefresh(win);
+}
+
+static int
+calendar_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h,
+ int *w, const char *text, struct buttons bs)
+{
+ int htext, wtext;
+
+ if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) {
+ if (text_size(conf, rows, cols, text, &bs, MINHCAL, MINWCAL,
+ &htext, &wtext) != 0)
+ return (BSDDIALOG_ERROR);
+ }
+
+ if (cols == BSDDIALOG_AUTOSIZE)
+ *w = widget_min_width(conf, wtext, MINWCAL, &bs);
+
+ if (rows == BSDDIALOG_AUTOSIZE)
+ *h = widget_min_height(conf, htext, MINHCAL, true);
+
+ return (0);
+}
+
+static int calendar_checksize(int rows, int cols, struct buttons bs)
+{
+ int mincols;
+
+ mincols = MAX(MINWCAL, buttons_min_width(bs));
+ mincols += VBORDERS;
+
+ if (cols < mincols)
+ RETURN_ERROR("Few cols for this calendar (at least 38)");
+
+ if (rows < MINHCAL + 2 + 2) /* 2 buttons + 2 borders */
+ RETURN_ERROR("Few rows for calendar (at least 17)");
+
+ return (0);
+}
+
+int
+bsddialog_calendar(struct bsddialog_conf *conf, const char *text, int rows,
+ int cols, unsigned int *yy, unsigned int *mm, unsigned int *dd)
+{
+ bool loop, focusbuttons;
+ int retval, y, x, h, w, sel, ycal, xcal, year, month, day;
+ wint_t input;
+ WINDOW *widget, *textpad, *shadow, *yearwin, *monthwin, *daywin;
+ struct buttons bs;
+ const char *m[12] = {
+ "January", "February", "March", "April", "May", "June", "July",
+ "August", "September", "October", "November", "December"
+ };
+
+ if (yy == NULL || mm == NULL || dd == NULL)
+ RETURN_ERROR("yy / mm / dd cannot be NULL");
+
+ year = *yy > MAXYEAR ? MAXYEAR : *yy;
+ if (year < MINYEAR)
+ year = MINYEAR;
+ month = *mm > 12 ? 12 : *mm;
+ if (month == 0)
+ month = 1;
+ day = *dd == 0 ? 1 : *dd;
+ if(day > month_days(year, month))
+ day = month_days(year, month);
+
+ get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL);
+
+ if (set_widget_size(conf, rows, cols, &h, &w) != 0)
+ return (BSDDIALOG_ERROR);
+ if (calendar_autosize(conf, rows, cols, &h, &w, text, bs) != 0)
+ return (BSDDIALOG_ERROR);
+ if (calendar_checksize(h, w, bs) != 0)
+ return (BSDDIALOG_ERROR);
+ if (set_widget_position(conf, &y, &x, h, w) != 0)
+ return (BSDDIALOG_ERROR);
+
+ if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, &bs,
+ true) != 0)
+ return (BSDDIALOG_ERROR);
+
+ pnoutrefresh(textpad, 0, 0, y+1, x+2, y+h-17, x+w-2);
+ doupdate();
+
+ ycal = y + h - 15;
+ xcal = x + w/2 - 17;
+ mvwaddstr(widget, h - 16, w/2 - 17, "Month");
+ monthwin = new_boxed_window(conf, ycal, xcal, 3, 17, RAISED);
+ mvwaddstr(widget, h - 16, w/2, "Year");
+ yearwin = new_boxed_window(conf, ycal, xcal + 17, 3, 17, RAISED);
+ daywin = new_boxed_window(conf, ycal + 3, xcal, 9, 34, RAISED);
+
+ wrefresh(widget);
+
+ sel = -1;
+ loop = focusbuttons = true;
+ while (loop) {
+ drawsquare(conf, monthwin, "%15s", m[month - 1], sel == 0);
+ drawsquare(conf, yearwin, "%15d", &year, sel == 1);
+ print_calendar(conf, daywin, year, month, day, sel == 2);
+
+ if (get_wch(&input) == ERR)
+ continue;
+ switch(input) {
+ case KEY_ENTER:
+ case 10: /* Enter */
+ if (focusbuttons || conf->button.always_active) {
+ retval = bs.value[bs.curr];
+ loop = false;
+ }
+ break;
+ case 27: /* Esc */
+ if (conf->key.enable_esc) {
+ retval = BSDDIALOG_ESC;
+ loop = false;
+ }
+ break;
+ case '\t': /* TAB */
+ if (focusbuttons) {
+ bs.curr++;
+ if (bs.curr >= (int)bs.nbuttons) {
+ focusbuttons = false;
+ sel = 0;
+ bs.curr = conf->button.always_active ?
+ 0 : -1;
+ }
+ } else {
+ sel++;
+ if (sel > 2) {
+ focusbuttons = true;
+ sel = -1;
+ bs.curr = 0;
+ }
+ }
+ draw_buttons(widget, bs, true);
+ wrefresh(widget);
+ break;
+ case KEY_RIGHT:
+ if (focusbuttons) {
+ bs.curr++;
+ if (bs.curr >= (int)bs.nbuttons) {
+ focusbuttons = false;
+ sel = 0;
+ bs.curr = conf->button.always_active ?
+ 0 : -1;
+ }
+ } else if (sel == 2) {
+ datectl(RIGHT_DAY, &year, &month, &day);
+ } else { /* Month or Year*/
+ sel++;
+ }
+ draw_buttons(widget, bs, true);
+ wrefresh(widget);
+ break;
+ case KEY_LEFT:
+ if (focusbuttons) {
+ bs.curr--;
+ if (bs.curr < 0) {
+ focusbuttons = false;
+ sel = 2;
+ bs.curr = conf->button.always_active ?
+ 0 : -1;
+ }
+ } else if (sel == 2) {
+ datectl(LEFT_DAY, &year, &month, &day);
+ } else if (sel == 1) {
+ sel = 0;
+ } else { /* sel = 0, Month */
+ focusbuttons = true;
+ sel = -1;
+ bs.curr = 0;
+ }
+ draw_buttons(widget, bs, true);
+ wrefresh(widget);
+ break;
+ case KEY_UP:
+ if (focusbuttons) {
+ sel = 2;
+ focusbuttons = false;
+ bs.curr = conf->button.always_active ? 0 : -1;
+ draw_buttons(widget, bs, true);
+ wrefresh(widget);
+ } else if (sel == 0) {
+ datectl(UP_MONTH, &year, &month, &day);
+ } else if (sel == 1) {
+ datectl(UP_YEAR, &year, &month, &day);
+ } else { /* sel = 2 */
+ datectl(UP_DAY, &year, &month, &day);
+ }
+ break;
+ case KEY_DOWN:
+ if (focusbuttons) {
+ break;
+ } else if (sel == 0) {
+ datectl(DOWN_MONTH, &year, &month, &day);
+ } else if (sel == 1) {
+ datectl(DOWN_YEAR, &year, &month, &day);
+ } else { /* sel = 2 */
+ datectl(DOWN_DAY, &year, &month, &day);
+ }
+ break;
+ case KEY_HOME:
+ datectl(UP_MONTH, &year, &month, &day);
+ break;
+ case KEY_END:
+ datectl(DOWN_MONTH, &year, &month, &day);
+ break;
+ case KEY_PPAGE:
+ datectl(UP_YEAR, &year, &month, &day);
+ break;
+ case KEY_NPAGE:
+ datectl(DOWN_YEAR, &year, &month, &day);
+ break;
+ case KEY_F(1):
+ if (conf->key.f1_file == NULL &&
+ conf->key.f1_message == NULL)
+ break;
+ if (f1help(conf) != 0)
+ return (BSDDIALOG_ERROR);
+ /* No break, screen size can change */
+ case KEY_RESIZE:
+ /* Important for decreasing screen */
+ hide_widget(y, x, h, w, conf->shadow);
+ refresh();
+
+ if (set_widget_size(conf, rows, cols, &h, &w) != 0)
+ return (BSDDIALOG_ERROR);
+ if (calendar_autosize(conf, rows, cols, &h, &w, text,
+ bs) != 0)
+ return (BSDDIALOG_ERROR);
+ if (calendar_checksize(h, w, bs) != 0)
+ return (BSDDIALOG_ERROR);
+ if (set_widget_position(conf, &y, &x, h, w) != 0)
+ return (BSDDIALOG_ERROR);
+
+ if (update_dialog(conf, shadow, widget, y, x, h, w,
+ textpad, text, &bs, true) != 0)
+ return (BSDDIALOG_ERROR);
+ pnoutrefresh(textpad, 0, 0, y+1, x+2, y+h-17, x+w-2);
+ doupdate();
+
+ ycal = y + h - 15;
+ xcal = x + w/2 - 17;
+ mvwaddstr(widget, h - 16, w/2 - 17, "Month");
+ mvwin(monthwin, ycal, xcal);
+ mvwaddstr(widget, h - 16, w/2, "Year");
+ mvwin(yearwin, ycal, xcal + 17);
+ mvwin(daywin, ycal + 3, xcal);
+ wrefresh(widget);
+
+ /* Important to avoid grey lines expanding screen */
+ refresh();
+ break;
+ default:
+ if (shortcut_buttons(input, &bs)) {
+ retval = bs.value[bs.curr];
+ loop = false;
+ }
+ }
+ }
+
+ if (retval == BSDDIALOG_OK) {
+ *yy = year;
+ *mm = month;
+ *dd = day;
+ }
+
+ delwin(yearwin);
+ delwin(monthwin);
+ delwin(daywin);
+ end_dialog(conf, shadow, widget, textpad);
+
+ return (retval);
+} \ No newline at end of file
diff --git a/contrib/bsddialog/lib/formbox.c b/contrib/bsddialog/lib/formbox.c
index 564fa99d69a8..5b1d2ab61de2 100644
--- a/contrib/bsddialog/lib/formbox.c
+++ b/contrib/bsddialog/lib/formbox.c
@@ -27,454 +27,605 @@
#include <sys/param.h>
-#include <ctype.h>
-#include <form.h>
+#include <curses.h>
+#include <limits.h>
#include <stdlib.h>
#include <string.h>
+#include <wchar.h>
#include "bsddialog.h"
#include "bsddialog_theme.h"
#include "lib_util.h"
-#define ISFIELDHIDDEN(item) (item.flags & BSDDIALOG_FIELDHIDDEN)
-#define ISFIELDREADONLY(item) (item.flags & BSDDIALOG_FIELDREADONLY)
-#define REDRAWFORM 19860214 /* magic number */
-
-/* field_userptr for private buffer and view options */
-struct myfield {
- int buflen;
- wchar_t *buf;
- int pos;
- int maxpos;
- bool secure;
- int securech;
- const char *bottomdesc;
+struct privateitem {
+ const char *label; /* formitem.label */
+ unsigned int ylabel; /* formitem.ylabel */
+ unsigned int xlabel; /* formitem.xlabel */
+ unsigned int yfield; /* formitem.yfield */
+ unsigned int xfield; /* formitem.xfield */
+ bool secure; /* formitem.flags & BSDDIALOG_FIELDHIDDEN */
+ bool readonly; /* formitem.flags & BSDDIALOG_FIELDREADONLY */
+ bool fieldnocolor; /* formitem.flags & BSDDIALOG_FIELDNOCOLOR */
+ bool extendfield; /* formitem.flags & BSDDIALOG_FIELDEXTEND */
+ bool fieldonebyte; /* formitem.flags & BSDDIALOG_FIELDSINGLEBYTE */
+ bool cursorend; /* formitem.flags & BSDDIALOG_FIELDCURSOREND */
+ bool cursor; /* field cursor visibility */
+ const char *bottomdesc; /* formitem.bottomdesc */
+
+ wchar_t *privwbuf; /* formitem.value */
+ wchar_t *pubwbuf; /* string for drawitem() */
+ unsigned int maxletters; /* formitem.maxvaluelen, [priv|pub]wbuf size */
+ unsigned int nletters; /* letters in privwbuf and pubwbuf */
+ unsigned int pos; /* pos in privwbuf and pubwbuf */
+ unsigned int fieldcols; /* formitem.fieldlen */
+ unsigned int xcursor; /* position in fieldcols [0 - fieldcols-1] */
+ unsigned int xposdraw; /* first pubwbuf index to draw */
};
-#define GETMYFIELD(field) ((struct myfield*)field_userptr(field))
-#define GETMYFIELD2(form) ((struct myfield*)field_userptr(current_field(form)))
-static void insertch(struct myfield *mf, int ch)
+struct privateform {
+ WINDOW *border;
+
+ WINDOW *pad;
+ unsigned int h; /* only to create pad */
+ unsigned int w; /* only to create pad */
+ unsigned int wmin; /* to refresh, w can change for FIELDEXTEND */
+ unsigned int ys; /* to refresh */
+ unsigned int ye; /* to refresh */
+ unsigned int xs; /* to refresh */
+ unsigned int xe; /* to refresh */
+ unsigned int y; /* changes moving focus around items */
+ unsigned int viewrows; /* visible rows, real formheight */
+ unsigned int minviewrows; /* min viewrows, ylabel != yfield */
+
+ wchar_t securewch; /* wide char of conf.form.secure[mb]ch */
+};
+
+enum operation {
+ MOVE_CURSOR_BEGIN,
+ MOVE_CURSOR_END,
+ MOVE_CURSOR_RIGHT,
+ MOVE_CURSOR_LEFT,
+ DEL_LETTER
+};
+
+static bool fieldctl(struct privateitem *item, enum operation op)
{
- int i;
+ bool change;
+ int width, oldwidth, nextwidth, cols;
+ unsigned int i;
+
+ change = false;
+ switch (op){
+ case MOVE_CURSOR_BEGIN:
+ if (item->pos == 0 && item->xcursor == 0)
+ break;
+ /* here the cursor is changed */
+ change = true;
+ item->pos = 0;
+ item->xcursor = 0;
+ item->xposdraw = 0;
+ break;
+ case MOVE_CURSOR_END:
+ while (fieldctl(item, MOVE_CURSOR_RIGHT))
+ change = true;
+ break;
+ case MOVE_CURSOR_LEFT:
+ if (item->pos == 0)
+ break;
+ /* check redundant by item->pos == 0 because of 'while' below */
+ if (item->xcursor == 0 && item->xposdraw == 0)
+ break;
+ /* here some letter to left */
+ change = true;
+ item->pos -= 1;
+ width = wcwidth(item->pubwbuf[item->pos]);
+ if (((int)item->xcursor) - width < 0) {
+ item->xcursor = 0;
+ item->xposdraw -= 1;
+ } else
+ item->xcursor -= width;
+
+ while (true) {
+ if (item->xposdraw == 0)
+ break;
+ if (item->xcursor >= item->fieldcols / 2)
+ break;
+ if (wcwidth(item->pubwbuf[item->xposdraw - 1]) +
+ item->xcursor + width > item->fieldcols)
+ break;
- if (mf->buflen > mf->maxpos)
- return;
+ item->xposdraw -= 1;
+ item->xcursor +=
+ wcwidth(item->pubwbuf[item->xposdraw]);
+ }
+ break;
+ case DEL_LETTER:
+ if (item->nletters == 0)
+ break;
+ if (item->pos == item->nletters)
+ break;
+ /* here a letter under the cursor */
+ change = true;
+ for (i = item->pos; i < item->nletters; i++) {
+ item->privwbuf[i] = item->privwbuf[i+1];
+ item->pubwbuf[i] = item->pubwbuf[i+1];
+ }
+ item->nletters -= 1;
+ item->privwbuf[i] = L'\0';
+ item->pubwbuf[i] = L'\0';
+ break;
+ case MOVE_CURSOR_RIGHT: /* used also by "insert", see handler loop */
+ if (item->pos + 1 == item->maxletters)
+ break;
+ if (item->pos == item->nletters)
+ break;
+ /* here a change to right */
+ change = true;
+ oldwidth = wcwidth(item->pubwbuf[item->pos]);
+ item->pos += 1;
+ if (item->pos == item->nletters) { /* empty column */
+ nextwidth = 1;
+ } else { /* a letter to right */
+ nextwidth = wcwidth(item->pubwbuf[item->pos]);
+ }
+ if (item->xcursor + oldwidth + nextwidth - 1 >= item->fieldcols) {
+ cols = nextwidth;
+ item->xposdraw = item->pos;
+ while (item->xposdraw != 0) {
+ cols += wcwidth(item->pubwbuf[item->xposdraw - 1]);
+ if (cols > (int)item->fieldcols)
+ break;
+ item->xposdraw -= 1;
+ }
+ item->xcursor = 0;
+ for (i = item->xposdraw; i < item->pos ; i++)
+ item->xcursor += wcwidth(item->pubwbuf[i]);
+ }
+ else {
+ item->xcursor += oldwidth;
+ }
- for (i = mf->buflen; i >= mf->pos; i--) {
- mf->buf[i+1] = mf->buf[i];
+ break;
}
- mf->buf[mf->pos] = ch;
- mf->pos += 1;
- if (mf->pos > mf->maxpos)
- mf->pos = mf->maxpos;
- mf->buflen += 1;
- mf->buf[mf->buflen] = '\0';
+ return (change);
}
-static void shiftleft(struct myfield *mf)
+static void
+drawitem(struct privateform *form, struct privateitem *item, bool focus)
{
- int i, last;
+ int color;
+ unsigned int n, cols;
+
+ /* Label */
+ wattron(form->pad, t.dialog.color);
+ mvwaddstr(form->pad, item->ylabel, item->xlabel, item->label);
+ wattroff(form->pad, t.dialog.color);
+
+ /* Field */
+ if (item->readonly)
+ color = t.form.readonlycolor;
+ else if (item->fieldnocolor)
+ color = t.dialog.color;
+ else
+ color = focus ? t.form.f_fieldcolor : t.form.fieldcolor;
+ wattron(form->pad, color);
+ mvwhline(form->pad, item->yfield, item->xfield, ' ', item->fieldcols);
+ n = 0;
+ cols = wcwidth(item->pubwbuf[item->xposdraw]);
+ while (cols <= item->fieldcols && item->xposdraw + n <
+ wcslen(item->pubwbuf)) {
+ n++;
+ cols += wcwidth(item->pubwbuf[item->xposdraw + n]);
- for (i = mf->pos; i < mf->buflen -1; i++) {
- mf->buf[i] = mf->buf[i+1];
}
+ mvwaddnwstr(form->pad, item->yfield, item->xfield,
+ &item->pubwbuf[item->xposdraw], n);
+ wattroff(form->pad, color);
- last = mf->buflen > 0 ? mf->buflen -1 : 0;
- mf->buf[last] = '\0';
- mf->buflen = last;
-}
-
-static void print_bottomdesc(struct myfield *mf)
-{
+ /* Bottom Desc */
move(SCREENLINES - 1, 2);
clrtoeol();
- if (mf->bottomdesc != NULL) {
- addstr(mf->bottomdesc);
+ if (item->bottomdesc != NULL && focus) {
+ attron(t.form.bottomdesccolor);
+ addstr(item->bottomdesc);
+ attroff(t.form.bottomdesccolor);
refresh();
}
+
+ /* Cursor */
+ curs_set((focus && item->cursor) ? 1 : 0);
+ wmove(form->pad, item->yfield, item->xfield + item->xcursor);
+
+ prefresh(form->pad, form->y, 0, form->ys, form->xs, form->ye, form->xe);
}
-static char *w2c(wchar_t *string)
+/*
+ * Trick: draw 2 times an item switching focus.
+ * Problem: curses tries to optimize the rendering but sometimes it misses some
+ * updates or draws old stuff. libformw has a similar problem fixed by the
+ * same trick.
+ * Case 1: KEY_DC and KEY_BACKSPACE, deleted multicolumn letters are drawn
+ * again. It seems fixed by new items pad and prefresh(), previously WINDOW.
+ * Case2: some terminal, tmux and ssh does not show the cursor.
+ */
+#define DRAWITEM_TRICK(form,item,focus) do { \
+ drawitem(form, item, !focus); \
+ drawitem(form, item, focus); \
+} while (0)
+
+static bool
+insertch(struct privateform *form, struct privateitem *item, wchar_t wch)
{
- int i, len;
- char *value;
+ int i;
- len = wcslen(string);
- if ((value = calloc(len + 1, sizeof(char))) == NULL)
- return NULL;
+ if (item->nletters >= item->maxletters)
+ return (false);
- for (i = 0; i < len; i++)
- value[i] = string[i];
- value[i] = '\0';
+ for (i = (int)item->nletters - 1; i >= (int)item->pos; i--) {
+ item->privwbuf[i+1] = item->privwbuf[i];
+ item->pubwbuf[i+1] = item->pubwbuf[i];
+ }
+
+ item->privwbuf[item->pos] = wch;
+ item->pubwbuf[item->pos] = item->secure ? form->securewch : wch;
+ item->nletters += 1;
+ item->privwbuf[item->nletters] = L'\0';
+ item->pubwbuf[item->nletters] = L'\0';
- return value;
+ return (true);
+}
+
+static char* alloc_wstomb(wchar_t *wstr)
+{
+ int len, nbytes, i;
+ char mbch[MB_LEN_MAX], *mbstr;
+
+ nbytes = MB_LEN_MAX; /* to ensure a null terminated string */
+ len = wcslen(wstr);
+ for (i = 0; i < len; i++) {
+ wctomb(mbch, wstr[i]);
+ nbytes += mblen(mbch, MB_LEN_MAX);
+ }
+ if((mbstr = malloc(nbytes)) == NULL)
+ return (NULL);
+
+ wcstombs(mbstr, wstr, nbytes);
+
+ return (mbstr);
}
static int
return_values(struct bsddialog_conf *conf, int output, int nitems,
- struct bsddialog_formitem *items, FORM *form, FIELD **cfield)
+ struct bsddialog_formitem *apiitems, struct privateitem *items)
{
int i;
- struct myfield *mf;
if (output != BSDDIALOG_OK && conf->form.value_without_ok == false)
return (output);
- form_driver_w(form, KEY_CODE_YES, REQ_NEXT_FIELD);
- form_driver_w(form, KEY_CODE_YES, REQ_PREV_FIELD);
for (i = 0; i < nitems; i++) {
- mf = GETMYFIELD(cfield[i]);
- if (conf->form.enable_wchar) {
- items[i].value = (char*)wcsdup(mf->buf);
+ if (conf->form.value_wchar) {
+ apiitems[i].value = (char*)wcsdup(items[i].privwbuf);
} else {
- items[i].value = w2c(mf->buf);
+ apiitems[i].value = alloc_wstomb(items[i].privwbuf);
}
- if (items[i].value == NULL)
+ if (apiitems[i].value == NULL)
RETURN_ERROR("Cannot allocate memory for form value");
}
return (output);
}
-static int
-form_handler(struct bsddialog_conf *conf, WINDOW *widget, struct buttons bs,
- WINDOW *formwin, FORM *form, FIELD **cfield, int nitems,
- struct bsddialog_formitem *items)
+static unsigned int firstitem(unsigned int nitems, struct privateitem *items)
{
- bool loop, buttupdate, informwin;
- int i, chtype, output;
- wint_t input;
- struct myfield *mf;
+ int i;
- mf = GETMYFIELD2(form);
- print_bottomdesc(mf);
- pos_form_cursor(form);
- form_driver_w(form, KEY_CODE_YES, REQ_END_LINE);
- mf->pos = MIN(mf->buflen, mf->maxpos);
- curs_set(1);
- informwin = true;
+ for (i = 0; i < (int)nitems; i++)
+ if (items[i].readonly == false)
+ break;
- bs.curr = -1;
- buttupdate = true;
+ return (i);
+}
- loop = true;
- while (loop) {
- if (buttupdate) {
- draw_buttons(widget, bs, !informwin);
- wrefresh(widget);
- buttupdate = false;
- }
- wrefresh(formwin);
- chtype = get_wch(&input);
- if (chtype != KEY_CODE_YES && input > 127 &&
- conf->form.enable_wchar == false)